diff options
author | Evgeny Mandrikov <mandrikov@gmail.com> | 2011-09-27 11:01:56 +0400 |
---|---|---|
committer | Evgeny Mandrikov <mandrikov@gmail.com> | 2011-09-27 12:59:40 +0400 |
commit | 591faa52ca6342ce9efef999d726bbfcac13462b (patch) | |
tree | acfad8ea9d231ce9a3b5552cd20781afe0746145 | |
parent | 75fc94e0b6f64c29f2c08d999715966319eee311 (diff) | |
download | sonarqube-591faa52ca6342ce9efef999d726bbfcac13462b.tar.gz sonarqube-591faa52ca6342ce9efef999d726bbfcac13462b.zip |
SONAR-2782 Fix detection of false-positive duplication in case of chain of cases
3 files changed, 123 insertions, 12 deletions
diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/java/JavaStatementBuilder.java b/sonar-duplications/src/main/java/org/sonar/duplications/java/JavaStatementBuilder.java index e783cd3c758..66917fa87d1 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/java/JavaStatementBuilder.java +++ b/sonar-duplications/src/main/java/org/sonar/duplications/java/JavaStatementBuilder.java @@ -43,8 +43,8 @@ public final class JavaStatementBuilder { .statement(from("else")) .statement(from("for"), bridge("(", ")")) .statement(from("while"), bridge("(", ")")) - .statement(from("case"), to(":")) - .statement(from("default"), to(":")) + .statement(from("case"), to(";", "{", "}"), forgetLastToken()) + .statement(from("default"), to(";", "{", "}"), forgetLastToken()) .statement(to(";", "{", "}"), forgetLastToken()) .build(); } diff --git a/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaDuplicationsFunctionalTest.java b/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaDuplicationsFunctionalTest.java new file mode 100644 index 00000000000..c9a1c1b90c7 --- /dev/null +++ b/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaDuplicationsFunctionalTest.java @@ -0,0 +1,95 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2011 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.duplications.java; + +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertThat; + +import java.util.List; + +import org.junit.Test; +import org.sonar.duplications.block.Block; +import org.sonar.duplications.block.BlockChunker; +import org.sonar.duplications.detector.original.OriginalCloneDetectionAlgorithm; +import org.sonar.duplications.index.CloneGroup; +import org.sonar.duplications.index.MemoryCloneIndex; +import org.sonar.duplications.statement.Statement; +import org.sonar.duplications.statement.StatementChunker; +import org.sonar.duplications.token.TokenChunker; + +import com.google.common.base.Joiner; + +public class JavaDuplicationsFunctionalTest { + + private static final int BLOCK_SIZE = 1; + + private TokenChunker tokenChunker = JavaTokenProducer.build(); + private StatementChunker statementChunker = JavaStatementBuilder.build(); + private BlockChunker blockChunker = new BlockChunker(BLOCK_SIZE); + + private List<CloneGroup> detect(String... lines) { + String sourceCode = Joiner.on('\n').join(lines); + MemoryCloneIndex index = new MemoryCloneIndex(); + List<Statement> statements = statementChunker.chunk(tokenChunker.chunk(sourceCode)); + List<Block> blocks = blockChunker.chunk("resourceId", statements); + for (Block block : blocks) { + index.insert(block); + } + return OriginalCloneDetectionAlgorithm.detect(index, blocks); + } + + /** + * See SONAR-2837 + */ + @Test + public void initializationOfMultidimensionalArray() { + List<CloneGroup> duplications = detect("int[][] idx = new int[][] { { 1, 2 }, { 3, 4 } };"); + assertThat(duplications.size(), is(0)); + } + + /** + * See SONAR-2782 + */ + @Test + public void chainOfCases() { + List<CloneGroup> duplications = detect( + "switch (a) {", + " case 'a': case 'b': case 'c':", + " doSomething();", + " case 'd': case 'e': case 'f':", + " doSomethingElse();", + "}"); + assertThat(duplications.size(), is(0)); + } + + @Test + public void literalsNormalization() { + List<CloneGroup> duplications = detect( + "String s = \"abc\";", + "String s = \"def\";"); + assertThat(duplications.size(), is(1)); + + duplications = detect( + "int i = 1;", + "int i = 2;"); + assertThat(duplications.size(), is(1)); + } + +} diff --git a/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java b/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java index 59aa6ee04e6..e264233f5bc 100644 --- a/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java +++ b/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java @@ -127,17 +127,33 @@ public class JavaStatementBuilderTest { "switch (month) {" + " case 1 : monthString=\"January\"; break;" + " case 2 : monthString=\"February\"; break;" + - " default: monthString=\"Invalid\";"); - assertThat(statements.size(), is(9)); + " default: monthString=\"Invalid\";" + + "}"); + assertThat(statements.size(), is(6)); assertThat(statements.get(0).getValue(), is("switch(month)")); - assertThat(statements.get(1).getValue(), is("case$NUMBER:")); - assertThat(statements.get(2).getValue(), is("monthString=$CHARS")); - assertThat(statements.get(3).getValue(), is("break")); - assertThat(statements.get(4).getValue(), is("case$NUMBER:")); - assertThat(statements.get(5).getValue(), is("monthString=$CHARS")); - assertThat(statements.get(6).getValue(), is("break")); - assertThat(statements.get(7).getValue(), is("default:")); - assertThat(statements.get(8).getValue(), is("monthString=$CHARS")); + assertThat(statements.get(1).getValue(), is("case$NUMBER:monthString=$CHARS")); + assertThat(statements.get(2).getValue(), is("break")); + assertThat(statements.get(3).getValue(), is("case$NUMBER:monthString=$CHARS")); + assertThat(statements.get(4).getValue(), is("break")); + assertThat(statements.get(5).getValue(), is("default:monthString=$CHARS")); + } + + /** + * See SONAR-2782 + */ + @Test + public void shouldHandleNestedSwitch() { + List<Statement> statements = chunk("" + + "switch (a) {" + + " case 'a': case 'b': case 'c': something(); break;" + + " case 'd': case 'e': case 'f': somethingOther(); break;" + + "}"); + assertThat(statements.size(), is(5)); + assertThat(statements.get(0).getValue(), is("switch(a)")); + assertThat(statements.get(1).getValue(), is("case$CHARS:case$CHARS:case$CHARS:something()")); + assertThat(statements.get(2).getValue(), is("break")); + assertThat(statements.get(3).getValue(), is("case$CHARS:case$CHARS:case$CHARS:somethingOther()")); + assertThat(statements.get(4).getValue(), is("break")); } @Test |