Skip to content
This repository has been archived by the owner on Feb 13, 2024. It is now read-only.

Commit

Permalink
SONAR-2782 Fix detection of false-positive duplication in case of cha…
Browse files Browse the repository at this point in the history
…in of cases
  • Loading branch information
Godin committed Sep 27, 2011
1 parent c7c56a4 commit 438d363
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 12 deletions.
Expand Up @@ -43,8 +43,8 @@ public static StatementChunker build() {
.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();
}
Expand Down
@@ -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));
}

}
Expand Up @@ -127,17 +127,33 @@ public void shouldHandleSwitch() {
"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
Expand Down

0 comments on commit 438d363

Please sign in to comment.