]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-16039 - Migrate existing issues to new_code table
authorBelen Pruvost <belen.pruvost@sonarsource.com>
Tue, 29 Mar 2022 08:40:53 +0000 (10:40 +0200)
committersonartech <sonartech@sonarsource.com>
Thu, 31 Mar 2022 20:02:59 +0000 (20:02 +0000)
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IntegrateIssuesVisitor.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/issue/IssueOnReferenceBranchVisitor.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStep.java
server/sonar-ce-task-projectanalysis/src/main/java/org/sonar/ce/task/projectanalysis/util/cache/ProtobufIssueDiskCache.java
server/sonar-ce-task-projectanalysis/src/main/protobuf/issue_cache.proto
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/issue/IssuesOnReferenceBranchVisitorTest.java
server/sonar-ce-task-projectanalysis/src/test/java/org/sonar/ce/task/projectanalysis/step/PersistIssuesStepTest.java
server/sonar-db-dao/src/main/java/org/sonar/db/issue/NewCodeReferenceIssueDto.java
server/sonar-db-dao/src/test/java/org/sonar/db/issue/NewCodeReferenceIssueDtoTest.java
sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java

index 47af93eaade5067af9745116ab62d5853ac7c871..5a322ab7ca1636bbe0046c4c3e5c8e95e2e1043d 100644 (file)
@@ -127,7 +127,8 @@ public class IntegrateIssuesVisitor extends TypeAwareVisitorAdapter {
   private void process(Component component, DefaultIssue issue, CacheAppender<DefaultIssue> cacheAppender) {
     issueLifecycle.doAutomaticTransition(issue);
     issueVisitors.onIssue(component, issue);
-    if (issue.isNew() || issue.isChanged() || issue.isCopied() || issue.isNoLongerNewCodeReferenceIssue()) {
+    if (issue.isNew() || issue.isChanged() || issue.isCopied() ||
+      issue.isNoLongerNewCodeReferenceIssue() || issue.isToBeMigratedAsNewCodeReferenceIssue()) {
       cacheAppender.append(issue);
     }
   }
index 61c78246511105cf90343811c797710cf8abe900..8f2e811c9975e846ee7170486feabc41efd6c39e 100644 (file)
@@ -36,9 +36,7 @@ public class IssueOnReferenceBranchVisitor extends IssueVisitor {
       return;
     }
 
-    issue.setIsOnReferencedBranch(newIssueClassifier.isOnBranchUsingReferenceBranch());
-
-    if (issue.isOnReferencedBranch()) {
+    if (newIssueClassifier.isOnBranchUsingReferenceBranch()) {
       issue.setIsOnChangedLine(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue));
 
       if (issue.isNewCodeReferenceIssue() && !issue.isOnChangedLine()) {
index c3721d357f82810188b75fcc4a50d211b0d73e36..379a7cc255b60e3e44bf46f111fdbd9eadcbc15c 100644 (file)
@@ -26,6 +26,7 @@ import org.sonar.api.utils.System2;
 import org.sonar.ce.task.projectanalysis.issue.ProtoIssueCache;
 import org.sonar.ce.task.projectanalysis.issue.RuleRepository;
 import org.sonar.ce.task.projectanalysis.issue.UpdateConflictResolver;
+import org.sonar.ce.task.projectanalysis.period.PeriodHolder;
 import org.sonar.ce.task.step.ComputationStep;
 import org.sonar.core.issue.DefaultIssue;
 import org.sonar.core.util.CloseableIterator;
@@ -37,6 +38,7 @@ import org.sonar.db.issue.IssueChangeMapper;
 import org.sonar.db.issue.IssueDto;
 import org.sonar.db.issue.IssueMapper;
 import org.sonar.db.issue.NewCodeReferenceIssueDto;
+import org.sonar.db.newcodeperiod.NewCodePeriodType;
 import org.sonar.server.issue.IssueStorage;
 
 import static org.sonar.core.util.FileUtils.humanReadableByteCountSI;
@@ -52,16 +54,19 @@ public class PersistIssuesStep implements ComputationStep {
   private final System2 system2;
   private final UpdateConflictResolver conflictResolver;
   private final RuleRepository ruleRepository;
+  private final PeriodHolder periodHolder;
   private final ProtoIssueCache protoIssueCache;
   private final IssueStorage issueStorage;
   private final UuidFactory uuidFactory;
 
   public PersistIssuesStep(DbClient dbClient, System2 system2, UpdateConflictResolver conflictResolver,
-    RuleRepository ruleRepository, ProtoIssueCache protoIssueCache, IssueStorage issueStorage, UuidFactory uuidFactory) {
+    RuleRepository ruleRepository, PeriodHolder periodHolder, ProtoIssueCache protoIssueCache, IssueStorage issueStorage,
+    UuidFactory uuidFactory) {
     this.dbClient = dbClient;
     this.system2 = system2;
     this.conflictResolver = conflictResolver;
     this.ruleRepository = ruleRepository;
+    this.periodHolder = periodHolder;
     this.protoIssueCache = protoIssueCache;
     this.issueStorage = issueStorage;
     this.uuidFactory = uuidFactory;
@@ -76,6 +81,7 @@ public class PersistIssuesStep implements ComputationStep {
       List<DefaultIssue> addedIssues = new ArrayList<>(ISSUE_BATCHING_SIZE);
       List<DefaultIssue> updatedIssues = new ArrayList<>(ISSUE_BATCHING_SIZE);
       List<DefaultIssue> noLongerNewIssues = new ArrayList<>(ISSUE_BATCHING_SIZE);
+      List<DefaultIssue> newCodeIssuesToMigrate = new ArrayList<>(ISSUE_BATCHING_SIZE);
 
       IssueMapper mapper = dbSession.getMapper(IssueMapper.class);
       IssueChangeMapper changeMapper = dbSession.getMapper(IssueChangeMapper.class);
@@ -93,17 +99,24 @@ public class PersistIssuesStep implements ComputationStep {
             persistUpdatedIssues(statistics, updatedIssues, mapper, changeMapper);
             updatedIssues.clear();
           }
-        } else if (issue.isNoLongerNewCodeReferenceIssue()) {
+        } else if (isOnBranchUsingReferenceBranch() && issue.isNoLongerNewCodeReferenceIssue()) {
           noLongerNewIssues.add(issue);
           if (noLongerNewIssues.size() >= ISSUE_BATCHING_SIZE) {
             persistNoLongerNewIssues(statistics, noLongerNewIssues, mapper);
             noLongerNewIssues.clear();
           }
+        } else if (isOnBranchUsingReferenceBranch() && issue.isToBeMigratedAsNewCodeReferenceIssue()) {
+          newCodeIssuesToMigrate.add(issue);
+          if (newCodeIssuesToMigrate.size() >= ISSUE_BATCHING_SIZE) {
+            persistNewCodeIssuesToMigrate(statistics, newCodeIssuesToMigrate, mapper);
+            newCodeIssuesToMigrate.clear();
+          }
         }
       }
       persistNewIssues(statistics, addedIssues, mapper, changeMapper);
       persistUpdatedIssues(statistics, updatedIssues, mapper, changeMapper);
       persistNoLongerNewIssues(statistics, noLongerNewIssues, mapper);
+      persistNewCodeIssuesToMigrate(statistics, newCodeIssuesToMigrate, mapper);
       flushSession(dbSession);
     } finally {
       statistics.dumpTo(context);
@@ -120,7 +133,7 @@ public class PersistIssuesStep implements ComputationStep {
       String ruleUuid = ruleRepository.getByKey(i.ruleKey()).getUuid();
       IssueDto dto = IssueDto.toDtoForComputationInsert(i, ruleUuid, now);
       mapper.insert(dto);
-      if (i.isOnReferencedBranch() && i.isOnChangedLine()) {
+      if (isOnBranchUsingReferenceBranch() && i.isOnChangedLine()) {
         mapper.insertAsNewCodeOnReferenceBranch(NewCodeReferenceIssueDto.fromIssueDto(dto, now, uuidFactory));
       }
       statistics.inserts++;
@@ -169,11 +182,30 @@ public class PersistIssuesStep implements ComputationStep {
 
   }
 
+  private void persistNewCodeIssuesToMigrate(IssueStatistics statistics, List<DefaultIssue> newCodeIssuesToMigrate, IssueMapper mapper) {
+    if (newCodeIssuesToMigrate.isEmpty()) {
+      return;
+    }
+
+    long now = system2.now();
+    newCodeIssuesToMigrate.forEach(i -> {
+      mapper.insertAsNewCodeOnReferenceBranch(NewCodeReferenceIssueDto.fromIssueKey(i.key(), now, uuidFactory));
+      statistics.updates++;
+    });
+  }
+
   private static void flushSession(DbSession dbSession) {
     dbSession.flushStatements();
     dbSession.commit();
   }
 
+  private boolean isOnBranchUsingReferenceBranch() {
+    if (periodHolder.hasPeriod()) {
+      return periodHolder.getPeriod().getMode().equals(NewCodePeriodType.REFERENCE_BRANCH.name());
+    }
+    return false;
+  }
+
   @Override
   public String getDescription() {
     return "Persist issues";
index 452751ba1ceb035aaccf3409861b6fc23dde0283..74650b078189424d14e1ba8ca8923123575529dd 100644 (file)
@@ -122,8 +122,8 @@ public class ProtobufIssueDiskCache implements DiskCache<DefaultIssue> {
     defaultIssue.setCloseDate(next.hasCloseDate() ? new Date(next.getCloseDate()) : null);
     defaultIssue.setCurrentChangeWithoutAddChange(next.hasCurrentChanges() ? toDefaultIssueChanges(next.getCurrentChanges()) : null);
     defaultIssue.setNew(next.getIsNew());
-    defaultIssue.setIsOnReferencedBranch(next.getIsOnReferencedBranch());
     defaultIssue.setIsOnChangedLine(next.getIsOnChangedLine());
+    defaultIssue.setIsNewCodeReferenceIssue(next.getIsNewCodeReferenceIssue());
     defaultIssue.setCopied(next.getIsCopied());
     defaultIssue.setBeingClosed(next.getBeingClosed());
     defaultIssue.setOnDisabledRule(next.getOnDisabledRule());
@@ -172,8 +172,8 @@ public class ProtobufIssueDiskCache implements DiskCache<DefaultIssue> {
     ofNullable(defaultIssue.closeDate()).map(Date::getTime).ifPresent(builder::setCloseDate);
     ofNullable(defaultIssue.currentChange()).ifPresent(c -> builder.setCurrentChanges(toProtoIssueChanges(c)));
     builder.setIsNew(defaultIssue.isNew());
-    builder.setIsOnReferencedBranch(defaultIssue.isOnReferencedBranch());
     builder.setIsOnChangedLine(defaultIssue.isOnChangedLine());
+    builder.setIsNewCodeReferenceIssue(defaultIssue.isNewCodeReferenceIssue());
     builder.setIsCopied(defaultIssue.isCopied());
     builder.setBeingClosed(defaultIssue.isBeingClosed());
     builder.setOnDisabledRule(defaultIssue.isOnDisabledRule());
index dbd6942998a24ac9733beb3bbeef0b746c394d7f..24b2198c4f6616ea96e93ff044b54013cec0cdc7 100644 (file)
@@ -77,7 +77,8 @@ message Issue {
 
   optional bool isOnReferencedBranch = 40;
   optional bool isOnChangedLine = 41;
-  optional bool isNoLongerNewCodeReferenceIssue = 42;
+  optional bool isNewCodeReferenceIssue = 42;
+  optional bool isNoLongerNewCodeReferenceIssue = 43;
 }
 
 message Comment {
index 1cb26f570b606c06b9570bcd3d46436ff43e0c29..693d665fcb46ee437568139782bd47faa746e129 100644 (file)
@@ -51,8 +51,6 @@ public class IssuesOnReferenceBranchVisitorTest {
     when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(false);
 
     underTest.onIssue(component, issue);
-    verify(issue).setIsOnReferencedBranch(false);
-    verify(issue).isOnReferencedBranch();
     verifyNoMoreInteractions(issue);
   }
 
@@ -61,12 +59,9 @@ public class IssuesOnReferenceBranchVisitorTest {
     when(newIssueClassifier.isEnabled()).thenReturn(true);
     when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(true);
     when(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue)).thenReturn(true);
-    when(issue.isOnReferencedBranch()).thenReturn(true);
     when(issue.isNewCodeReferenceIssue()).thenReturn(false);
 
     underTest.onIssue(component, issue);
-    verify(issue).setIsOnReferencedBranch(true);
-    verify(issue).isOnReferencedBranch();
     verify(issue).setIsOnChangedLine(true);
     verify(issue).isNewCodeReferenceIssue();
     verifyNoMoreInteractions(issue);
@@ -77,13 +72,10 @@ public class IssuesOnReferenceBranchVisitorTest {
     when(newIssueClassifier.isEnabled()).thenReturn(true);
     when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(true);
     when(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue)).thenReturn(true);
-    when(issue.isOnReferencedBranch()).thenReturn(true);
     when(issue.isNewCodeReferenceIssue()).thenReturn(true);
     when(issue.isOnChangedLine()).thenReturn(true);
 
     underTest.onIssue(component, issue);
-    verify(issue).setIsOnReferencedBranch(true);
-    verify(issue).isOnReferencedBranch();
     verify(issue).setIsOnChangedLine(true);
     verify(issue).isNewCodeReferenceIssue();
     verify(issue).isOnChangedLine();
@@ -95,13 +87,10 @@ public class IssuesOnReferenceBranchVisitorTest {
     when(newIssueClassifier.isEnabled()).thenReturn(true);
     when(newIssueClassifier.isOnBranchUsingReferenceBranch()).thenReturn(true);
     when(newIssueClassifier.hasAtLeastOneLocationOnChangedLines(component, issue)).thenReturn(false);
-    when(issue.isOnReferencedBranch()).thenReturn(true);
     when(issue.isNewCodeReferenceIssue()).thenReturn(true);
     when(issue.isOnChangedLine()).thenReturn(false);
 
     underTest.onIssue(component, issue);
-    verify(issue).setIsOnReferencedBranch(true);
-    verify(issue).isOnReferencedBranch();
     verify(issue).setIsOnChangedLine(false);
     verify(issue).isNewCodeReferenceIssue();
     verify(issue).setIsNoLongerNewCodeReferenceIssue(true);
index dcc22097b8e9068f691e046c0fa3e100ef9dccc7..a3b66907a9b7ec0748ad5ca1832f16b34c4d2cc8 100644 (file)
@@ -36,6 +36,8 @@ import org.sonar.ce.task.projectanalysis.issue.AdHocRuleCreator;
 import org.sonar.ce.task.projectanalysis.issue.ProtoIssueCache;
 import org.sonar.ce.task.projectanalysis.issue.RuleRepositoryImpl;
 import org.sonar.ce.task.projectanalysis.issue.UpdateConflictResolver;
+import org.sonar.ce.task.projectanalysis.period.Period;
+import org.sonar.ce.task.projectanalysis.period.PeriodHolderRule;
 import org.sonar.ce.task.projectanalysis.util.cache.DiskCache;
 import org.sonar.ce.task.step.ComputationStep;
 import org.sonar.ce.task.step.TestComputationStepContext;
@@ -50,6 +52,7 @@ import org.sonar.db.component.ComponentDto;
 import org.sonar.db.issue.IssueChangeDto;
 import org.sonar.db.issue.IssueDto;
 import org.sonar.db.issue.IssueMapper;
+import org.sonar.db.newcodeperiod.NewCodePeriodType;
 import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.db.rule.RuleTesting;
 import org.sonar.scanner.protocol.output.ScannerReport;
@@ -80,6 +83,8 @@ public class PersistIssuesStepTest extends BaseStepTest {
   public DbTester db = DbTester.create(System2.INSTANCE);
   @Rule
   public BatchReportReaderRule reportReader = new BatchReportReaderRule();
+  @Rule
+  public PeriodHolderRule periodHolder = new PeriodHolderRule();
 
   private System2 system2 = mock(System2.class);
   private DbSession session = db.getSession();
@@ -97,11 +102,13 @@ public class PersistIssuesStepTest extends BaseStepTest {
 
   @Before
   public void setup() throws Exception {
+    periodHolder.setPeriod(new Period(NewCodePeriodType.NUMBER_OF_DAYS.name(), "10", 1000L));
+
     protoIssueCache = new ProtoIssueCache(temp.newFile(), System2.INSTANCE);
     reportReader.setMetadata(ScannerReport.Metadata.getDefaultInstance());
 
-    underTest = new PersistIssuesStep(dbClient, system2, conflictResolver, new RuleRepositoryImpl(adHocRuleCreator, dbClient), protoIssueCache,
-      new IssueStorage(), UuidFactoryImpl.INSTANCE);
+    underTest = new PersistIssuesStep(dbClient, system2, conflictResolver, new RuleRepositoryImpl(adHocRuleCreator, dbClient), periodHolder,
+      protoIssueCache, new IssueStorage(), UuidFactoryImpl.INSTANCE);
   }
 
   @After
@@ -173,6 +180,8 @@ public class PersistIssuesStepTest extends BaseStepTest {
 
   @Test
   public void insert_copied_issue_with_minimal_info() {
+    periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
+
     RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
     db.rules().insert(rule);
     ComponentDto project = db.components().insertPrivateProject();
@@ -191,7 +200,6 @@ public class PersistIssuesStepTest extends BaseStepTest {
         .setSeverity(BLOCKER)
         .setStatus(STATUS_OPEN)
         .setNew(false)
-        .setIsOnReferencedBranch(true)
         .setCopied(true)
         .setType(RuleType.BUG)
         .setCreationDate(new Date(NOW))
@@ -219,6 +227,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
 
   @Test
   public void insert_merged_issue() {
+    periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
     RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
     db.rules().insert(rule);
     ComponentDto project = db.components().insertPrivateProject();
@@ -237,7 +246,6 @@ public class PersistIssuesStepTest extends BaseStepTest {
         .setSeverity(BLOCKER)
         .setStatus(STATUS_OPEN)
         .setNew(true)
-        .setIsOnReferencedBranch(true)
         .setIsOnChangedLine(true)
         .setCopied(true)
         .setType(RuleType.BUG)
@@ -313,6 +321,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
 
   @Test
   public void insert_new_issue() {
+    periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
     RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
     db.rules().insert(rule);
     ComponentDto project = db.components().insertPrivateProject();
@@ -332,7 +341,6 @@ public class PersistIssuesStepTest extends BaseStepTest {
       .setStatus(STATUS_OPEN)
       .setCreationDate(new Date(NOW))
       .setNew(true)
-      .setIsOnReferencedBranch(true)
       .setIsOnChangedLine(true)
       .setType(RuleType.BUG)).close();
 
@@ -385,6 +393,7 @@ public class PersistIssuesStepTest extends BaseStepTest {
 
   @Test
   public void handle_no_longer_new_issue() {
+    periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
     RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
     db.rules().insert(rule);
     ComponentDto project = db.components().insertPrivateProject();
@@ -403,7 +412,6 @@ public class PersistIssuesStepTest extends BaseStepTest {
       .setSeverity(BLOCKER)
       .setStatus(STATUS_OPEN)
       .setNew(true)
-      .setIsOnReferencedBranch(true)
       .setIsOnChangedLine(true)
       .setIsNewCodeReferenceIssue(true)
       .setIsNoLongerNewCodeReferenceIssue(false)
@@ -421,7 +429,6 @@ public class PersistIssuesStepTest extends BaseStepTest {
     assertThat(result.isNewCodeReferenceIssue()).isTrue();
 
     protoIssueCache.newAppender().append(defaultIssue.setNew(false)
-        .setIsOnReferencedBranch(true)
         .setIsOnChangedLine(false)
         .setIsNewCodeReferenceIssue(false)
         .setIsNoLongerNewCodeReferenceIssue(true))
@@ -437,6 +444,109 @@ public class PersistIssuesStepTest extends BaseStepTest {
     assertThat(result.isNewCodeReferenceIssue()).isFalse();
   }
 
+  @Test
+  public void handle_existing_new_code_issue_migration() {
+    periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
+    RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
+    db.rules().insert(rule);
+    ComponentDto project = db.components().insertPrivateProject();
+    ComponentDto file = db.components().insertComponent(newFileDto(project, null));
+    when(system2.now()).thenReturn(NOW);
+    String issueKey = "ISSUE-6";
+
+    DefaultIssue defaultIssue = new DefaultIssue()
+      .setKey(issueKey)
+      .setType(RuleType.CODE_SMELL)
+      .setRuleKey(rule.getKey())
+      .setComponentUuid(file.uuid())
+      .setComponentKey(file.getKey())
+      .setProjectUuid(project.uuid())
+      .setProjectKey(project.getKey())
+      .setSeverity(BLOCKER)
+      .setStatus(STATUS_OPEN)
+      .setNew(true)
+      .setCopied(false)
+      .setType(RuleType.BUG)
+      .setCreationDate(new Date(NOW))
+      .setSelectedAt(NOW);
+
+    IssueDto issueDto = IssueDto.toDtoForComputationInsert(defaultIssue, rule.getUuid(), NOW);
+    dbClient.issueDao().insert(session, issueDto);
+    session.commit();
+
+    IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
+    assertThat(result.isNewCodeReferenceIssue()).isFalse();
+
+    protoIssueCache.newAppender().append(defaultIssue.setNew(false)
+        .setIsOnChangedLine(true)
+        .setIsNewCodeReferenceIssue(false)
+        .setIsNoLongerNewCodeReferenceIssue(false))
+      .close();
+
+    TestComputationStepContext context = new TestComputationStepContext();
+    underTest.execute(context);
+
+    assertThat(context.getStatistics().getAll()).contains(
+      entry("inserts", "0"), entry("updates", "1"), entry("merged", "0"));
+
+    result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
+    assertThat(result.isNewCodeReferenceIssue()).isTrue();
+  }
+
+  @Test
+  public void handle_existing_without_need_for_new_code_issue_migration() {
+    periodHolder.setPeriod(new Period(NewCodePeriodType.REFERENCE_BRANCH.name(), "master", null));
+    RuleDefinitionDto rule = RuleTesting.newRule(RuleKey.of("xoo", "S01"));
+    db.rules().insert(rule);
+    ComponentDto project = db.components().insertPrivateProject();
+    ComponentDto file = db.components().insertComponent(newFileDto(project, null));
+    when(system2.now()).thenReturn(NOW);
+    String issueKey = "ISSUE-7";
+
+    DefaultIssue defaultIssue = new DefaultIssue()
+      .setKey(issueKey)
+      .setType(RuleType.CODE_SMELL)
+      .setRuleKey(rule.getKey())
+      .setComponentUuid(file.uuid())
+      .setComponentKey(file.getKey())
+      .setProjectUuid(project.uuid())
+      .setProjectKey(project.getKey())
+      .setSeverity(BLOCKER)
+      .setStatus(STATUS_OPEN)
+      .setNew(true)
+      .setIsOnChangedLine(true)
+      .setIsNewCodeReferenceIssue(true)
+      .setIsNoLongerNewCodeReferenceIssue(false)
+      .setCopied(false)
+      .setType(RuleType.BUG)
+      .setCreationDate(new Date(NOW))
+      .setSelectedAt(NOW);
+
+    IssueDto issueDto = IssueDto.toDtoForComputationInsert(defaultIssue, rule.getUuid(), NOW);
+    dbClient.issueDao().insert(session, issueDto);
+    dbClient.issueDao().insertAsNewCodeOnReferenceBranch(session, newCodeReferenceIssue(issueDto));
+    session.commit();
+
+    IssueDto result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
+    assertThat(result.isNewCodeReferenceIssue()).isTrue();
+
+    protoIssueCache.newAppender().append(defaultIssue.setNew(false)
+        .setIsOnChangedLine(false)
+        .setIsNewCodeReferenceIssue(true)
+        .setIsOnChangedLine(true)
+        .setIsNoLongerNewCodeReferenceIssue(false))
+      .close();
+
+    TestComputationStepContext context = new TestComputationStepContext();
+    underTest.execute(context);
+
+    assertThat(context.getStatistics().getAll()).contains(
+      entry("inserts", "0"), entry("updates", "0"), entry("merged", "0"));
+
+    result = dbClient.issueDao().selectOrFailByKey(session, issueKey);
+    assertThat(result.isNewCodeReferenceIssue()).isTrue();
+  }
+
   @Test
   public void add_comment() {
     ComponentDto project = db.components().insertPrivateProject();
@@ -497,6 +607,8 @@ public class PersistIssuesStepTest extends BaseStepTest {
           .setSelectedAt(NOW)
           .setNew(false)
           .setChanged(true)
+          .setIsOnChangedLine(false)
+          .setIsNewCodeReferenceIssue(false)
           .setCurrentChange(new FieldDiffs()
             .setIssueKey("ISSUE")
             .setUserUuid("john_uuid")
index 1ca29e296e6250bb2343e2730a35f29a897b22f7..719a12e7986d8a59f424ddd72b77767b9650d4ea 100644 (file)
@@ -66,4 +66,11 @@ public final class NewCodeReferenceIssueDto implements Serializable {
       .setIssueKey(issue.getKey())
       .setCreatedAt(now);
   }
+
+  public static NewCodeReferenceIssueDto fromIssueKey(String issueKey, long now, UuidFactory uuidFactory) {
+    return new NewCodeReferenceIssueDto()
+      .setUuid(uuidFactory.create())
+      .setIssueKey(issueKey)
+      .setCreatedAt(now);
+  }
 }
index 2bcbd5d01892f9c92b873e936bbfb097384e07a4..ffa7d5dae2727762b70720ac9bdcb18ef100d546 100644 (file)
@@ -45,4 +45,16 @@ public class NewCodeReferenceIssueDtoTest {
     assertThat(dto.getIssueKey()).isEqualTo(KEY);
     assertThat(dto.getCreatedAt()).isNotNull();
   }
+
+  @Test
+  public void create_from_issue_key() {
+    when(UUID_FACTORY.create()).thenReturn(UUID);
+    long now = System.currentTimeMillis();
+
+    NewCodeReferenceIssueDto dto = NewCodeReferenceIssueDto.fromIssueKey(KEY, now, UUID_FACTORY);
+
+    assertThat(dto.getUuid()).isEqualTo(UUID);
+    assertThat(dto.getIssueKey()).isEqualTo(KEY);
+    assertThat(dto.getCreatedAt()).isNotNull();
+  }
 }
index 198bc25d418b4274fc4cf889d9b33ce3d6d597aa..b5d3a21c7bac57e9f32c8237c58236906706f921 100644 (file)
@@ -98,9 +98,6 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
   // true if the issue did not exist in the previous scan.
   private boolean isNew = true;
 
-  // true if the issue is on a branch using the reference branch new code strategy
-  private boolean isOnReferencedBranch = false;
-
   // true if the issue is on a changed line on a branch using the reference branch new code strategy
   private boolean isOnChangedLine = false;
 
@@ -396,10 +393,6 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
     return isNew;
   }
 
-  public boolean isOnReferencedBranch() {
-    return isOnReferencedBranch;
-  }
-
   public boolean isOnChangedLine() {
     return isOnChangedLine;
   }
@@ -419,11 +412,6 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
     return this;
   }
 
-  public DefaultIssue setIsOnReferencedBranch(boolean b) {
-    isOnReferencedBranch = b;
-    return this;
-  }
-
   public DefaultIssue setIsOnChangedLine(boolean b) {
     isOnChangedLine = b;
     return this;
@@ -554,6 +542,12 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
     return this;
   }
 
+  // true if the issue is new on a reference branch,
+  // but it's not persisted as such due to being created before the SQ 9.3 migration
+  public boolean isToBeMigratedAsNewCodeReferenceIssue() {
+    return isOnChangedLine && !isNewCodeReferenceIssue && !isNoLongerNewCodeReferenceIssue;
+  }
+
   @CheckForNull
   public FieldDiffs currentChange() {
     return currentChange;
index 97797a5a4961d5d1a2fdc6435178d8cf7d67ac4f..53d866457c00eb5e52ace969fc565e607d7bdca5 100644 (file)
@@ -19,7 +19,6 @@
  */
 package org.sonar.core.issue;
 
-import com.google.common.collect.ImmutableMap;
 import java.text.SimpleDateFormat;
 import java.util.List;
 import org.apache.commons.lang.StringUtils;
@@ -29,7 +28,6 @@ import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.Duration;
 
 import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.entry;
 import static org.junit.Assert.fail;
 import static org.mockito.Mockito.mock;
 
@@ -56,7 +54,6 @@ public class DefaultIssueTest {
       .setAuthorLogin("steph")
       .setChecksum("c7b5db46591806455cf082bb348631e8")
       .setNew(true)
-      .setIsOnReferencedBranch(true)
       .setIsOnChangedLine(true)
       .setIsNewCodeReferenceIssue(true)
       .setIsNoLongerNewCodeReferenceIssue(true)
@@ -87,10 +84,10 @@ public class DefaultIssueTest {
     assertThat(issue.authorLogin()).isEqualTo("steph");
     assertThat(issue.checksum()).isEqualTo("c7b5db46591806455cf082bb348631e8");
     assertThat(issue.isNew()).isTrue();
-    assertThat(issue.isOnReferencedBranch()).isTrue();
     assertThat(issue.isOnChangedLine()).isTrue();
     assertThat(issue.isNewCodeReferenceIssue()).isTrue();
     assertThat(issue.isNoLongerNewCodeReferenceIssue()).isTrue();
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse();
     assertThat(issue.isCopied()).isTrue();
     assertThat(issue.isBeingClosed()).isTrue();
     assertThat(issue.isOnDisabledRule()).isTrue();
@@ -208,6 +205,58 @@ public class DefaultIssueTest {
     assertThat(issue.changes()).isEmpty();
   }
 
+  @Test
+  public void test_isToBeMigratedAsNewCodeReferenceIssue_is_correctly_calculated() {
+    issue.setKey("ABCD")
+      .setIsOnChangedLine(true)
+      .setIsNewCodeReferenceIssue(false)
+      .setIsNoLongerNewCodeReferenceIssue(false);
+
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isTrue();
+
+    issue.setKey("ABCD")
+      .setIsOnChangedLine(false)
+      .setIsNewCodeReferenceIssue(false)
+      .setIsNoLongerNewCodeReferenceIssue(false);
+
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse();
+
+    issue.setKey("ABCD")
+      .setIsOnChangedLine(true)
+      .setIsNewCodeReferenceIssue(true)
+      .setIsNoLongerNewCodeReferenceIssue(false);
+
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse();
+
+    issue.setKey("ABCD")
+      .setIsOnChangedLine(false)
+      .setIsNewCodeReferenceIssue(false)
+      .setIsNoLongerNewCodeReferenceIssue(true);
+
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse();
+
+    issue.setKey("ABCD")
+      .setIsOnChangedLine(true)
+      .setIsNewCodeReferenceIssue(true)
+      .setIsNoLongerNewCodeReferenceIssue(true);
+
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse();
+
+    issue.setKey("ABCD")
+      .setIsOnChangedLine(false)
+      .setIsNewCodeReferenceIssue(true)
+      .setIsNoLongerNewCodeReferenceIssue(true);
+
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse();
+
+    issue.setKey("ABCD")
+      .setIsOnChangedLine(true)
+      .setIsNewCodeReferenceIssue(false)
+      .setIsNoLongerNewCodeReferenceIssue(true);
+
+    assertThat(issue.isToBeMigratedAsNewCodeReferenceIssue()).isFalse();
+  }
+
   @Test
   public void isQuickFixAvailable_givenQuickFixAvailable_returnTrue() {
     DefaultIssue defaultIssue = new DefaultIssue();