diff options
77 files changed, 995 insertions, 308 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 9040b071b1a..2187ca1cf85 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -34,11 +34,6 @@ import org.sonar.plugins.core.dashboards.ProjectIssuesDashboard; import org.sonar.plugins.core.dashboards.ProjectTimeMachineDashboard; import org.sonar.plugins.core.issue.CountFalsePositivesDecorator; import org.sonar.plugins.core.issue.CountUnresolvedIssuesDecorator; -import org.sonar.plugins.core.issue.InitialOpenIssuesSensor; -import org.sonar.plugins.core.issue.InitialOpenIssuesStack; -import org.sonar.plugins.core.issue.IssueHandlers; -import org.sonar.plugins.core.issue.IssueTracking; -import org.sonar.plugins.core.issue.IssueTrackingDecorator; import org.sonar.plugins.core.measurefilters.MyFavouritesFilter; import org.sonar.plugins.core.measurefilters.ProjectFilter; import org.sonar.plugins.core.notifications.alerts.NewAlerts; @@ -325,13 +320,8 @@ public final class CorePlugin extends SonarPlugin { DistributionAreaChart.class, // issues - IssueTrackingDecorator.class, - IssueTracking.class, - IssueHandlers.class, CountUnresolvedIssuesDecorator.class, CountFalsePositivesDecorator.class, - InitialOpenIssuesSensor.class, - InitialOpenIssuesStack.class, HotspotMostViolatedRulesWidget.class, MyUnresolvedIssuesWidget.class, FalsePositiveIssuesWidget.class, diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java index 886104c14a0..01973adef97 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/CreateIssueByInternalKeySensor.java @@ -19,7 +19,10 @@ */ package org.sonar.xoo.rule; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFile.Type; import org.sonar.api.batch.rule.ActiveRule; import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.SensorContext; @@ -40,7 +43,9 @@ public class CreateIssueByInternalKeySensor implements Sensor { @Override public void execute(SensorContext context) { - for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) { + FileSystem fs = context.fileSystem(); + FilePredicates p = fs.predicates(); + for (InputFile file : fs.inputFiles(p.and(p.hasLanguages(Xoo.KEY), p.hasType(Type.MAIN)))) { createIssues(file, context); } } diff --git a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java index 3e0b9f48ee5..7e79e2857f6 100644 --- a/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java +++ b/plugins/sonar-xoo-plugin/src/main/java/org/sonar/xoo/rule/OneIssuePerLineSensor.java @@ -19,7 +19,10 @@ */ package org.sonar.xoo.rule; +import org.sonar.api.batch.fs.FilePredicates; +import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputFile.Type; import org.sonar.api.batch.sensor.Sensor; import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.SensorDescriptor; @@ -43,7 +46,9 @@ public class OneIssuePerLineSensor implements Sensor { @Override public void execute(SensorContext context) { - for (InputFile file : context.fileSystem().inputFiles(context.fileSystem().predicates().hasLanguages(Xoo.KEY))) { + FileSystem fs = context.fileSystem(); + FilePredicates p = fs.predicates(); + for (InputFile file : fs.inputFiles(p.and(p.hasLanguages(Xoo.KEY), p.hasType(Type.MAIN)))) { createIssues(file, context); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java index 9f87aa9ad1f..a6a40efbc45 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryAction.java @@ -25,7 +25,7 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.RequestHandler; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import org.sonar.server.plugins.MimeTypes; public class ProjectRepositoryAction implements RequestHandler { @@ -67,7 +67,7 @@ public class ProjectRepositoryAction implements RequestHandler { @Override public void handle(Request request, Response response) throws Exception { - ProjectReferentials ref = projectReferentialsLoader.load(ProjectRepositoryQuery.create() + ProjectRepository ref = projectReferentialsLoader.load(ProjectRepositoryQuery.create() .setModuleKey(request.mandatoryParam(PARAM_KEY)) .setProfileName(request.param(PARAM_PROFILE)) .setPreview(request.mandatoryParamAsBoolean(PARAM_PREVIEW))); diff --git a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java index 90d0151b79c..deea4177e33 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/batch/ProjectRepositoryLoader.java @@ -28,7 +28,7 @@ import org.sonar.api.resources.Language; import org.sonar.api.resources.Languages; import org.sonar.api.rule.RuleKey; import org.sonar.batch.protocol.input.FileData; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import org.sonar.core.UtcDateUtils; import org.sonar.core.component.ComponentDto; import org.sonar.core.component.FilePathWithHashDto; @@ -77,13 +77,13 @@ public class ProjectRepositoryLoader implements ServerComponent { this.languages = languages; } - public ProjectReferentials load(ProjectRepositoryQuery query) { + public ProjectRepository load(ProjectRepositoryQuery query) { boolean hasScanPerm = UserSession.get().hasGlobalPermission(GlobalPermissions.SCAN_EXECUTION); checkPermission(query.isPreview()); DbSession session = dbClient.openSession(false); try { - ProjectReferentials ref = new ProjectReferentials(); + ProjectRepository ref = new ProjectRepository(); String projectKey = query.getModuleKey(); ComponentDto module = dbClient.componentDao().getNullableByKey(session, query.getModuleKey()); // Current project/module can be null when analysing a new project @@ -145,7 +145,7 @@ public class ProjectRepositoryLoader implements ServerComponent { } } - private void addSettingsToChildrenModules(ProjectReferentials ref, String moduleKey, Map<String, String> parentProperties, TreeModuleSettings treeModuleSettings, + private void addSettingsToChildrenModules(ProjectRepository ref, String moduleKey, Map<String, String> parentProperties, TreeModuleSettings treeModuleSettings, boolean hasScanPerm, DbSession session) { Map<String, String> currentParentProperties = newHashMap(); currentParentProperties.putAll(parentProperties); @@ -158,7 +158,7 @@ public class ProjectRepositoryLoader implements ServerComponent { } } - private void addSettings(ProjectReferentials ref, String module, Map<String, String> properties) { + private void addSettings(ProjectRepository ref, String module, Map<String, String> properties) { if (!properties.isEmpty()) { ref.addSettings(module, properties); } @@ -180,7 +180,7 @@ public class ProjectRepositoryLoader implements ServerComponent { return !key.contains(".secured") || hasScanPerm; } - private void addProfiles(ProjectReferentials ref, @Nullable String projectKey, @Nullable String profileName, DbSession session) { + private void addProfiles(ProjectRepository ref, @Nullable String projectKey, @Nullable String profileName, DbSession session) { for (Language language : languages.all()) { String languageKey = language.getKey(); QualityProfileDto qualityProfileDto = getProfile(languageKey, projectKey, profileName, session); @@ -212,7 +212,7 @@ public class ProjectRepositoryLoader implements ServerComponent { } } - private void addActiveRules(ProjectReferentials ref) { + private void addActiveRules(ProjectRepository ref) { for (org.sonar.batch.protocol.input.QProfile qProfile : ref.qProfiles()) { for (ActiveRule activeRule : qProfileLoader.findActiveRulesByProfile(qProfile.key())) { Rule rule = ruleService.getNonNullByKey(activeRule.key().ruleKey()); @@ -231,7 +231,7 @@ public class ProjectRepositoryLoader implements ServerComponent { } } - private void addManualRules(ProjectReferentials ref) { + private void addManualRules(ProjectRepository ref) { Result<Rule> ruleSearchResult = ruleService.search(new RuleQuery().setRepositories(newArrayList(RuleKey.MANUAL_REPOSITORY_KEY)), new QueryContext().setScroll(true) .setFieldsToReturn(newArrayList(RuleNormalizer.RuleField.KEY.field(), RuleNormalizer.RuleField.NAME.field()))); Iterator<Rule> rules = ruleSearchResult.scroll(); @@ -245,7 +245,7 @@ public class ProjectRepositoryLoader implements ServerComponent { } } - private void addFileData(DbSession session, ProjectReferentials ref, List<ComponentDto> moduleChildren, String moduleKey) { + private void addFileData(DbSession session, ProjectRepository ref, List<ComponentDto> moduleChildren, String moduleKey) { Map<String, String> moduleKeysByUuid = newHashMap(); for (ComponentDto module : moduleChildren) { moduleKeysByUuid.put(module.uuid(), module.key()); diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryActionTest.java index 4dd4ae8e46f..97085c32ad9 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryActionTest.java @@ -26,7 +26,7 @@ import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import org.sonar.server.ws.WsTester; import static org.assertj.core.api.Assertions.assertThat; @@ -51,7 +51,7 @@ public class ProjectRepositoryActionTest { public void project_referentials() throws Exception { String projectKey = "org.codehaus.sonar:sonar"; - ProjectReferentials projectReferentials = mock(ProjectReferentials.class); + ProjectRepository projectReferentials = mock(ProjectRepository.class); when(projectReferentials.toJson()).thenReturn("{\"settingsByModule\": {}}"); ArgumentCaptor<ProjectRepositoryQuery> queryArgumentCaptor = ArgumentCaptor.forClass(ProjectRepositoryQuery.class); diff --git a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java index 5726333c222..0b3ed071d82 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/batch/ProjectRepositoryLoaderMediumTest.java @@ -31,7 +31,7 @@ import org.sonar.api.server.rule.RuleParamType; import org.sonar.api.utils.DateUtils; import org.sonar.batch.protocol.input.ActiveRule; import org.sonar.batch.protocol.input.FileData; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import org.sonar.batch.protocol.input.QProfile; import org.sonar.core.component.ComponentDto; import org.sonar.core.permission.GlobalPermissions; @@ -99,7 +99,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession); dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); Map<String, String> projectSettings = ref.settings(project.key()); assertThat(projectSettings).isEqualTo(ImmutableMap.of( "sonar.jira.project.key", "SONAR", @@ -124,7 +124,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession); dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key()).setPreview(true)); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key()).setPreview(true)); Map<String, String> projectSettings = ref.settings(project.key()); assertThat(projectSettings).isEqualTo(ImmutableMap.of( "sonar.jira.project.key", "SONAR" @@ -156,7 +156,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( "sonar.jira.project.key", "SONAR", "sonar.jira.login.secured", "john" @@ -189,7 +189,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( "sonar.jira.project.key", "SONAR", "sonar.jira.login.secured", "john" @@ -232,7 +232,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( "sonar.jira.project.key", "SONAR", "sonar.jira.login.secured", "john" @@ -278,7 +278,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( "sonar.jira.project.key", "SONAR", "sonar.jira.login.secured", "john" @@ -295,6 +295,28 @@ public class ProjectRepositoryLoaderMediumTest { } @Test + public void return_provisioned_project_settings() throws Exception { + MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + + // No snapshot attached on the project -> provisioned project + ComponentDto project = ComponentTesting.newProjectDto(); + tester.get(DbClient.class).componentDao().insert(dbSession, project); + addDefaultProfile(); + + // Project properties + tester.get(DbClient.class).propertiesDao().setProperty(new PropertyDto().setKey("sonar.jira.project.key").setValue("SONAR").setResourceId(project.getId()), dbSession); + tester.get(DbClient.class).propertiesDao().setProperty(new PropertyDto().setKey("sonar.jira.login.secured").setValue("john").setResourceId(project.getId()), dbSession); + + dbSession.commit(); + + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + assertThat(ref.settings(project.key())).isEqualTo(ImmutableMap.of( + "sonar.jira.project.key", "SONAR", + "sonar.jira.login.secured", "john" + )); + } + + @Test public void return_sub_module_settings() throws Exception { MockUserSession.set().setLogin("john").setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); @@ -317,7 +339,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); assertThat(ref.settings(project.key())).isEmpty(); assertThat(ref.settings(module.key())).isEmpty(); assertThat(ref.settings(subModule.key())).isEqualTo(ImmutableMap.of( @@ -352,7 +374,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); assertThat(ref.settings(project.key())).isEmpty(); assertThat(ref.settings(module.key())).isEmpty(); assertThat(ref.settings(subModule.key())).isEqualTo(ImmutableMap.of( @@ -385,7 +407,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); assertThat(ref.settings(project.key())).isEmpty(); assertThat(ref.settings(module.key())).isEmpty(); assertThat(ref.settings(subModule.key())).isEqualTo(ImmutableMap.of( @@ -419,7 +441,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(subModule.key())); assertThat(ref.settings(project.key())).isEmpty(); assertThat(ref.settings(module.key())).isEmpty(); assertThat(ref.settings(subModule.key())).isEqualTo(ImmutableMap.of( @@ -444,7 +466,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); List<QProfile> profiles = newArrayList(ref.qProfiles()); assertThat(profiles).hasSize(1); assertThat(profiles.get(0).key()).isEqualTo("abcd"); @@ -468,7 +490,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); List<QProfile> profiles = newArrayList(ref.qProfiles()); assertThat(profiles).hasSize(1); assertThat(profiles.get(0).key()).isEqualTo("abcd"); @@ -492,7 +514,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key()).setProfileName("SonarQube way")); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key()).setProfileName("SonarQube way")); List<QProfile> profiles = newArrayList(ref.qProfiles()); assertThat(profiles).hasSize(1); assertThat(profiles.get(0).key()).isEqualTo("abcd"); @@ -513,7 +535,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey("project")); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey("project")); List<QProfile> profiles = newArrayList(ref.qProfiles()); assertThat(profiles).hasSize(1); assertThat(profiles.get(0).key()).isEqualTo("abcd"); @@ -538,7 +560,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); List<QProfile> profiles = newArrayList(ref.qProfiles()); assertThat(profiles).hasSize(1); assertThat(profiles.get(0).key()).isEqualTo("abcd"); @@ -589,7 +611,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); List<ActiveRule> activeRules = newArrayList(ref.activeRules()); assertThat(activeRules).hasSize(1); assertThat(activeRules.get(0).repositoryKey()).isEqualTo("squid"); @@ -614,7 +636,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); List<ActiveRule> activeRules = newArrayList(ref.activeRules()); assertThat(activeRules).extracting("repositoryKey").containsOnly(RuleKey.MANUAL_REPOSITORY_KEY); assertThat(activeRules).extracting("ruleKey").containsOnly("manualRuleKey"); @@ -671,7 +693,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); assertThat(ref.fileDataByPath(project.key())).hasSize(1); FileData fileData = ref.fileData(project.key(), file.path()); assertThat(fileData.hash()).isEqualTo("123456"); @@ -700,7 +722,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(project.key())); assertThat(ref.fileData(project.key(), projectFile.path()).hash()).isEqualTo("123456"); assertThat(ref.fileData(module.key(), moduleFile.path()).hash()).isEqualTo("789456"); } @@ -728,7 +750,7 @@ public class ProjectRepositoryLoaderMediumTest { dbSession.commit(); - ProjectReferentials ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(module.key())); + ProjectRepository ref = loader.load(ProjectRepositoryQuery.create().setModuleKey(module.key())); assertThat(ref.fileData(module.key(), moduleFile.path()).hash()).isEqualTo("789456"); assertThat(ref.fileData(project.key(), projectFile.path())).isNull(); } diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectReferentials.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepository.java index 8e83d0fabf5..f207a34d989 100644 --- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectReferentials.java +++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepository.java @@ -30,7 +30,7 @@ import java.util.*; * Container for all project data going from server to batch. * This is not an API since server and batch always share the same version. */ -public class ProjectReferentials { +public class ProjectRepository { private long timestamp; private Map<String, QProfile> qprofilesByLanguage = new HashMap<String, QProfile>(); @@ -43,7 +43,7 @@ public class ProjectReferentials { return settingsByModule.containsKey(moduleKey) ? settingsByModule.get(moduleKey) : Collections.<String, String>emptyMap(); } - public ProjectReferentials addSettings(String moduleKey, Map<String, String> settings) { + public ProjectRepository addSettings(String moduleKey, Map<String, String> settings) { Map<String, String> existingSettings = settingsByModule.get(moduleKey); if (existingSettings == null) { existingSettings = new HashMap<>(); @@ -57,7 +57,7 @@ public class ProjectReferentials { return qprofilesByLanguage.values(); } - public ProjectReferentials addQProfile(QProfile qProfile) { + public ProjectRepository addQProfile(QProfile qProfile) { qprofilesByLanguage.put(qProfile.language(), qProfile); return this; } @@ -66,7 +66,7 @@ public class ProjectReferentials { return activeRules; } - public ProjectReferentials addActiveRule(ActiveRule activeRule) { + public ProjectRepository addActiveRule(ActiveRule activeRule) { activeRules.add(activeRule); return this; } @@ -75,7 +75,7 @@ public class ProjectReferentials { return fileDataByModuleAndPath.containsKey(moduleKey) ? fileDataByModuleAndPath.get(moduleKey) : Collections.<String, FileData>emptyMap(); } - public ProjectReferentials addFileData(String moduleKey, String path, FileData fileData) { + public ProjectRepository addFileData(String moduleKey, String path, FileData fileData) { Map<String, FileData> existingFileDataByPath = fileDataByModuleAndPath.get(moduleKey); if (existingFileDataByPath == null) { existingFileDataByPath = new HashMap<>(); @@ -111,8 +111,8 @@ public class ProjectReferentials { return GsonHelper.create().toJson(this); } - public static ProjectReferentials fromJson(String json) { - return GsonHelper.create().fromJson(json, ProjectReferentials.class); + public static ProjectRepository fromJson(String json) { + return GsonHelper.create().fromJson(json, ProjectRepository.class); } } diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssue.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssue.java index 27afc945c29..10f44f1e390 100644 --- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssue.java +++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssue.java @@ -19,10 +19,11 @@ */ package org.sonar.batch.protocol.input.issues; -import javax.annotation.CheckForNull; import javax.annotation.Nullable; -public class PreviousIssue { +import java.io.Serializable; + +public class PreviousIssue implements Serializable { private String key; private String componentKey; @@ -30,6 +31,7 @@ public class PreviousIssue { private String ruleRepo; private Integer line; private String message; + // For manual issues and when user has overriden severity private String overriddenSeverity; private String resolution; private String status; @@ -45,7 +47,7 @@ public class PreviousIssue { return key; } - public PreviousIssue setComponentKey(@Nullable String key) { + public PreviousIssue setComponentKey(String key) { this.componentKey = key; return this; } @@ -95,7 +97,6 @@ public class PreviousIssue { return this; } - @CheckForNull public String overriddenSeverity() { return overriddenSeverity; } diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssueHelper.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssueHelper.java index 14e4e4a3785..056b0077eea 100644 --- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssueHelper.java +++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/issues/PreviousIssueHelper.java @@ -70,7 +70,7 @@ public class PreviousIssueHelper implements Closeable { } } - public Iterable<PreviousIssue> getIssues(final Reader reader) { + public static Iterable<PreviousIssue> getIssues(final Reader reader) { return new Iterable<PreviousIssue>() { @Override @@ -80,9 +80,10 @@ public class PreviousIssueHelper implements Closeable { }; } - private final class PreviousIssueIterator implements Iterator<PreviousIssue> { + private final static class PreviousIssueIterator implements Iterator<PreviousIssue> { private JsonReader jsonreader; + private final Gson gson = GsonHelper.create(); public PreviousIssueIterator(Reader reader) { try { diff --git a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectReferentialsTest.java b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoryTest.java index 348fcd8187f..d60222b455a 100644 --- a/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectReferentialsTest.java +++ b/sonar-batch-protocol/src/test/java/org/sonar/batch/protocol/input/ProjectRepositoryTest.java @@ -29,11 +29,11 @@ import java.util.HashMap; import static org.assertj.core.api.Assertions.assertThat; -public class ProjectReferentialsTest { +public class ProjectRepositoryTest { @Test public void testToJson() throws Exception { - ProjectReferentials ref = new ProjectReferentials(); + ProjectRepository ref = new ProjectRepository(); assertThat(ref.settings("foo")).isEmpty(); ref.addQProfile(new QProfile("squid-java", "Java", "java", new SimpleDateFormat("dd/MM/yyyy").parse("14/03/1984"))); @@ -66,7 +66,7 @@ public class ProjectReferentialsTest { @Test public void testFromJson() throws JSONException, ParseException { - ProjectReferentials ref = ProjectReferentials + ProjectRepository ref = ProjectRepository .fromJson("{timestamp:1," + "qprofilesByLanguage:{java:{key:\"squid-java\",name:Java,language:java,rulesUpdatedAt:\"1984-03-14T00:00:00+0100\"}}," + "activeRules:[{repositoryKey:repo,ruleKey:rule,name:Rule,severity:MAJOR,internalKey:rule1,language:java,params:{param1:value1}}]," diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java index 333a041f13f..dca499c6869 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchComponents.java @@ -26,6 +26,7 @@ import org.sonar.batch.design.FileTangleIndexDecorator; import org.sonar.batch.design.MavenDependenciesSensor; import org.sonar.batch.design.ProjectDsmDecorator; import org.sonar.batch.design.SubProjectDsmDecorator; +import org.sonar.batch.issue.tracking.IssueTracking; import org.sonar.batch.maven.DefaultMavenPluginExecutor; import org.sonar.batch.maven.MavenProjectBootstrapper; import org.sonar.batch.maven.MavenProjectBuilder; @@ -66,6 +67,9 @@ public class BatchComponents { LinesSensor.class, + // Issues tracking + IssueTracking.class, + // Reports ConsoleReport.class, JSONReport.class, diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java index 75071b09ef1..d3749c4cf7f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java @@ -35,11 +35,13 @@ import org.sonar.batch.components.PastSnapshotFinderByDays; import org.sonar.batch.components.PastSnapshotFinderByPreviousAnalysis; import org.sonar.batch.components.PastSnapshotFinderByPreviousVersion; import org.sonar.batch.components.PastSnapshotFinderByVersion; -import org.sonar.batch.referential.DefaultGlobalReferentialsLoader; -import org.sonar.batch.referential.DefaultProjectReferentialsLoader; -import org.sonar.batch.referential.GlobalReferentialsLoader; -import org.sonar.batch.referential.GlobalReferentialsProvider; -import org.sonar.batch.referential.ProjectReferentialsLoader; +import org.sonar.batch.repository.DefaultGlobalReferentialsLoader; +import org.sonar.batch.repository.DefaultPreviousIssuesLoader; +import org.sonar.batch.repository.DefaultProjectReferentialsLoader; +import org.sonar.batch.repository.GlobalReferentialsLoader; +import org.sonar.batch.repository.GlobalReferentialsProvider; +import org.sonar.batch.repository.PreviousIssuesLoader; +import org.sonar.batch.repository.ProjectRepositoriesLoader; import org.sonar.batch.user.UserRepository; import org.sonar.core.cluster.NullQueue; import org.sonar.core.config.Logback; @@ -113,9 +115,12 @@ public class BootstrapContainer extends ComponentContainer { if (getComponentByType(GlobalReferentialsLoader.class) == null) { add(DefaultGlobalReferentialsLoader.class); } - if (getComponentByType(ProjectReferentialsLoader.class) == null) { + if (getComponentByType(ProjectRepositoriesLoader.class) == null) { add(DefaultProjectReferentialsLoader.class); } + if (getComponentByType(PreviousIssuesLoader.class) == null) { + add(DefaultPreviousIssuesLoader.class); + } } private void addDatabaseComponents() { diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java index 470f0f79686..3b53ae97c19 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java @@ -103,7 +103,7 @@ public class ServerClient implements BatchComponent { } } - private InputSupplier<InputStream> doRequest(String pathStartingWithSlash, String requestMethod, @Nullable Integer timeoutMillis) { + public InputSupplier<InputStream> doRequest(String pathStartingWithSlash, String requestMethod, @Nullable Integer timeoutMillis) { Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /"); String path = StringEscapeUtils.escapeHtml(pathStartingWithSlash); diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java index afa2ed7fee3..4a97a6c8ab8 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/ResourceCache.java @@ -38,6 +38,8 @@ public class ResourceCache implements BatchComponent { // dedicated cache for libraries private final Map<Library, BatchResource> libraries = Maps.newLinkedHashMap(); + private BatchResource root; + @CheckForNull public BatchResource get(String componentKey) { return resources.get(componentKey); @@ -56,10 +58,13 @@ public class ResourceCache implements BatchComponent { String componentKey = resource.getEffectiveKey(); Preconditions.checkState(!Strings.isNullOrEmpty(componentKey), "Missing resource effective key"); BatchResource parent = parentResource != null ? get(parentResource.getEffectiveKey()) : null; - BatchResource batchResource = new BatchResource((long) resources.size() + 1, resource, parent); + BatchResource batchResource = new BatchResource(resources.size() + 1, resource, parent); if (!(resource instanceof Library)) { // Libraries can have the same effective key than a project so we can't cache by effectiveKey resources.put(componentKey, batchResource); + if (parent == null) { + root = batchResource; + } } else { libraries.put((Library) resource, batchResource); } @@ -73,4 +78,8 @@ public class ResourceCache implements BatchComponent { public Collection<BatchResource> allLibraries() { return libraries.values(); } + + public BatchResource getRoot() { + return root; + } } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/FileHashes.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/FileHashes.java index d45ac2d65cc..49b0405787b 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/FileHashes.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/FileHashes.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue.tracking; +package org.sonar.batch.issue.tracking; import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensor.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensor.java index 17f22757db8..a58f5c93a80 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensor.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import org.apache.commons.lang.time.DateUtils; import org.apache.ibatis.session.ResultContext; @@ -25,6 +25,7 @@ import org.apache.ibatis.session.ResultHandler; import org.sonar.api.batch.Sensor; import org.sonar.api.batch.SensorContext; import org.sonar.api.resources.Project; +import org.sonar.core.DryRunIncompatible; import org.sonar.core.issue.db.IssueChangeDao; import org.sonar.core.issue.db.IssueChangeDto; import org.sonar.core.issue.db.IssueDao; @@ -36,6 +37,7 @@ import java.util.Date; /** * Load all the issues referenced during the previous scan. */ +@DryRunIncompatible public class InitialOpenIssuesSensor implements Sensor { private final InitialOpenIssuesStack initialOpenIssuesStack; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesStack.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStack.java index 1d6f3592547..acc9ebf21b8 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/InitialOpenIssuesStack.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStack.java @@ -18,9 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; -import java.util.Collections; import org.sonar.api.BatchExtension; import org.sonar.api.batch.InstantiationStrategy; import org.sonar.batch.index.Cache; @@ -29,6 +28,7 @@ import org.sonar.core.issue.db.IssueChangeDto; import org.sonar.core.issue.db.IssueDto; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import static com.google.common.collect.Lists.newArrayList; @@ -49,11 +49,11 @@ public class InitialOpenIssuesStack implements BatchExtension { return this; } - public List<IssueDto> selectAndRemoveIssues(String componentKey) { + public List<PreviousIssue> selectAndRemoveIssues(String componentKey) { Iterable<IssueDto> issues = issuesCache.values(componentKey); - List<IssueDto> result = newArrayList(); + List<PreviousIssue> result = newArrayList(); for (IssueDto issue : issues) { - result.add(issue); + result.add(new PreviousIssueFromDb(issue)); } issuesCache.clear(componentKey); return result; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueHandlers.java index d416b57f061..f8a98c29b00 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueHandlers.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import org.sonar.api.BatchExtension; import org.sonar.api.issue.Issue; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTracking.java index da4059eeb0d..2c1c49afa97 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTracking.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTracking.java @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Objects; @@ -26,13 +26,9 @@ import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Multimap; -import org.sonar.api.BatchExtension; +import org.sonar.api.BatchComponent; +import org.sonar.api.batch.InstantiationStrategy; import org.sonar.api.issue.internal.DefaultIssue; -import org.sonar.api.rule.RuleKey; -import org.sonar.core.issue.db.IssueDto; -import org.sonar.plugins.core.issue.tracking.FileHashes; -import org.sonar.plugins.core.issue.tracking.IssueTrackingBlocksRecognizer; -import org.sonar.plugins.core.issue.tracking.RollingFileHashes; import javax.annotation.Nullable; @@ -42,12 +38,13 @@ import java.util.Comparator; import java.util.List; import java.util.Map; -public class IssueTracking implements BatchExtension { +@InstantiationStrategy(InstantiationStrategy.PER_BATCH) +public class IssueTracking implements BatchComponent { /** * @param sourceHashHolder Null when working on resource that is not a file (directory/project) */ - public IssueTrackingResult track(@Nullable SourceHashHolder sourceHashHolder, Collection<IssueDto> dbIssues, Collection<DefaultIssue> newIssues) { + public IssueTrackingResult track(@Nullable SourceHashHolder sourceHashHolder, Collection<PreviousIssue> previousIssues, Collection<DefaultIssue> newIssues) { IssueTrackingResult result = new IssueTrackingResult(); if (sourceHashHolder != null) { @@ -55,7 +52,7 @@ public class IssueTracking implements BatchExtension { } // Map new issues with old ones - mapIssues(newIssues, dbIssues, sourceHashHolder, result); + mapIssues(newIssues, previousIssues, sourceHashHolder, result); return result; } @@ -72,12 +69,12 @@ public class IssueTracking implements BatchExtension { } @VisibleForTesting - void mapIssues(Collection<DefaultIssue> newIssues, @Nullable Collection<IssueDto> lastIssues, @Nullable SourceHashHolder sourceHashHolder, IssueTrackingResult result) { + void mapIssues(Collection<DefaultIssue> newIssues, @Nullable Collection<PreviousIssue> previousIssues, @Nullable SourceHashHolder sourceHashHolder, IssueTrackingResult result) { boolean hasLastScan = false; - if (lastIssues != null) { + if (previousIssues != null) { hasLastScan = true; - mapLastIssues(newIssues, lastIssues, result); + mapLastIssues(newIssues, previousIssues, result); } // If each new issue matches an old one we can stop the matching mechanism @@ -92,8 +89,8 @@ public class IssueTracking implements BatchExtension { } } - private void mapLastIssues(Collection<DefaultIssue> newIssues, Collection<IssueDto> lastIssues, IssueTrackingResult result) { - for (IssueDto lastIssue : lastIssues) { + private void mapLastIssues(Collection<DefaultIssue> newIssues, Collection<PreviousIssue> previousIssues, IssueTrackingResult result) { + for (PreviousIssue lastIssue : previousIssues) { result.addUnmatched(lastIssue); } @@ -121,7 +118,7 @@ public class IssueTracking implements BatchExtension { RollingFileHashes b = RollingFileHashes.create(hashedSource, 5); Multimap<Integer, DefaultIssue> newIssuesByLines = newIssuesByLines(newIssues, rec, result); - Multimap<Integer, IssueDto> lastIssuesByLines = lastIssuesByLines(result.unmatched(), rec); + Multimap<Integer, PreviousIssue> lastIssuesByLines = lastIssuesByLines(result.unmatched(), rec); Map<Integer, HashOccurrence> map = Maps.newHashMap(); @@ -207,12 +204,12 @@ public class IssueTracking implements BatchExtension { } } - private void map(Collection<DefaultIssue> newIssues, Collection<IssueDto> lastIssues, IssueTrackingResult result) { + private void map(Collection<DefaultIssue> newIssues, Collection<PreviousIssue> previousIssues, IssueTrackingResult result) { for (DefaultIssue newIssue : newIssues) { if (isNotAlreadyMapped(newIssue, result)) { - for (IssueDto pastIssue : lastIssues) { - if (isNotAlreadyMapped(pastIssue, result) && Objects.equal(newIssue.ruleKey(), RuleKey.of(pastIssue.getRuleRepo(), pastIssue.getRule()))) { - mapIssue(newIssue, pastIssue, result); + for (PreviousIssue previousIssue : previousIssues) { + if (isNotAlreadyMapped(previousIssue, result) && Objects.equal(newIssue.ruleKey(), previousIssue.ruleKey())) { + mapIssue(newIssue, previousIssue, result); break; } } @@ -230,72 +227,72 @@ public class IssueTracking implements BatchExtension { return newIssuesByLines; } - private Multimap<Integer, IssueDto> lastIssuesByLines(Collection<IssueDto> lastIssues, IssueTrackingBlocksRecognizer rec) { - Multimap<Integer, IssueDto> lastIssuesByLines = LinkedHashMultimap.create(); - for (IssueDto pastIssue : lastIssues) { - if (rec.isValidLineInReference(pastIssue.getLine())) { - lastIssuesByLines.put(pastIssue.getLine(), pastIssue); + private Multimap<Integer, PreviousIssue> lastIssuesByLines(Collection<PreviousIssue> previousIssues, IssueTrackingBlocksRecognizer rec) { + Multimap<Integer, PreviousIssue> previousIssuesByLines = LinkedHashMultimap.create(); + for (PreviousIssue previousIssue : previousIssues) { + if (rec.isValidLineInReference(previousIssue.line())) { + previousIssuesByLines.put(previousIssue.line(), previousIssue); } } - return lastIssuesByLines; + return previousIssuesByLines; } - private IssueDto findLastIssueWithSameChecksum(DefaultIssue newIssue, Collection<IssueDto> lastIssues) { - for (IssueDto pastIssue : lastIssues) { - if (isSameChecksum(newIssue, pastIssue)) { - return pastIssue; + private PreviousIssue findLastIssueWithSameChecksum(DefaultIssue newIssue, Collection<PreviousIssue> previousIssues) { + for (PreviousIssue previousIssue : previousIssues) { + if (isSameChecksum(newIssue, previousIssue)) { + return previousIssue; } } return null; } - private IssueDto findLastIssueWithSameLineAndMessage(DefaultIssue newIssue, Collection<IssueDto> lastIssues) { - for (IssueDto pastIssue : lastIssues) { - if (isSameLine(newIssue, pastIssue) && isSameMessage(newIssue, pastIssue)) { - return pastIssue; + private PreviousIssue findLastIssueWithSameLineAndMessage(DefaultIssue newIssue, Collection<PreviousIssue> previousIssues) { + for (PreviousIssue previousIssue : previousIssues) { + if (isSameLine(newIssue, previousIssue) && isSameMessage(newIssue, previousIssue)) { + return previousIssue; } } return null; } - private IssueDto findLastIssueWithSameChecksumAndMessage(DefaultIssue newIssue, Collection<IssueDto> lastIssues) { - for (IssueDto pastIssue : lastIssues) { - if (isSameChecksum(newIssue, pastIssue) && isSameMessage(newIssue, pastIssue)) { - return pastIssue; + private PreviousIssue findLastIssueWithSameChecksumAndMessage(DefaultIssue newIssue, Collection<PreviousIssue> previousIssues) { + for (PreviousIssue previousIssue : previousIssues) { + if (isSameChecksum(newIssue, previousIssue) && isSameMessage(newIssue, previousIssue)) { + return previousIssue; } } return null; } - private IssueDto findLastIssueWithSameLineAndChecksum(DefaultIssue newIssue, IssueTrackingResult result) { - Collection<IssueDto> sameRuleAndSameLineAndSameChecksum = result.unmatchedForRuleAndForLineAndForChecksum(newIssue.ruleKey(), newIssue.line(), newIssue.checksum()); + private PreviousIssue findLastIssueWithSameLineAndChecksum(DefaultIssue newIssue, IssueTrackingResult result) { + Collection<PreviousIssue> sameRuleAndSameLineAndSameChecksum = result.unmatchedForRuleAndForLineAndForChecksum(newIssue.ruleKey(), newIssue.line(), newIssue.checksum()); if (!sameRuleAndSameLineAndSameChecksum.isEmpty()) { return sameRuleAndSameLineAndSameChecksum.iterator().next(); } return null; } - private boolean isNotAlreadyMapped(IssueDto pastIssue, IssueTrackingResult result) { - return result.unmatched().contains(pastIssue); + private boolean isNotAlreadyMapped(PreviousIssue previousIssue, IssueTrackingResult result) { + return result.unmatched().contains(previousIssue); } private boolean isNotAlreadyMapped(DefaultIssue newIssue, IssueTrackingResult result) { return !result.isMatched(newIssue); } - private boolean isSameChecksum(DefaultIssue newIssue, IssueDto pastIssue) { - return Objects.equal(pastIssue.getChecksum(), newIssue.checksum()); + private boolean isSameChecksum(DefaultIssue newIssue, PreviousIssue previousIssue) { + return Objects.equal(previousIssue.checksum(), newIssue.checksum()); } - private boolean isSameLine(DefaultIssue newIssue, IssueDto pastIssue) { - return Objects.equal(pastIssue.getLine(), newIssue.line()); + private boolean isSameLine(DefaultIssue newIssue, PreviousIssue previousIssue) { + return Objects.equal(previousIssue.line(), newIssue.line()); } - private boolean isSameMessage(DefaultIssue newIssue, IssueDto pastIssue) { - return Objects.equal(newIssue.message(), pastIssue.getMessage()); + private boolean isSameMessage(DefaultIssue newIssue, PreviousIssue previousIssue) { + return Objects.equal(newIssue.message(), previousIssue.message()); } - private void mapIssue(DefaultIssue issue, @Nullable IssueDto ref, IssueTrackingResult result) { + private void mapIssue(DefaultIssue issue, @Nullable PreviousIssue ref, IssueTrackingResult result) { if (ref != null) { result.setMatch(issue, ref); } diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/IssueTrackingBlocksRecognizer.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingBlocksRecognizer.java index 11611ad952d..c7e01c9020d 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/IssueTrackingBlocksRecognizer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingBlocksRecognizer.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue.tracking; +package org.sonar.batch.issue.tracking; import javax.annotation.Nullable; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingDecorator.java index 3d2bfc48e9d..8bc86e35fa7 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingDecorator.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Strings; @@ -50,6 +50,7 @@ import org.sonar.api.utils.KeyValueFormat; import org.sonar.batch.issue.IssueCache; import org.sonar.batch.scan.LastLineHashes; import org.sonar.batch.scan.filesystem.InputPathCache; +import org.sonar.core.DryRunIncompatible; import org.sonar.core.issue.IssueUpdater; import org.sonar.core.issue.db.IssueChangeDto; import org.sonar.core.issue.db.IssueDto; @@ -59,6 +60,7 @@ import java.util.Collection; @DependsUpon(DecoratorBarriers.ISSUES_ADDED) @DependedUpon(DecoratorBarriers.ISSUES_TRACKED) +@DryRunIncompatible public class IssueTrackingDecorator implements Decorator { private static final Logger LOG = LoggerFactory.getLogger(IssueTrackingDecorator.class); @@ -123,7 +125,7 @@ public class IssueTrackingDecorator implements Decorator { // issues = all the issues created by rule engines during this module scan and not excluded by filters // all the issues that are not closed in db before starting this module scan, including manual issues - Collection<IssueDto> dbOpenIssues = initialOpenIssues.selectAndRemoveIssues(resource.getEffectiveKey()); + Collection<PreviousIssue> dbOpenIssues = initialOpenIssues.selectAndRemoveIssues(resource.getEffectiveKey()); SourceHashHolder sourceHashHolder = null; if (ResourceUtils.isFile(resource)) { @@ -157,7 +159,7 @@ public class IssueTrackingDecorator implements Decorator { @VisibleForTesting protected void mergeMatched(IssueTrackingResult result) { for (DefaultIssue issue : result.matched()) { - IssueDto ref = result.matching(issue); + IssueDto ref = ((PreviousIssueFromDb) result.matching(issue)).getDto(); // invariant fields issue.setKey(ref.getKee()); @@ -206,8 +208,9 @@ public class IssueTrackingDecorator implements Decorator { } } - private void addUnmatched(Collection<IssueDto> unmatchedIssues, SourceHashHolder sourceHashHolder, Collection<DefaultIssue> issues) { - for (IssueDto unmatchedDto : unmatchedIssues) { + private void addUnmatched(Collection<PreviousIssue> unmatchedIssues, SourceHashHolder sourceHashHolder, Collection<DefaultIssue> issues) { + for (PreviousIssue unmatchedIssue : unmatchedIssues) { + IssueDto unmatchedDto = ((PreviousIssueFromDb) unmatchedIssue).getDto(); DefaultIssue unmatched = unmatchedDto.toDefaultIssue(); if (StringUtils.isNotBlank(unmatchedDto.getReporter()) && !Issue.STATUS_CLOSED.equals(unmatchedDto.getStatus())) { relocateManualIssue(unmatched, unmatchedDto, sourceHashHolder); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingResult.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingResult.java index f63f94f8115..f7b4e8d119e 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingResult.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/IssueTrackingResult.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import com.google.common.collect.HashMultimap; import com.google.common.collect.Maps; @@ -25,7 +25,6 @@ import com.google.common.collect.Multimap; import org.apache.commons.lang.StringUtils; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rule.RuleKey; -import org.sonar.core.issue.db.IssueDto; import javax.annotation.Nullable; @@ -35,30 +34,29 @@ import java.util.HashMap; import java.util.Map; class IssueTrackingResult { - private final Map<String, IssueDto> unmatchedByKey = new HashMap<String, IssueDto>(); - private final Map<RuleKey, Map<String, IssueDto>> unmatchedByRuleAndKey = new HashMap<RuleKey, Map<String, IssueDto>>(); - private final Map<RuleKey, Map<Integer, Multimap<String, IssueDto>>> unmatchedByRuleAndLineAndChecksum = - new HashMap<RuleKey, Map<Integer, Multimap<String, IssueDto>>>(); - private final Map<DefaultIssue, IssueDto> matched = Maps.newIdentityHashMap(); + private final Map<String, PreviousIssue> unmatchedByKey = new HashMap<>(); + private final Map<RuleKey, Map<String, PreviousIssue>> unmatchedByRuleAndKey = new HashMap<>(); + private final Map<RuleKey, Map<Integer, Multimap<String, PreviousIssue>>> unmatchedByRuleAndLineAndChecksum = new HashMap<>(); + private final Map<DefaultIssue, PreviousIssue> matched = Maps.newIdentityHashMap(); - Collection<IssueDto> unmatched() { + Collection<PreviousIssue> unmatched() { return unmatchedByKey.values(); } - Map<String, IssueDto> unmatchedByKeyForRule(RuleKey ruleKey) { - return unmatchedByRuleAndKey.containsKey(ruleKey) ? unmatchedByRuleAndKey.get(ruleKey) : Collections.<String, IssueDto>emptyMap(); + Map<String, PreviousIssue> unmatchedByKeyForRule(RuleKey ruleKey) { + return unmatchedByRuleAndKey.containsKey(ruleKey) ? unmatchedByRuleAndKey.get(ruleKey) : Collections.<String, PreviousIssue>emptyMap(); } - Collection<IssueDto> unmatchedForRuleAndForLineAndForChecksum(RuleKey ruleKey, @Nullable Integer line, @Nullable String checksum) { + Collection<PreviousIssue> unmatchedForRuleAndForLineAndForChecksum(RuleKey ruleKey, @Nullable Integer line, @Nullable String checksum) { if (!unmatchedByRuleAndLineAndChecksum.containsKey(ruleKey)) { return Collections.emptyList(); } - Map<Integer, Multimap<String, IssueDto>> unmatchedForRule = unmatchedByRuleAndLineAndChecksum.get(ruleKey); + Map<Integer, Multimap<String, PreviousIssue>> unmatchedForRule = unmatchedByRuleAndLineAndChecksum.get(ruleKey); Integer lineNotNull = line != null ? line : 0; if (!unmatchedForRule.containsKey(lineNotNull)) { return Collections.emptyList(); } - Multimap<String, IssueDto> unmatchedForRuleAndLine = unmatchedForRule.get(lineNotNull); + Multimap<String, PreviousIssue> unmatchedForRuleAndLine = unmatchedForRule.get(lineNotNull); String checksumNotNull = StringUtils.defaultString(checksum, ""); if (!unmatchedForRuleAndLine.containsKey(checksumNotNull)) { return Collections.emptyList(); @@ -74,40 +72,40 @@ class IssueTrackingResult { return matched.containsKey(issue); } - IssueDto matching(DefaultIssue issue) { + PreviousIssue matching(DefaultIssue issue) { return matched.get(issue); } - void addUnmatched(IssueDto i) { - unmatchedByKey.put(i.getKee(), i); - RuleKey ruleKey = RuleKey.of(i.getRuleRepo(), i.getRule()); + void addUnmatched(PreviousIssue i) { + unmatchedByKey.put(i.key(), i); + RuleKey ruleKey = i.ruleKey(); if (!unmatchedByRuleAndKey.containsKey(ruleKey)) { - unmatchedByRuleAndKey.put(ruleKey, new HashMap<String, IssueDto>()); - unmatchedByRuleAndLineAndChecksum.put(ruleKey, new HashMap<Integer, Multimap<String, IssueDto>>()); + unmatchedByRuleAndKey.put(ruleKey, new HashMap<String, PreviousIssue>()); + unmatchedByRuleAndLineAndChecksum.put(ruleKey, new HashMap<Integer, Multimap<String, PreviousIssue>>()); } - unmatchedByRuleAndKey.get(ruleKey).put(i.getKee(), i); - Map<Integer, Multimap<String, IssueDto>> unmatchedForRule = unmatchedByRuleAndLineAndChecksum.get(ruleKey); + unmatchedByRuleAndKey.get(ruleKey).put(i.key(), i); + Map<Integer, Multimap<String, PreviousIssue>> unmatchedForRule = unmatchedByRuleAndLineAndChecksum.get(ruleKey); Integer lineNotNull = lineNotNull(i); if (!unmatchedForRule.containsKey(lineNotNull)) { - unmatchedForRule.put(lineNotNull, HashMultimap.<String, IssueDto>create()); + unmatchedForRule.put(lineNotNull, HashMultimap.<String, PreviousIssue>create()); } - Multimap<String, IssueDto> unmatchedForRuleAndLine = unmatchedForRule.get(lineNotNull); - String checksumNotNull = StringUtils.defaultString(i.getChecksum(), ""); + Multimap<String, PreviousIssue> unmatchedForRuleAndLine = unmatchedForRule.get(lineNotNull); + String checksumNotNull = StringUtils.defaultString(i.checksum(), ""); unmatchedForRuleAndLine.put(checksumNotNull, i); } - private Integer lineNotNull(IssueDto i) { - Integer line = i.getLine(); + private Integer lineNotNull(PreviousIssue i) { + Integer line = i.line(); return line != null ? line : 0; } - void setMatch(DefaultIssue issue, IssueDto matching) { + void setMatch(DefaultIssue issue, PreviousIssue matching) { matched.put(issue, matching); - RuleKey ruleKey = RuleKey.of(matching.getRuleRepo(), matching.getRule()); - unmatchedByRuleAndKey.get(ruleKey).remove(matching.getKee()); - unmatchedByKey.remove(matching.getKee()); + RuleKey ruleKey = matching.ruleKey(); + unmatchedByRuleAndKey.get(ruleKey).remove(matching.key()); + unmatchedByKey.remove(matching.key()); Integer lineNotNull = lineNotNull(matching); - String checksumNotNull = StringUtils.defaultString(matching.getChecksum(), ""); + String checksumNotNull = StringUtils.defaultString(matching.checksum(), ""); unmatchedByRuleAndLineAndChecksum.get(ruleKey).get(lineNotNull).get(checksumNotNull).remove(matching); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java new file mode 100644 index 00000000000..99542db8cb6 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java @@ -0,0 +1,227 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue.tracking; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import org.sonar.api.BatchComponent; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.rule.ActiveRule; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.internal.DefaultIssue; +import org.sonar.api.issue.internal.IssueChangeContext; +import org.sonar.api.resources.File; +import org.sonar.api.resources.Project; +import org.sonar.api.resources.ResourceUtils; +import org.sonar.api.rule.RuleKey; +import org.sonar.batch.index.BatchResource; +import org.sonar.batch.index.ResourceCache; +import org.sonar.batch.issue.IssueCache; +import org.sonar.batch.scan.LastLineHashes; +import org.sonar.batch.scan.filesystem.InputPathCache; +import org.sonar.core.issue.IssueUpdater; +import org.sonar.core.issue.workflow.IssueWorkflow; + +import java.util.ArrayList; +import java.util.Collection; + +public class LocalIssueTracking implements BatchComponent { + + private final IssueCache issueCache; + private final IssueTracking tracking; + private final LastLineHashes lastLineHashes; + private final IssueWorkflow workflow; + private final IssueUpdater updater; + private final IssueChangeContext changeContext; + private final ActiveRules activeRules; + private final InputPathCache inputPathCache; + private final ResourceCache resourceCache; + private final PreviousIssueRepository previousIssueCache; + + public LocalIssueTracking(ResourceCache resourceCache, IssueCache issueCache, IssueTracking tracking, + LastLineHashes lastLineHashes, IssueWorkflow workflow, IssueUpdater updater, + ActiveRules activeRules, InputPathCache inputPathCache, PreviousIssueRepository previousIssueCache) { + this.resourceCache = resourceCache; + this.issueCache = issueCache; + this.tracking = tracking; + this.lastLineHashes = lastLineHashes; + this.workflow = workflow; + this.updater = updater; + this.inputPathCache = inputPathCache; + this.previousIssueCache = previousIssueCache; + this.changeContext = IssueChangeContext.createScan(((Project) resourceCache.getRoot().resource()).getAnalysisDate()); + this.activeRules = activeRules; + } + + public void execute() { + previousIssueCache.load(); + + for (BatchResource component : resourceCache.all()) { + trackIssues(component); + } + } + + public void trackIssues(BatchResource component) { + + Collection<DefaultIssue> issues = Lists.newArrayList(); + for (Issue issue : issueCache.byComponent(component.resource().getEffectiveKey())) { + issues.add((DefaultIssue) issue); + } + issueCache.clear(component.resource().getEffectiveKey()); + // issues = all the issues created by rule engines during this module scan and not excluded by filters + + // all the issues that are not closed in db before starting this module scan, including manual issues + Collection<PreviousIssue> previousIssues = new ArrayList<>(); + for (org.sonar.batch.protocol.input.issues.PreviousIssue previousIssue : previousIssueCache.byComponent(component)) { + previousIssues.add(new PreviousIssueFromWs(previousIssue)); + } + + SourceHashHolder sourceHashHolder = null; + if (ResourceUtils.isFile(component.resource())) { + File sonarFile = (File) component.resource(); + InputFile file = inputPathCache.getFile(component.parent().parent().resource().getEffectiveKey(), sonarFile.getPath()); + if (file == null) { + throw new IllegalStateException("Resource " + component.resource() + " was not found in InputPath cache"); + } + sourceHashHolder = new SourceHashHolder((DefaultInputFile) file, lastLineHashes); + } + + IssueTrackingResult trackingResult = tracking.track(sourceHashHolder, previousIssues, issues); + + // unmatched = issues that have been resolved + issues on disabled/removed rules + manual issues + addUnmatched(trackingResult.unmatched(), sourceHashHolder, issues); + + mergeMatched(trackingResult); + + if (ResourceUtils.isRootProject(component.resource())) { + // issues that relate to deleted components + addIssuesOnDeletedComponents(issues); + } + + for (DefaultIssue issue : issues) { + workflow.doAutomaticTransition(issue, changeContext); + issueCache.put(issue); + } + } + + @VisibleForTesting + protected void mergeMatched(IssueTrackingResult result) { + for (DefaultIssue issue : result.matched()) { + org.sonar.batch.protocol.input.issues.PreviousIssue ref = ((PreviousIssueFromWs) result.matching(issue)).getDto(); + + // invariant fields + issue.setKey(ref.key()); + + // non-persisted fields + issue.setNew(false); + issue.setEndOfLife(false); + issue.setOnDisabledRule(false); + + // fields to update with old values + issue.setResolution(ref.resolution()); + issue.setStatus(ref.status()); + issue.setAssignee(ref.assigneeLogin()); + + String overriddenSeverity = ref.overriddenSeverity(); + if (overriddenSeverity != null) { + // Severity overriden by user + issue.setSeverity(overriddenSeverity); + } + } + } + + private void addUnmatched(Collection<PreviousIssue> unmatchedIssues, SourceHashHolder sourceHashHolder, Collection<DefaultIssue> issues) { + for (PreviousIssue unmatchedIssue : unmatchedIssues) { + org.sonar.batch.protocol.input.issues.PreviousIssue unmatchedPreviousIssue = ((PreviousIssueFromWs) unmatchedIssue).getDto(); + ActiveRule activeRule = activeRules.find(unmatchedIssue.ruleKey()); + DefaultIssue unmatched = toUnmatchedIssue(unmatchedPreviousIssue); + if (activeRule != null && !Issue.STATUS_CLOSED.equals(unmatchedPreviousIssue.status())) { + relocateManualIssue(unmatched, unmatchedIssue, sourceHashHolder); + } + updateUnmatchedIssue(unmatched, false /* manual issues can be kept open */); + issues.add(unmatched); + } + } + + private void addIssuesOnDeletedComponents(Collection<DefaultIssue> issues) { + for (org.sonar.batch.protocol.input.issues.PreviousIssue previous : previousIssueCache.issuesOnMissingComponents()) { + DefaultIssue dead = toUnmatchedIssue(previous); + updateUnmatchedIssue(dead, true); + issues.add(dead); + } + } + + private DefaultIssue toUnmatchedIssue(org.sonar.batch.protocol.input.issues.PreviousIssue previous) { + DefaultIssue issue = new DefaultIssue(); + issue.setKey(previous.key()); + issue.setStatus(previous.status()); + issue.setResolution(previous.resolution()); + issue.setMessage(previous.message()); + issue.setLine(previous.line()); + String overriddenSeverity = previous.overriddenSeverity(); + if (overriddenSeverity != null) { + issue.setSeverity(overriddenSeverity); + } else { + ActiveRule activeRule = activeRules.find(RuleKey.of(previous.ruleRepo(), previous.ruleKey())); + if (activeRule != null) { + // FIXME if rule was removed we can't guess what was the severity of the issue + issue.setSeverity(activeRule.severity()); + } + } + issue.setAssignee(previous.assigneeLogin()); + issue.setComponentKey(previous.componentKey()); + issue.setManualSeverity(overriddenSeverity != null); + issue.setRuleKey(RuleKey.of(previous.ruleRepo(), previous.ruleKey())); + issue.setNew(false); + return issue; + } + + private void updateUnmatchedIssue(DefaultIssue issue, boolean forceEndOfLife) { + ActiveRule activeRule = activeRules.find(issue.ruleKey()); + boolean isRemovedRule = activeRule == null; + issue.setEndOfLife(forceEndOfLife || isRemovedRule); + issue.setOnDisabledRule(isRemovedRule); + } + + private void relocateManualIssue(DefaultIssue newIssue, PreviousIssue oldIssue, SourceHashHolder sourceHashHolder) { + Integer previousLine = oldIssue.line(); + if (previousLine == null) { + return; + } + + Collection<Integer> newLinesWithSameHash = sourceHashHolder.getNewLinesMatching(previousLine); + if (newLinesWithSameHash.isEmpty()) { + if (previousLine > sourceHashHolder.getHashedSource().length()) { + newIssue.setLine(null); + updater.setStatus(newIssue, Issue.STATUS_CLOSED, changeContext); + updater.setResolution(newIssue, Issue.RESOLUTION_REMOVED, changeContext); + updater.setPastLine(newIssue, previousLine); + updater.setPastMessage(newIssue, oldIssue.message(), changeContext); + } + } else if (newLinesWithSameHash.size() == 1) { + Integer newLine = newLinesWithSameHash.iterator().next(); + newIssue.setLine(newLine); + updater.setPastLine(newIssue, previousLine); + updater.setPastMessage(newIssue, oldIssue.message(), changeContext); + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssue.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssue.java new file mode 100644 index 00000000000..dcef8caaa5a --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssue.java @@ -0,0 +1,47 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue.tracking; + +import org.sonar.api.rule.RuleKey; + +import javax.annotation.CheckForNull; + +public interface PreviousIssue { + + String key(); + + RuleKey ruleKey(); + + /** + * Null for issue with no line + */ + @CheckForNull + String checksum(); + + /** + * Global issues have no line + */ + @CheckForNull + Integer line(); + + @CheckForNull + String message(); + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueFromDb.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueFromDb.java new file mode 100644 index 00000000000..f20f420def4 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueFromDb.java @@ -0,0 +1,62 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue.tracking; + +import org.sonar.api.rule.RuleKey; +import org.sonar.core.issue.db.IssueDto; + +public class PreviousIssueFromDb implements PreviousIssue { + + private IssueDto dto; + + public PreviousIssueFromDb(IssueDto dto) { + this.dto = dto; + } + + public IssueDto getDto() { + return dto; + } + + @Override + public String key() { + return dto.getKee(); + } + + @Override + public RuleKey ruleKey() { + return dto.getRuleKey(); + } + + @Override + public String checksum() { + return dto.getChecksum(); + } + + @Override + public Integer line() { + return dto.getLine(); + } + + @Override + public String message() { + return dto.getMessage(); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueFromWs.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueFromWs.java new file mode 100644 index 00000000000..a9a435abb8c --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueFromWs.java @@ -0,0 +1,61 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue.tracking; + +import org.sonar.api.rule.RuleKey; + +public class PreviousIssueFromWs implements PreviousIssue { + + private org.sonar.batch.protocol.input.issues.PreviousIssue dto; + + public PreviousIssueFromWs(org.sonar.batch.protocol.input.issues.PreviousIssue dto) { + this.dto = dto; + } + + public org.sonar.batch.protocol.input.issues.PreviousIssue getDto() { + return dto; + } + + @Override + public String key() { + return dto.key(); + } + + @Override + public RuleKey ruleKey() { + return RuleKey.of(dto.ruleRepo(), dto.ruleKey()); + } + + @Override + public String checksum() { + return dto.checksum(); + } + + @Override + public Integer line() { + return dto.line(); + } + + @Override + public String message() { + return dto.message(); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueRepository.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueRepository.java new file mode 100644 index 00000000000..6bad06cf818 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/PreviousIssueRepository.java @@ -0,0 +1,84 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue.tracking; + +import com.google.common.base.Function; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.BatchComponent; +import org.sonar.api.batch.InstantiationStrategy; +import org.sonar.api.batch.bootstrap.ProjectReactor; +import org.sonar.api.utils.TimeProfiler; +import org.sonar.batch.index.BatchResource; +import org.sonar.batch.index.Cache; +import org.sonar.batch.index.Caches; +import org.sonar.batch.index.ResourceCache; +import org.sonar.batch.protocol.input.issues.PreviousIssue; +import org.sonar.batch.repository.PreviousIssuesLoader; + +@InstantiationStrategy(InstantiationStrategy.PER_BATCH) +public class PreviousIssueRepository implements BatchComponent { + + private static final Logger LOG = LoggerFactory.getLogger(PreviousIssueRepository.class); + + private final Caches caches; + private Cache<PreviousIssue> issuesCache; + private final PreviousIssuesLoader previousIssuesLoader; + private final ProjectReactor reactor; + private final ResourceCache resourceCache; + + public PreviousIssueRepository(Caches caches, PreviousIssuesLoader previousIssuesLoader, ProjectReactor reactor, ResourceCache resourceCache) { + this.caches = caches; + this.previousIssuesLoader = previousIssuesLoader; + this.reactor = reactor; + this.resourceCache = resourceCache; + } + + public void load() { + TimeProfiler profiler = new TimeProfiler(LOG).start("Load previous issues"); + try { + this.issuesCache = caches.createCache("previousIssues"); + previousIssuesLoader.load(reactor, new Function<PreviousIssue, Void>() { + + @Override + public Void apply(PreviousIssue issue) { + String componentKey = issue.componentKey(); + BatchResource r = resourceCache.get(componentKey); + if (r == null) { + // Deleted resource + issuesCache.put(0, issue.key(), issue); + } + issuesCache.put(r.batchId(), issue.key(), issue); + return null; + } + }); + } finally { + profiler.stop(); + } + } + + public Iterable<PreviousIssue> byComponent(BatchResource component) { + return issuesCache.values(component.batchId()); + } + + public Iterable<PreviousIssue> issuesOnMissingComponents() { + return issuesCache.values(0); + } +} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingFileHashes.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/RollingFileHashes.java index 313507a4d69..84beecd42ed 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/RollingFileHashes.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/RollingFileHashes.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue.tracking; +package org.sonar.batch.issue.tracking; /** * Compute hashes of block around each line diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SourceHashHolder.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/SourceHashHolder.java index 612968e8fc9..38f0af7745a 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/SourceHashHolder.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/SourceHashHolder.java @@ -17,13 +17,12 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import com.google.common.collect.ImmutableSet; import org.sonar.api.batch.fs.InputFile.Status; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.batch.scan.LastLineHashes; -import org.sonar.plugins.core.issue.tracking.FileHashes; import javax.annotation.CheckForNull; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/package-info.java index 4a3c6986229..8df05a16129 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/tracking/package-info.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/package-info.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +@ParametersAreNonnullByDefault +package org.sonar.batch.issue.tracking; -@javax.annotation.ParametersAreNonnullByDefault -package org.sonar.plugins.core.issue.tracking; - +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java index 1afdd61be6d..27bbc64ef0a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java +++ b/sonar-batch/src/main/java/org/sonar/batch/mediumtest/BatchMediumTester.java @@ -19,6 +19,7 @@ */ package org.sonar.batch.mediumtest; +import com.google.common.base.Function; import org.apache.commons.io.Charsets; import org.sonar.api.SonarPlugin; import org.sonar.api.batch.bootstrap.ProjectReactor; @@ -32,9 +33,11 @@ import org.sonar.batch.bootstrapper.Batch; import org.sonar.batch.bootstrapper.EnvironmentInformation; import org.sonar.batch.protocol.input.ActiveRule; import org.sonar.batch.protocol.input.GlobalReferentials; -import org.sonar.batch.protocol.input.ProjectReferentials; -import org.sonar.batch.referential.GlobalReferentialsLoader; -import org.sonar.batch.referential.ProjectReferentialsLoader; +import org.sonar.batch.protocol.input.ProjectRepository; +import org.sonar.batch.protocol.input.issues.PreviousIssue; +import org.sonar.batch.repository.GlobalReferentialsLoader; +import org.sonar.batch.repository.PreviousIssuesLoader; +import org.sonar.batch.repository.ProjectRepositoriesLoader; import org.sonar.core.plugins.DefaultPluginMetadata; import org.sonar.core.plugins.RemotePlugin; @@ -65,6 +68,7 @@ public class BatchMediumTester { private final FakeGlobalReferentialsLoader globalRefProvider = new FakeGlobalReferentialsLoader(); private final FakeProjectReferentialsLoader projectRefProvider = new FakeProjectReferentialsLoader(); private final FakePluginsReferential pluginsReferential = new FakePluginsReferential(); + private final FakePreviousIssuesLoader previousIssues = new FakePreviousIssuesLoader(); private final Map<String, String> bootstrapProperties = new HashMap<String, String>(); public BatchMediumTester build() { @@ -114,6 +118,11 @@ public class BatchMediumTester { return this; } + public BatchMediumTesterBuilder addPreviousIssue(PreviousIssue issue) { + previousIssues.getPreviousIssues().add(issue); + return this; + } + } public void start() { @@ -132,6 +141,7 @@ public class BatchMediumTester { builder.pluginsReferential, builder.globalRefProvider, builder.projectRefProvider, + builder.previousIssues, new DefaultDebtModel()) .setBootstrapProperties(builder.bootstrapProperties) .build(); @@ -217,12 +227,12 @@ public class BatchMediumTester { } } - private static class FakeProjectReferentialsLoader implements ProjectReferentialsLoader { + private static class FakeProjectReferentialsLoader implements ProjectRepositoriesLoader { - private ProjectReferentials ref = new ProjectReferentials(); + private ProjectRepository ref = new ProjectRepository(); @Override - public ProjectReferentials load(ProjectReactor reactor, TaskProperties taskProperties) { + public ProjectRepository load(ProjectReactor reactor, TaskProperties taskProperties) { return ref; } @@ -272,4 +282,22 @@ public class BatchMediumTester { } + private static class FakePreviousIssuesLoader implements PreviousIssuesLoader { + + List<PreviousIssue> previousIssues = new ArrayList<>(); + + public List<PreviousIssue> getPreviousIssues() { + return previousIssues; + } + + @Override + public void load(ProjectReactor reactor, Function<PreviousIssue, Void> consumer) { + for (PreviousIssue previousIssue : previousIssues) { + consumer.apply(previousIssue); + } + + } + + } + } diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PreviewPhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PreviewPhaseExecutor.java index de4bd65a3b4..80c2fe8c078 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/PreviewPhaseExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PreviewPhaseExecutor.java @@ -25,6 +25,7 @@ import org.sonar.batch.events.BatchStepEvent; import org.sonar.batch.events.EventBus; import org.sonar.batch.index.DefaultIndex; import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader; +import org.sonar.batch.issue.tracking.LocalIssueTracking; import org.sonar.batch.rule.QProfileVerifier; import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; import org.sonar.batch.scan.filesystem.FileSystemLogger; @@ -46,13 +47,14 @@ public final class PreviewPhaseExecutor implements PhaseExecutor { private final QProfileVerifier profileVerifier; private final IssueExclusionsLoader issueExclusionsLoader; private final IssuesReports issuesReport; + private final LocalIssueTracking localIssueTracking; public PreviewPhaseExecutor(Phases phases, MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor, SensorsExecutor sensorsExecutor, SensorContext sensorContext, DefaultIndex index, EventBus eventBus, ProjectInitializer pi, FileSystemLogger fsLogger, IssuesReports jsonReport, DefaultModuleFileSystem fs, QProfileVerifier profileVerifier, - IssueExclusionsLoader issueExclusionsLoader) { + IssueExclusionsLoader issueExclusionsLoader, LocalIssueTracking localIssueTracking) { this.phases = phases; this.mavenPluginsConfigurator = mavenPluginsConfigurator; this.initializersExecutor = initializersExecutor; @@ -66,6 +68,7 @@ public final class PreviewPhaseExecutor implements PhaseExecutor { this.fs = fs; this.profileVerifier = profileVerifier; this.issueExclusionsLoader = issueExclusionsLoader; + this.localIssueTracking = localIssueTracking; } /** @@ -95,6 +98,9 @@ public final class PreviewPhaseExecutor implements PhaseExecutor { } if (module.isRoot()) { + + localIssueTracking(); + issuesReport(); } @@ -102,6 +108,13 @@ public final class PreviewPhaseExecutor implements PhaseExecutor { eventBus.fireEvent(new ProjectAnalysisEvent(module, false)); } + private void localIssueTracking() { + String stepName = "Local Issue Tracking"; + eventBus.fireEvent(new BatchStepEvent(stepName, true)); + localIssueTracking.execute(); + eventBus.fireEvent(new BatchStepEvent(stepName, false)); + } + private void issuesReport() { String stepName = "Issues Reports"; eventBus.fireEvent(new BatchStepEvent(stepName, true)); diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/DefaultGlobalReferentialsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalReferentialsLoader.java index 17fd6821a6c..91012f9a6e3 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/referential/DefaultGlobalReferentialsLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultGlobalReferentialsLoader.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.referential; +package org.sonar.batch.repository; import org.sonar.batch.bootstrap.ServerClient; import org.sonar.batch.protocol.input.GlobalReferentials; diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultPreviousIssuesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultPreviousIssuesLoader.java new file mode 100644 index 00000000000..d2831e4a8f2 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultPreviousIssuesLoader.java @@ -0,0 +1,55 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.repository; + +import com.google.common.base.Charsets; +import com.google.common.base.Function; +import com.google.common.io.InputSupplier; +import org.sonar.api.batch.bootstrap.ProjectReactor; +import org.sonar.batch.bootstrap.ServerClient; +import org.sonar.batch.protocol.input.issues.PreviousIssue; +import org.sonar.batch.protocol.input.issues.PreviousIssueHelper; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.Reader; + +public class DefaultPreviousIssuesLoader implements PreviousIssuesLoader { + + private final ServerClient serverClient; + + public DefaultPreviousIssuesLoader(ServerClient serverClient) { + this.serverClient = serverClient; + } + + @Override + public void load(ProjectReactor reactor, Function<PreviousIssue, Void> consumer) { + InputSupplier<InputStream> request = serverClient.doRequest("/batch/issues?key=" + ServerClient.encodeForUrl(reactor.getRoot().getKeyWithBranch()), "GET", null); + try (InputStream is = request.getInput(); Reader reader = new InputStreamReader(is, Charsets.UTF_8)) { + for (PreviousIssue issue : PreviousIssueHelper.getIssues(reader)) { + consumer.apply(issue); + } + } catch (IOException e) { + throw new IllegalStateException("Unable to get previous issues", e); + } + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/DefaultProjectReferentialsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectReferentialsLoader.java index 90a10bc1191..de45aeaf428 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/referential/DefaultProjectReferentialsLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectReferentialsLoader.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.referential; +package org.sonar.batch.repository; import com.google.common.collect.Maps; import org.slf4j.Logger; @@ -35,7 +35,7 @@ import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.ServerClient; import org.sonar.batch.bootstrap.TaskProperties; import org.sonar.batch.protocol.input.FileData; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import org.sonar.batch.rule.ModuleQProfiles; import javax.annotation.CheckForNull; @@ -48,7 +48,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -public class DefaultProjectReferentialsLoader implements ProjectReferentialsLoader { +public class DefaultProjectReferentialsLoader implements ProjectRepositoriesLoader { private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectReferentialsLoader.class); @@ -71,7 +71,7 @@ public class DefaultProjectReferentialsLoader implements ProjectReferentialsLoad } @Override - public ProjectReferentials load(ProjectReactor reactor, TaskProperties taskProperties) { + public ProjectRepository load(ProjectReactor reactor, TaskProperties taskProperties) { String projectKey = reactor.getRoot().getKeyWithBranch(); String url = BATCH_PROJECT_URL + "?key=" + ServerClient.encodeForUrl(projectKey); if (taskProperties.properties().containsKey(ModuleQProfiles.SONAR_PROFILE_PROP)) { @@ -80,7 +80,7 @@ public class DefaultProjectReferentialsLoader implements ProjectReferentialsLoad url += "&profile=" + ServerClient.encodeForUrl(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP)); } url += "&preview=" + analysisMode.isPreview(); - ProjectReferentials ref = ProjectReferentials.fromJson(serverClient.request(url)); + ProjectRepository ref = ProjectRepository.fromJson(serverClient.request(url)); if (session != null) { for (ProjectDefinition module : reactor.getProjects()) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/GlobalReferentialsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/GlobalReferentialsLoader.java index d355867d433..1dbbb520882 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/referential/GlobalReferentialsLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/GlobalReferentialsLoader.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.referential; +package org.sonar.batch.repository; import org.sonar.batch.protocol.input.GlobalReferentials; diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/GlobalReferentialsProvider.java b/sonar-batch/src/main/java/org/sonar/batch/repository/GlobalReferentialsProvider.java index 5e10e6c61e4..d3c99dc6552 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/referential/GlobalReferentialsProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/GlobalReferentialsProvider.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.referential; +package org.sonar.batch.repository; import org.picocontainer.injectors.ProviderAdapter; import org.slf4j.Logger; diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/PreviousIssuesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/PreviousIssuesLoader.java new file mode 100644 index 00000000000..fe706da3e73 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/PreviousIssuesLoader.java @@ -0,0 +1,30 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.repository; + +import com.google.common.base.Function; +import org.sonar.api.batch.bootstrap.ProjectReactor; +import org.sonar.batch.protocol.input.issues.PreviousIssue; + +public interface PreviousIssuesLoader { + + void load(ProjectReactor reactor, Function<PreviousIssue, Void> consumer); + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java index e4bad9f1e13..75caa6f3b4f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java @@ -17,14 +17,14 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.referential; +package org.sonar.batch.repository; import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.batch.bootstrap.TaskProperties; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; -public interface ProjectReferentialsLoader { +public interface ProjectRepositoriesLoader { - ProjectReferentials load(ProjectReactor reactor, TaskProperties taskProperties); + ProjectRepository load(ProjectReactor reactor, TaskProperties taskProperties); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsProvider.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesProvider.java index 03486bfdcee..c9cf9e40537 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/referential/ProjectReferentialsProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesProvider.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.referential; +package org.sonar.batch.repository; import org.picocontainer.injectors.ProviderAdapter; import org.slf4j.Logger; @@ -25,15 +25,15 @@ import org.slf4j.LoggerFactory; import org.sonar.api.batch.bootstrap.ProjectReactor; import org.sonar.api.utils.TimeProfiler; import org.sonar.batch.bootstrap.TaskProperties; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; -public class ProjectReferentialsProvider extends ProviderAdapter { +public class ProjectRepositoriesProvider extends ProviderAdapter { - private static final Logger LOG = LoggerFactory.getLogger(ProjectReferentialsProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(ProjectRepositoriesProvider.class); - private ProjectReferentials projectReferentials; + private ProjectRepository projectReferentials; - public ProjectReferentials provide(ProjectReferentialsLoader loader, ProjectReactor reactor, TaskProperties taskProps) { + public ProjectRepository provide(ProjectRepositoriesLoader loader, ProjectReactor reactor, TaskProperties taskProps) { if (projectReferentials == null) { TimeProfiler profiler = new TimeProfiler(LOG).start("Load project referentials"); try { diff --git a/sonar-batch/src/main/java/org/sonar/batch/referential/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/repository/package-info.java index 1a50ff50cdf..353f019b08f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/referential/package-info.java +++ b/sonar-batch/src/main/java/org/sonar/batch/repository/package-info.java @@ -18,6 +18,6 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ @ParametersAreNonnullByDefault -package org.sonar.batch.referential; +package org.sonar.batch.repository; import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java index a539b744073..4ae65303f0e 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java +++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java @@ -25,26 +25,26 @@ import org.sonar.api.batch.rule.internal.ActiveRulesBuilder; import org.sonar.api.batch.rule.internal.NewActiveRule; import org.sonar.api.rule.RuleKey; import org.sonar.batch.protocol.input.ActiveRule; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import java.util.Map.Entry; /** * Loads the rules that are activated on the Quality profiles - * used by the current module and build {@link org.sonar.api.batch.rule.ActiveRules}. + * used by the current project and build {@link org.sonar.api.batch.rule.ActiveRules}. */ public class ActiveRulesProvider extends ProviderAdapter { private ActiveRules singleton = null; - public ActiveRules provide(ProjectReferentials ref) { + public ActiveRules provide(ProjectRepository ref) { if (singleton == null) { singleton = load(ref); } return singleton; } - private ActiveRules load(ProjectReferentials ref) { + private ActiveRules load(ProjectRepository ref) { ActiveRulesBuilder builder = new ActiveRulesBuilder(); for (ActiveRule activeRule : ref.activeRules()) { NewActiveRule newActiveRule = builder.create(RuleKey.of(activeRule.repositoryKey(), activeRule.ruleKey())); diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java index dba6cd74a9b..badcc7878c6 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java +++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java @@ -21,7 +21,7 @@ package org.sonar.batch.rule; import com.google.common.collect.ImmutableMap; import org.sonar.api.BatchComponent; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import javax.annotation.CheckForNull; @@ -36,7 +36,7 @@ public class ModuleQProfiles implements BatchComponent { public static final String SONAR_PROFILE_PROP = "sonar.profile"; private final Map<String, QProfile> byLanguage; - public ModuleQProfiles(ProjectReferentials ref) { + public ModuleQProfiles(ProjectRepository ref) { ImmutableMap.Builder<String, QProfile> builder = ImmutableMap.builder(); for (org.sonar.batch.protocol.input.QProfile qProfile : ref.qProfiles()) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java index 59dc45098d5..c54806dd347 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java @@ -19,8 +19,6 @@ */ package org.sonar.batch.scan; -import org.sonar.batch.sensor.AnalyzerOptimizer; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; @@ -59,6 +57,9 @@ import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader; import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner; +import org.sonar.batch.issue.tracking.InitialOpenIssuesSensor; +import org.sonar.batch.issue.tracking.IssueHandlers; +import org.sonar.batch.issue.tracking.IssueTrackingDecorator; import org.sonar.batch.language.LanguageDistributionDecorator; import org.sonar.batch.phases.DecoratorsExecutor; import org.sonar.batch.phases.DefaultPhaseExecutor; @@ -75,7 +76,6 @@ import org.sonar.batch.qualitygate.QualityGateVerifier; import org.sonar.batch.report.ComponentsPublisher; import org.sonar.batch.report.IssuesPublisher; import org.sonar.batch.report.PublishReportJob; -import org.sonar.batch.rule.ActiveRulesProvider; import org.sonar.batch.rule.ModuleQProfiles; import org.sonar.batch.rule.QProfileDecorator; import org.sonar.batch.rule.QProfileEventsDecorator; @@ -97,6 +97,7 @@ import org.sonar.batch.scan.filesystem.ProjectFileSystemAdapter; import org.sonar.batch.scan.filesystem.StatusDetectionFactory; import org.sonar.batch.scan.maven.MavenPluginsConfigurator; import org.sonar.batch.scan.report.IssuesReports; +import org.sonar.batch.sensor.AnalyzerOptimizer; import org.sonar.batch.sensor.DefaultSensorContext; import org.sonar.batch.sensor.DefaultSensorStorage; import org.sonar.batch.sensor.coverage.CoverageExclusions; @@ -185,7 +186,6 @@ public class ModuleScanContainer extends ComponentContainer { // rules ModuleQProfiles.class, - new ActiveRulesProvider(), new RulesProfileProvider(), QProfileSensor.class, QProfileDecorator.class, @@ -229,6 +229,11 @@ public class ModuleScanContainer extends ComponentContainer { SqaleRatingDecorator.class, SqaleRatingSettings.class, + // Issue tracking + IssueTrackingDecorator.class, + IssueHandlers.class, + InitialOpenIssuesSensor.class, + QProfileEventsDecorator.class, TimeMachineConfiguration.class); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java index f7c2d9fa27d..83b1c328deb 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java @@ -27,7 +27,7 @@ import org.sonar.api.config.Settings; import org.sonar.api.utils.MessageException; import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.GlobalSettings; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import java.util.List; @@ -36,10 +36,10 @@ import java.util.List; */ public class ModuleSettings extends Settings { - private final ProjectReferentials projectReferentials; + private final ProjectRepository projectReferentials; private AnalysisMode analysisMode; - public ModuleSettings(GlobalSettings batchSettings, ProjectDefinition project, ProjectReferentials projectReferentials, + public ModuleSettings(GlobalSettings batchSettings, ProjectDefinition project, ProjectRepository projectReferentials, AnalysisMode analysisMode) { super(batchSettings.getDefinitions()); this.projectReferentials = projectReferentials; diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java index 0a3c22ef77a..d6a47de9952 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java @@ -59,11 +59,15 @@ import org.sonar.batch.index.ResourcePersister; import org.sonar.batch.index.SourcePersister; import org.sonar.batch.issue.DefaultProjectIssues; import org.sonar.batch.issue.IssueCache; +import org.sonar.batch.issue.tracking.InitialOpenIssuesStack; +import org.sonar.batch.issue.tracking.LocalIssueTracking; +import org.sonar.batch.issue.tracking.PreviousIssueRepository; import org.sonar.batch.languages.DefaultLanguagesReferential; import org.sonar.batch.mediumtest.ScanTaskObservers; import org.sonar.batch.phases.GraphPersister; import org.sonar.batch.profiling.PhasesSumUpTimeProfiler; -import org.sonar.batch.referential.ProjectReferentialsProvider; +import org.sonar.batch.repository.ProjectRepositoriesProvider; +import org.sonar.batch.rule.ActiveRulesProvider; import org.sonar.batch.rule.RulesProvider; import org.sonar.batch.scan.filesystem.InputPathCache; import org.sonar.batch.scan.maven.FakeMavenPluginExecutor; @@ -131,7 +135,7 @@ public class ProjectScanContainer extends ComponentContainer { private void addBatchComponents() { add( - new ProjectReferentialsProvider(), + new ProjectRepositoriesProvider(), DefaultResourceCreationLock.class, CodeColorizers.class, DefaultNotificationManager.class, @@ -148,6 +152,9 @@ public class ProjectScanContainer extends ComponentContainer { InputPathCache.class, PathResolver.class, + // rules + new ActiveRulesProvider(), + // issues IssueUpdater.class, FunctionExecutor.class, @@ -155,6 +162,8 @@ public class ProjectScanContainer extends ComponentContainer { IssueCache.class, DefaultProjectIssues.class, IssueChangelogDebtCalculator.class, + LocalIssueTracking.class, + PreviousIssueRepository.class, // tests TestPlanPerspectiveLoader.class, @@ -203,6 +212,9 @@ public class ProjectScanContainer extends ComponentContainer { // technical debt DefaultTechnicalDebtModel.class, + // Issue tracking + InitialOpenIssuesStack.class, + ProjectLock.class); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java index 72218e95ce3..f6539dbfa7f 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java @@ -28,18 +28,18 @@ import org.sonar.api.config.Settings; import org.sonar.api.utils.MessageException; import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.GlobalSettings; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; public class ProjectSettings extends Settings { private static final Logger LOG = LoggerFactory.getLogger(ProjectSettings.class); private final GlobalSettings globalSettings; - private final ProjectReferentials projectReferentials; + private final ProjectRepository projectReferentials; private final AnalysisMode mode; public ProjectSettings(ProjectReactor reactor, GlobalSettings globalSettings, PropertyDefinitions propertyDefinitions, - ProjectReferentials projectReferentials, AnalysisMode mode) { + ProjectRepository projectReferentials, AnalysisMode mode) { super(propertyDefinitions); this.mode = mode; getEncryption().setPathToSecretKey(globalSettings.getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH)); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java index 8843e604989..883268fcc01 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java @@ -22,13 +22,13 @@ package org.sonar.batch.scan.filesystem; import org.apache.commons.lang.StringUtils; import org.sonar.api.batch.fs.InputFile; import org.sonar.batch.protocol.input.FileData; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; class StatusDetection { - private final ProjectReferentials projectReferentials; + private final ProjectRepository projectReferentials; - StatusDetection(ProjectReferentials projectReferentials) { + StatusDetection(ProjectRepository projectReferentials) { this.projectReferentials = projectReferentials; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java index 830cb346c09..15e19d6457b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java @@ -20,13 +20,13 @@ package org.sonar.batch.scan.filesystem; import org.sonar.api.BatchComponent; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; public class StatusDetectionFactory implements BatchComponent { - private final ProjectReferentials projectReferentials; + private final ProjectRepository projectReferentials; - public StatusDetectionFactory(ProjectReferentials projectReferentials) { + public StatusDetectionFactory(ProjectRepository projectReferentials) { this.projectReferentials = projectReferentials; } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java index 00f6839bfdb..fc42a20e18c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java @@ -34,7 +34,7 @@ import org.sonar.api.batch.sensor.measure.internal.DefaultMeasure; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.utils.TimeProfiler; import org.sonar.batch.protocol.input.FileData; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import org.sonar.core.DryRunIncompatible; import java.util.LinkedList; @@ -48,10 +48,10 @@ public final class ScmSensor implements Sensor { private final ProjectDefinition projectDefinition; private final ScmConfiguration configuration; private final FileSystem fs; - private final ProjectReferentials projectReferentials; + private final ProjectRepository projectReferentials; public ScmSensor(ProjectDefinition projectDefinition, ScmConfiguration configuration, - ProjectReferentials projectReferentials, FileSystem fs) { + ProjectRepository projectReferentials, FileSystem fs) { this.projectDefinition = projectDefinition; this.configuration = configuration; this.projectReferentials = projectReferentials; diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensorTest.java index e1c70330963..85c1e43c51a 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesSensorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesSensorTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import org.apache.ibatis.session.ResultHandler; import org.junit.Test; diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java index ed7782e138b..34adce38fa1 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/InitialOpenIssuesStackTest.java @@ -18,7 +18,7 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import org.junit.After; import org.junit.Before; @@ -73,9 +73,9 @@ public class InitialOpenIssuesStackTest { IssueDto issueDto = new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-1"); stack.addIssue(issueDto); - List<IssueDto> issueDtos = stack.selectAndRemoveIssues("org.struts.Action"); + List<PreviousIssue> issueDtos = stack.selectAndRemoveIssues("org.struts.Action"); assertThat(issueDtos).hasSize(1); - assertThat(issueDtos.get(0).getKee()).isEqualTo("ISSUE-1"); + assertThat(issueDtos.get(0).key()).isEqualTo("ISSUE-1"); assertThat(stack.selectAllIssues()).isEmpty(); } @@ -85,7 +85,7 @@ public class InitialOpenIssuesStackTest { stack.addIssue(new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-1")); stack.addIssue(new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-2")); - List<IssueDto> issueDtos = stack.selectAndRemoveIssues("org.struts.Action"); + List<PreviousIssue> issueDtos = stack.selectAndRemoveIssues("org.struts.Action"); assertThat(issueDtos).hasSize(2); assertThat(stack.selectAllIssues()).isEmpty(); @@ -95,7 +95,7 @@ public class InitialOpenIssuesStackTest { public void get_and_remove_do_nothing_if_resource_not_found() { stack.addIssue(new IssueDto().setComponentKey("org.struts.Action").setKee("ISSUE-1")); - List<IssueDto> issueDtos = stack.selectAndRemoveIssues("Other"); + List<PreviousIssue> issueDtos = stack.selectAndRemoveIssues("Other"); assertThat(issueDtos).hasSize(0); assertThat(stack.selectAllIssues()).hasSize(1); diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueHandlersTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueHandlersTest.java index b1f745927e5..8b210bd731d 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueHandlersTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueHandlersTest.java @@ -17,7 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; + +import org.sonar.batch.issue.tracking.IssueHandlers; import org.junit.Test; import org.mockito.ArgumentMatcher; diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/IssueTrackingBlocksRecognizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingBlocksRecognizerTest.java index 55d84685253..30bf045483d 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/IssueTrackingBlocksRecognizerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingBlocksRecognizerTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue.tracking; +package org.sonar.batch.issue.tracking; import org.junit.Test; diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java index 337f16b94fe..7691dbf6538 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingDecoratorTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import org.apache.commons.codec.digest.DigestUtils; import org.junit.Before; @@ -61,7 +61,13 @@ import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.argThat; import static org.mockito.Matchers.eq; import static org.mockito.Matchers.isA; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.RETURNS_MOCKS; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; public class IssueTrackingDecoratorTest { @@ -115,7 +121,7 @@ public class IssueTrackingDecoratorTest { // INPUT : one issue, no open issues during previous scan, no filtering when(issueCache.byComponent("struts:Action.java")).thenReturn(Arrays.asList(issue)); - List<IssueDto> dbIssues = Collections.emptyList(); + List<PreviousIssue> dbIssues = Collections.emptyList(); when(initialOpenIssues.selectAndRemoveIssues("struts:Action.java")).thenReturn(dbIssues); when(inputPathCache.getFile("foo", "Action.java")).thenReturn(mock(DefaultInputFile.class)); decorator.doDecorate(file); @@ -139,7 +145,7 @@ public class IssueTrackingDecoratorTest { Resource file = File.create("Action.java").setEffectiveKey("struts:Action.java").setId(123); // INPUT : one issue existing during previous scan - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle")); IssueTrackingResult trackingResult = new IssueTrackingResult(); trackingResult.addUnmatched(unmatchedIssue); @@ -164,7 +170,7 @@ public class IssueTrackingDecoratorTest { @Test public void manual_issues_should_be_moved_if_matching_line_found() throws Exception { // INPUT : one issue existing during previous scan - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(6).setStatus("OPEN").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(6).setStatus("OPEN").setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -219,7 +225,7 @@ public class IssueTrackingDecoratorTest { public void manual_issues_should_be_untouched_if_already_closed() throws Exception { // INPUT : one issue existing during previous scan - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("CLOSED").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("CLOSED").setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -251,7 +257,7 @@ public class IssueTrackingDecoratorTest { public void manual_issues_should_be_untouched_if_line_is_null() throws Exception { // INPUT : one issue existing during previous scan - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(null).setStatus("OPEN").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(null).setStatus("OPEN").setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -285,7 +291,8 @@ public class IssueTrackingDecoratorTest { // INPUT : one issue existing during previous scan final int issueOnLine = 6; - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(issueOnLine).setStatus("OPEN").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(issueOnLine).setStatus("OPEN") + .setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -332,7 +339,8 @@ public class IssueTrackingDecoratorTest { // INPUT : one issue existing during previous scan final int issueOnLine = 3; - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(issueOnLine).setStatus("OPEN").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(issueOnLine).setStatus("OPEN") + .setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance")); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -377,7 +385,7 @@ public class IssueTrackingDecoratorTest { // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed // INPUT : one issue existing during previous scan - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("OPEN").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("OPEN").setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(new Rule("manual", "Performance").setStatus(Rule.STATUS_REMOVED)); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -408,7 +416,7 @@ public class IssueTrackingDecoratorTest { // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed // INPUT : one issue existing during previous scan - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("OPEN").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(1).setStatus("OPEN").setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(null); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -439,7 +447,7 @@ public class IssueTrackingDecoratorTest { // "Unmatched" issues existed in previous scan but not in current one -> they have to be closed // INPUT : one issue existing during previous scan - IssueDto unmatchedIssue = new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(6).setStatus("OPEN").setRuleKey("manual", "Performance"); + PreviousIssue unmatchedIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setReporter("freddy").setLine(6).setStatus("OPEN").setRuleKey("manual", "Performance")); when(ruleFinder.findByKey(RuleKey.of("manual", "Performance"))).thenReturn(null); IssueTrackingResult trackingResult = new IssueTrackingResult(); @@ -504,8 +512,8 @@ public class IssueTrackingDecoratorTest { @Test public void merge_matched_issue() throws Exception { - IssueDto previousIssue = new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") - .setLine(10).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L).setProjectKey("sample"); + PreviousIssue previousIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") + .setLine(10).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L).setProjectKey("sample")); DefaultIssue issue = new DefaultIssue(); IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); @@ -523,8 +531,8 @@ public class IssueTrackingDecoratorTest { @Test public void merge_matched_issue_on_manual_severity() throws Exception { - IssueDto previousIssue = new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") - .setLine(10).setManualSeverity(true).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L); + PreviousIssue previousIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") + .setLine(10).setManualSeverity(true).setSeverity("MAJOR").setMessage("Message").setEffortToFix(1.5).setDebt(1L)); DefaultIssue issue = new DefaultIssue(); IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); @@ -541,8 +549,8 @@ public class IssueTrackingDecoratorTest { public void merge_issue_changelog_with_previous_changelog() throws Exception { when(initialOpenIssues.selectChangelog("ABCDE")).thenReturn(newArrayList(new IssueChangeDto().setIssueKey("ABCD").setCreatedAt(System2.INSTANCE.now()))); - IssueDto previousIssue = new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") - .setLine(10).setMessage("Message").setEffortToFix(1.5).setDebt(1L).setCreatedAt(System2.INSTANCE.now()); + PreviousIssue previousIssue = new PreviousIssueFromDb(new IssueDto().setKee("ABCDE").setResolution(null).setStatus("OPEN").setRuleKey("squid", "AvoidCycle") + .setLine(10).setMessage("Message").setEffortToFix(1.5).setDebt(1L).setCreatedAt(System2.INSTANCE.now())); DefaultIssue issue = new DefaultIssue(); IssueTrackingResult trackingResult = mock(IssueTrackingResult.class); diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingTest.java index 7fb8b6a9103..2efb24c13eb 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/IssueTrackingTest.java @@ -18,9 +18,10 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import com.google.common.base.Charsets; +import com.google.common.collect.Lists; import com.google.common.io.Resources; import org.apache.commons.codec.digest.DigestUtils; import org.junit.Before; @@ -62,22 +63,24 @@ public class IssueTrackingTest { @Test public void key_should_be_the_prioritary_field_to_check() { - IssueDto referenceIssue1 = newReferenceIssue("message", 10, "squid", "AvoidCycle", "checksum1").setKee("100"); - IssueDto referenceIssue2 = newReferenceIssue("message", 10, "squid", "AvoidCycle", "checksum2").setKee("200"); + PreviousIssueFromDb referenceIssue1 = newReferenceIssue("message", 10, "squid", "AvoidCycle", "checksum1"); + referenceIssue1.getDto().setKee("100"); + PreviousIssueFromDb referenceIssue2 = newReferenceIssue("message", 10, "squid", "AvoidCycle", "checksum2"); + referenceIssue2.getDto().setKee("200"); // exactly the fields of referenceIssue1 but not the same key DefaultIssue newIssue = newDefaultIssue("message", 10, RuleKey.of("squid", "AvoidCycle"), "checksum1").setKey("200"); IssueTrackingResult result = new IssueTrackingResult(); - tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue1, referenceIssue2), null, result); + tracking.mapIssues(newArrayList(newIssue), Lists.<PreviousIssue>newArrayList(referenceIssue1, referenceIssue2), null, result); // same key assertThat(result.matching(newIssue)).isSameAs(referenceIssue2); } @Test public void checksum_should_have_greater_priority_than_line() { - IssueDto referenceIssue1 = newReferenceIssue("message", 1, "squid", "AvoidCycle", "checksum1"); - IssueDto referenceIssue2 = newReferenceIssue("message", 3, "squid", "AvoidCycle", "checksum2"); + PreviousIssue referenceIssue1 = newReferenceIssue("message", 1, "squid", "AvoidCycle", "checksum1"); + PreviousIssue referenceIssue2 = newReferenceIssue("message", 3, "squid", "AvoidCycle", "checksum2"); DefaultIssue newIssue1 = newDefaultIssue("message", 3, RuleKey.of("squid", "AvoidCycle"), "checksum1"); DefaultIssue newIssue2 = newDefaultIssue("message", 5, RuleKey.of("squid", "AvoidCycle"), "checksum2"); @@ -94,7 +97,7 @@ public class IssueTrackingTest { @Test public void same_rule_and_null_line_and_checksum_but_different_messages() { DefaultIssue newIssue = newDefaultIssue("new message", null, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("old message", null, "squid", "AvoidCycle", "checksum1"); + PreviousIssue referenceIssue = newReferenceIssue("old message", null, "squid", "AvoidCycle", "checksum1"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -104,7 +107,7 @@ public class IssueTrackingTest { @Test public void same_rule_and_line_and_checksum_but_different_messages() { DefaultIssue newIssue = newDefaultIssue("new message", 1, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("old message", 1, "squid", "AvoidCycle", "checksum1"); + PreviousIssue referenceIssue = newReferenceIssue("old message", 1, "squid", "AvoidCycle", "checksum1"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -114,7 +117,7 @@ public class IssueTrackingTest { @Test public void same_rule_and_line_message() { DefaultIssue newIssue = newDefaultIssue("message", 1, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("message", 1, "squid", "AvoidCycle", "checksum2"); + PreviousIssue referenceIssue = newReferenceIssue("message", 1, "squid", "AvoidCycle", "checksum2"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -124,7 +127,7 @@ public class IssueTrackingTest { @Test public void should_ignore_reference_measure_without_checksum() { DefaultIssue newIssue = newDefaultIssue("message", 1, RuleKey.of("squid", "AvoidCycle"), null); - IssueDto referenceIssue = newReferenceIssue("message", 1, "squid", "NullDeref", null); + PreviousIssue referenceIssue = newReferenceIssue("message", 1, "squid", "NullDeref", null); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -134,7 +137,7 @@ public class IssueTrackingTest { @Test public void same_rule_and_message_and_checksum_but_different_line() { DefaultIssue newIssue = newDefaultIssue("message", 1, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("message", 2, "squid", "AvoidCycle", "checksum1"); + PreviousIssue referenceIssue = newReferenceIssue("message", 2, "squid", "AvoidCycle", "checksum1"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -147,7 +150,7 @@ public class IssueTrackingTest { @Test public void same_checksum_and_rule_but_different_line_and_different_message() { DefaultIssue newIssue = newDefaultIssue("new message", 1, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("old message", 2, "squid", "AvoidCycle", "checksum1"); + PreviousIssue referenceIssue = newReferenceIssue("old message", 2, "squid", "AvoidCycle", "checksum1"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -157,7 +160,7 @@ public class IssueTrackingTest { @Test public void should_create_new_issue_when_same_rule_same_message_but_different_line_and_checksum() { DefaultIssue newIssue = newDefaultIssue("message", 1, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("message", 2, "squid", "AvoidCycle", "checksum2"); + PreviousIssue referenceIssue = newReferenceIssue("message", 2, "squid", "AvoidCycle", "checksum2"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -167,7 +170,7 @@ public class IssueTrackingTest { @Test public void should_not_track_issue_if_different_rule() { DefaultIssue newIssue = newDefaultIssue("message", 1, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("message", 1, "squid", "NullDeref", "checksum1"); + PreviousIssue referenceIssue = newReferenceIssue("message", 1, "squid", "NullDeref", "checksum1"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -179,7 +182,7 @@ public class IssueTrackingTest { // issue messages are trimmed and can be abbreviated when persisted in database. // Comparing issue messages must use the same format. DefaultIssue newIssue = newDefaultIssue(" message ", 1, RuleKey.of("squid", "AvoidCycle"), "checksum1"); - IssueDto referenceIssue = newReferenceIssue("message", 1, "squid", "AvoidCycle", "checksum2"); + PreviousIssue referenceIssue = newReferenceIssue("message", 1, "squid", "AvoidCycle", "checksum2"); IssueTrackingResult result = new IssueTrackingResult(); tracking.mapIssues(newArrayList(newIssue), newArrayList(referenceIssue), null, result); @@ -191,7 +194,7 @@ public class IssueTrackingTest { initLastHashes("example2-v1", "example2-v2"); DefaultIssue newIssue = newDefaultIssue("Indentation", 9, RuleKey.of("squid", "AvoidCycle"), "foo"); - IssueDto referenceIssue = newReferenceIssue("2 branches need to be covered", null, "squid", "AvoidCycle", null); + PreviousIssue referenceIssue = newReferenceIssue("2 branches need to be covered", null, "squid", "AvoidCycle", null); IssueTrackingResult result = tracking.track(sourceHashHolder, newArrayList(referenceIssue), newArrayList(newIssue)); @@ -203,7 +206,7 @@ public class IssueTrackingTest { initLastHashes("example2-v1", "example2-v2"); DefaultIssue newIssue = newDefaultIssue("1 branch need to be covered", null, RuleKey.of("squid", "AvoidCycle"), "foo"); - IssueDto referenceIssue = newReferenceIssue("Indentationd", 7, "squid", "AvoidCycle", null); + PreviousIssue referenceIssue = newReferenceIssue("Indentationd", 7, "squid", "AvoidCycle", null); IssueTrackingResult result = tracking.track(sourceHashHolder, newArrayList(referenceIssue), newArrayList(newIssue)); @@ -218,7 +221,7 @@ public class IssueTrackingTest { initLastHashes("example2-v1", "example2-v2"); DefaultIssue newIssue = newDefaultIssue("1 branch need to be covered", null, RuleKey.of("squid", "AvoidCycle"), null); - IssueDto referenceIssue = newReferenceIssue("2 branches need to be covered", null, "squid", "AvoidCycle", null); + PreviousIssue referenceIssue = newReferenceIssue("2 branches need to be covered", null, "squid", "AvoidCycle", null); IssueTrackingResult result = tracking.track(sourceHashHolder, newArrayList(referenceIssue), newArrayList(newIssue)); @@ -232,8 +235,8 @@ public class IssueTrackingTest { public void should_track_issues_based_on_blocks_recognition_on_example1() throws Exception { initLastHashes("example1-v1", "example1-v2"); - IssueDto referenceIssue1 = newReferenceIssue("Indentation", 7, "squid", "AvoidCycle", null); - IssueDto referenceIssue2 = newReferenceIssue("Indentation", 11, "squid", "AvoidCycle", null); + PreviousIssue referenceIssue1 = newReferenceIssue("Indentation", 7, "squid", "AvoidCycle", null); + PreviousIssue referenceIssue2 = newReferenceIssue("Indentation", 11, "squid", "AvoidCycle", null); DefaultIssue newIssue1 = newDefaultIssue("Indentation", 9, RuleKey.of("squid", "AvoidCycle"), null); DefaultIssue newIssue2 = newDefaultIssue("Indentation", 13, RuleKey.of("squid", "AvoidCycle"), null); @@ -255,7 +258,7 @@ public class IssueTrackingTest { public void should_track_issues_based_on_blocks_recognition_on_example2() throws Exception { initLastHashes("example2-v1", "example2-v2"); - IssueDto referenceIssue1 = newReferenceIssue("SystemPrintln", 5, "squid", "AvoidCycle", null); + PreviousIssue referenceIssue1 = newReferenceIssue("SystemPrintln", 5, "squid", "AvoidCycle", null); DefaultIssue newIssue1 = newDefaultIssue("SystemPrintln", 6, RuleKey.of("squid", "AvoidCycle"), null); DefaultIssue newIssue2 = newDefaultIssue("SystemPrintln", 10, RuleKey.of("squid", "AvoidCycle"), null); @@ -276,9 +279,9 @@ public class IssueTrackingTest { public void should_track_issues_based_on_blocks_recognition_on_example3() throws Exception { initLastHashes("example3-v1", "example3-v2"); - IssueDto referenceIssue1 = newReferenceIssue("Avoid unused local variables such as 'j'.", 6, "squid", "AvoidCycle", "63c11570fc0a76434156be5f8138fa03"); - IssueDto referenceIssue2 = newReferenceIssue("Avoid unused private methods such as 'myMethod()'.", 13, "squid", "NullDeref", "ef23288705d1ef1e512448ace287586e"); - IssueDto referenceIssue3 = newReferenceIssue("Method 'avoidUtilityClass' is not designed for extension - needs to be abstract, final or empty.", 9, "pmd", + PreviousIssue referenceIssue1 = newReferenceIssue("Avoid unused local variables such as 'j'.", 6, "squid", "AvoidCycle", "63c11570fc0a76434156be5f8138fa03"); + PreviousIssue referenceIssue2 = newReferenceIssue("Avoid unused private methods such as 'myMethod()'.", 13, "squid", "NullDeref", "ef23288705d1ef1e512448ace287586e"); + PreviousIssue referenceIssue3 = newReferenceIssue("Method 'avoidUtilityClass' is not designed for extension - needs to be abstract, final or empty.", 9, "pmd", "UnusedLocalVariable", "ed5cdd046fda82727d6fedd1d8e3a310"); // New issue @@ -311,7 +314,7 @@ public class IssueTrackingTest { public void dont_load_checksum_if_no_new_issue() throws Exception { sourceHashHolder = mock(SourceHashHolder.class); - IssueDto referenceIssue = newReferenceIssue("2 branches need to be covered", null, "squid", "AvoidCycle", null); + PreviousIssue referenceIssue = newReferenceIssue("2 branches need to be covered", null, "squid", "AvoidCycle", null); tracking.track(sourceHashHolder, newArrayList(referenceIssue), Collections.<DefaultIssue>emptyList()); @@ -326,7 +329,7 @@ public class IssueTrackingTest { return new DefaultIssue().setMessage(message).setLine(line).setRuleKey(ruleKey).setChecksum(checksum).setStatus(Issue.STATUS_OPEN); } - private IssueDto newReferenceIssue(String message, Integer lineId, String ruleRepo, String ruleKey, String lineChecksum) { + private PreviousIssueFromDb newReferenceIssue(String message, Integer lineId, String ruleRepo, String ruleKey, String lineChecksum) { IssueDto referenceIssue = new IssueDto(); Long id = violationId++; referenceIssue.setId(id); @@ -337,7 +340,7 @@ public class IssueTrackingTest { referenceIssue.setChecksum(lineChecksum); referenceIssue.setResolution(null); referenceIssue.setStatus(Issue.STATUS_OPEN); - return referenceIssue; + return new PreviousIssueFromDb(referenceIssue); } private void initLastHashes(String reference, String newSource) throws IOException { diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/RollingFileHashesTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/RollingFileHashesTest.java index 50c3d0eefa0..25abe186d2e 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/tracking/RollingFileHashesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/RollingFileHashesTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue.tracking; +package org.sonar.batch.issue.tracking; import org.junit.Test; diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/SourceHashHolderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/SourceHashHolderTest.java index c9942c852b4..6ac6645bbae 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/SourceHashHolderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/SourceHashHolderTest.java @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.plugins.core.issue; +package org.sonar.batch.issue.tracking; import org.junit.Before; import org.junit.Test; diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java index 89f926e296f..a6bed59f2fd 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/IssuesMediumTest.java @@ -66,7 +66,7 @@ public class IssuesMediumTest { .newScanTask(new File(projectDir, "sonar-project.properties")) .start(); - assertThat(result.issues()).hasSize(26); + assertThat(result.issues()).hasSize(14); } @Test @@ -78,7 +78,7 @@ public class IssuesMediumTest { .property("sonar.xoo.internalKey", "OneIssuePerLine.internal") .start(); - assertThat(result.issues()).hasSize(26 /* 26 lines */+ 3 /* 3 files */); + assertThat(result.issues()).hasSize(14 /* 8 + 6 lines */+ 2 /* 2 files */); } @Test @@ -103,7 +103,7 @@ public class IssuesMediumTest { .property("sonar.issue.ignore.allfile.1.fileRegexp", "object") .start(); - assertThat(result.issues()).hasSize(20); + assertThat(result.issues()).hasSize(8); } @Test diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/ReportsMediumTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/ReportsMediumTest.java index 23f6b90f2c4..04c588ad63f 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/ReportsMediumTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issues/ReportsMediumTest.java @@ -20,6 +20,7 @@ package org.sonar.batch.mediumtest.issues; import com.google.common.collect.ImmutableMap; +import org.apache.commons.codec.digest.DigestUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -27,6 +28,7 @@ import org.junit.rules.TemporaryFolder; import org.sonar.batch.mediumtest.BatchMediumTester; import org.sonar.batch.mediumtest.TaskResult; import org.sonar.batch.protocol.input.ActiveRule; +import org.sonar.batch.protocol.input.issues.PreviousIssue; import org.sonar.xoo.XooPlugin; import java.io.File; @@ -43,6 +45,13 @@ public class ReportsMediumTest { .addDefaultQProfile("xoo", "Sonar Way") .activateRule(new ActiveRule("xoo", "OneIssuePerLine", "One issue per line", "MAJOR", "OneIssuePerLine.internal", "xoo")) .bootstrapProperties(ImmutableMap.of("sonar.analysis.mode", "sensor")) + .addPreviousIssue(new PreviousIssue().setKey("xyz") + .setComponentKey("sample:xources/hello/HelloJava.xoo") + .setRuleKey("xoo", "OneIssuePerLine") + .setLine(1) + .setOverriddenSeverity("MAJOR") + .setChecksum(DigestUtils.md5Hex("packagehello;")) + .setStatus("OPEN")) .build(); @Before @@ -64,7 +73,7 @@ public class ReportsMediumTest { .property("sonar.issuesReport.console.enable", "true") .start(); - assertThat(result.issues()).hasSize(26); + assertThat(result.issues()).hasSize(14); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/referential/DefaultProjectReferentialsLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectReferentialsLoaderTest.java index 2a66a09cc59..108151f5aac 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/referential/DefaultProjectReferentialsLoaderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectReferentialsLoaderTest.java @@ -17,7 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package org.sonar.batch.referential; +package org.sonar.batch.repository; + +import org.sonar.batch.repository.DefaultProjectReferentialsLoader; import com.google.common.collect.Maps; import org.junit.Before; @@ -29,7 +31,6 @@ import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.ServerClient; import org.sonar.batch.bootstrap.TaskProperties; import org.sonar.batch.rule.ModuleQProfiles; - import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java index 6a8e64d6ccf..2c03cd472f4 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java @@ -29,7 +29,7 @@ import org.sonar.api.config.PropertyDefinitions; import org.sonar.api.utils.MessageException; import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.GlobalSettings; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import java.util.List; @@ -42,12 +42,12 @@ public class ModuleSettingsTest { @Rule public ExpectedException thrown = ExpectedException.none(); - ProjectReferentials projectRef; + ProjectRepository projectRef; private AnalysisMode mode; @Before public void before() { - projectRef = new ProjectReferentials(); + projectRef = new ProjectRepository(); mode = mock(AnalysisMode.class); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java index ca6a0aa84e5..3326102185e 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectScanContainerTest.java @@ -19,6 +19,8 @@ */ package org.sonar.batch.scan; +import org.sonar.batch.repository.ProjectRepositoriesLoader; + import org.junit.Before; import org.junit.Test; import org.sonar.api.BatchExtension; @@ -41,8 +43,7 @@ import org.sonar.batch.bootstrap.GlobalSettings; import org.sonar.batch.bootstrap.TaskProperties; import org.sonar.batch.profiling.PhasesSumUpTimeProfiler; import org.sonar.batch.protocol.input.GlobalReferentials; -import org.sonar.batch.protocol.input.ProjectReferentials; -import org.sonar.batch.referential.ProjectReferentialsLoader; +import org.sonar.batch.protocol.input.ProjectRepository; import org.sonar.batch.scan.maven.MavenPluginExecutor; import java.util.Collections; @@ -72,10 +73,10 @@ public class ProjectScanContainerTest { GlobalReferentials globalRef = new GlobalReferentials(); settings = new GlobalSettings(bootstrapProperties, new PropertyDefinitions(), globalRef, analysisMode); parentContainer.add(settings); - ProjectReferentialsLoader projectReferentialsLoader = new ProjectReferentialsLoader() { + ProjectRepositoriesLoader projectReferentialsLoader = new ProjectRepositoriesLoader() { @Override - public ProjectReferentials load(ProjectReactor reactor, TaskProperties taskProperties) { - return new ProjectReferentials(); + public ProjectRepository load(ProjectReactor reactor, TaskProperties taskProperties) { + return new ProjectRepository(); } }; parentContainer.add(projectReferentialsLoader); diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java index c75f7aafb3d..69db0207a8b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java @@ -33,7 +33,7 @@ import org.sonar.batch.bootstrap.AnalysisMode; import org.sonar.batch.bootstrap.BootstrapProperties; import org.sonar.batch.bootstrap.GlobalSettings; import org.sonar.batch.protocol.input.GlobalReferentials; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import java.util.Collections; @@ -46,7 +46,7 @@ public class ProjectSettingsTest { @Rule public ExpectedException thrown = ExpectedException.none(); - ProjectReferentials projectRef; + ProjectRepository projectRef; ProjectDefinition project = ProjectDefinition.create().setKey("struts"); GlobalSettings bootstrapProps; @@ -54,7 +54,7 @@ public class ProjectSettingsTest { @Before public void prepare() { - projectRef = new ProjectReferentials(); + projectRef = new ProjectRepository(); mode = mock(AnalysisMode.class); bootstrapProps = new GlobalSettings(new BootstrapProperties(Collections.<String, String>emptyMap()), new PropertyDefinitions(), new GlobalReferentials(), mode); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java index e6c73e80fd7..7b01635b67e 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/FileMetadataTest.java @@ -77,9 +77,9 @@ public class FileMetadataTest { assertThat(metadata.lines).isEqualTo(4); assertThat(metadata.hash).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n")); assertThat(metadata.originalLineOffsets).containsOnly(0, 5, 10, 18); - assertThat(metadata.lineHashes[0]).containsOnly(md5("föo")); - assertThat(metadata.lineHashes[1]).containsOnly(md5("bàr")); - assertThat(metadata.lineHashes[2]).containsOnly(md5("\u1D11Ebaßz")); + assertThat(metadata.lineHashes[0]).containsExactly(md5("föo")); + assertThat(metadata.lineHashes[1]).containsExactly(md5("bàr")); + assertThat(metadata.lineHashes[2]).containsExactly(md5("\u1D11Ebaßz")); assertThat(metadata.lineHashes[3]).isNull(); } @@ -92,9 +92,9 @@ public class FileMetadataTest { assertThat(metadata.lines).isEqualTo(4); assertThat(metadata.hash).isEqualTo(md5Hex("föo\nbàr\n\u1D11Ebaßz\n")); assertThat(metadata.originalLineOffsets).containsOnly(0, 5, 10, 18); - assertThat(metadata.lineHashes[0]).containsOnly(md5("föo")); - assertThat(metadata.lineHashes[1]).containsOnly(md5("bàr")); - assertThat(metadata.lineHashes[2]).containsOnly(md5("\u1D11Ebaßz")); + assertThat(metadata.lineHashes[0]).containsExactly(md5("föo")); + assertThat(metadata.lineHashes[1]).containsExactly(md5("bàr")); + assertThat(metadata.lineHashes[2]).containsExactly(md5("\u1D11Ebaßz")); assertThat(metadata.lineHashes[3]).isNull(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java index 5b1badcd0a5..ddc9d1d376b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java @@ -20,7 +20,7 @@ package org.sonar.batch.scan.filesystem; import org.junit.Test; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; @@ -28,7 +28,7 @@ import static org.mockito.Mockito.mock; public class StatusDetectionFactoryTest { @Test public void testCreate() throws Exception { - StatusDetectionFactory factory = new StatusDetectionFactory(mock(ProjectReferentials.class)); + StatusDetectionFactory factory = new StatusDetectionFactory(mock(ProjectRepository.class)); StatusDetection detection = factory.create(); assertThat(detection).isNotNull(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java index df3a94ce132..ca3282fc393 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java @@ -22,14 +22,14 @@ package org.sonar.batch.scan.filesystem; import org.junit.Test; import org.sonar.api.batch.fs.InputFile; import org.sonar.batch.protocol.input.FileData; -import org.sonar.batch.protocol.input.ProjectReferentials; +import org.sonar.batch.protocol.input.ProjectRepository; import static org.assertj.core.api.Assertions.assertThat; public class StatusDetectionTest { @Test public void detect_status() throws Exception { - ProjectReferentials ref = new ProjectReferentials(); + ProjectRepository ref = new ProjectRepository(); ref.addFileData("foo", "src/Foo.java", new FileData("ABCDE", true, null, null, null)); ref.addFileData("foo", "src/Bar.java", new FileData("FGHIJ", true, null, null, null)); StatusDetection statusDetection = new StatusDetection(ref); diff --git a/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/HelloJava.xoo.measures b/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/HelloJava.xoo.measures index 388d08b58a8..9eaf8ba2549 100644 --- a/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/HelloJava.xoo.measures +++ b/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/HelloJava.xoo.measures @@ -1,3 +1,2 @@ -lines:8 ncloc:3 complexity:1 diff --git a/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/helloscala.xoo.measures b/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/helloscala.xoo.measures index c47948fc955..d2c8386aed1 100644 --- a/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/helloscala.xoo.measures +++ b/sonar-batch/src/test/resources/mediumtest/xoo/sample/xources/hello/helloscala.xoo.measures @@ -1,3 +1,2 @@ -lines:5 ncloc:5 complexity:2 diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example1-v1.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example1-v1.txt index 1920333ddb6..1920333ddb6 100644 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example1-v1.txt +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example1-v1.txt diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example1-v2.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example1-v2.txt index 231532452b2..231532452b2 100644 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example1-v2.txt +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example1-v2.txt diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example2-v1.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example2-v1.txt index a920afe459b..a920afe459b 100644 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example2-v1.txt +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example2-v1.txt diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example2-v2.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example2-v2.txt index c5c8250cf65..c5c8250cf65 100644 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example2-v2.txt +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example2-v2.txt diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example3-v1.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example3-v1.txt index facdcbc008c..facdcbc008c 100644 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example3-v1.txt +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example3-v1.txt diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example3-v2.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example3-v2.txt index 91db843fc4d..91db843fc4d 100644 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/IssueTrackingTest/example3-v2.txt +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/tracking/IssueTrackingTest/example3-v2.txt diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java index cd8bf7c1a36..2b1ecfa0b33 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/FileSystem.java @@ -48,7 +48,7 @@ import java.util.SortedSet; * for example : * <pre> * DefaultFileSystem fs = new DefaultFileSystem(); - * fs.add(new DefaultInputFile("src/foo/bar.php")); + * fs.add(new DefaultInputFile("myprojectKey", "src/foo/bar.php")); * </pre> * * @since 4.2 |