diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java index 586f426434..2a99990a07 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java @@ -35,6 +35,7 @@ import org.sonar.api.batch.sensor.SensorDescriptor; import org.sonar.api.batch.sensor.issue.NewIssue; import org.sonar.api.batch.sensor.issue.NewIssueLocation; +import org.sonar.api.issue.NoSonarFilter; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.api.measures.Metric; @@ -89,6 +90,7 @@ public class CxxSquidSensor implements Sensor { private final FileLinesContextFactory fileLinesContextFactory; private final CxxChecks checks; + private final NoSonarFilter noSonarFilter; private final CxxLanguage language; @@ -97,8 +99,9 @@ public class CxxSquidSensor implements Sensor { */ public CxxSquidSensor(CxxLanguage language, FileLinesContextFactory fileLinesContextFactory, - CheckFactory checkFactory) { - this(language, fileLinesContextFactory, checkFactory, null); + CheckFactory checkFactory, + NoSonarFilter noSonarFilter) { + this(language, fileLinesContextFactory, checkFactory, noSonarFilter, null); } /** @@ -107,11 +110,13 @@ public CxxSquidSensor(CxxLanguage language, public CxxSquidSensor(CxxLanguage language, FileLinesContextFactory fileLinesContextFactory, CheckFactory checkFactory, + NoSonarFilter noSonarFilter, @Nullable CustomCxxRulesDefinition[] customRulesDefinition) { this.checks = CxxChecks.createCxxCheck(checkFactory) .addChecks(language.getRepositoryKey(), language.getChecks()) .addCustomChecks(customRulesDefinition); this.fileLinesContextFactory = fileLinesContextFactory; + this.noSonarFilter = noSonarFilter; this.language = language; } @@ -234,6 +239,10 @@ private void save(Collection squidSourceFiles, SensorContext context } private void saveMeasures(InputFile inputFile, SourceFile squidFile, SensorContext context) { + + // NOSONAR + noSonarFilter.noSonarInFile(inputFile, squidFile.getNoSonarTagLines()); + // CORE METRICS context.newMeasure().forMetric(CoreMetrics.NCLOC).on(inputFile) .withValue(squidFile.getInt(CxxMetric.LINES_OF_CODE)).save(); diff --git a/cxx-sensors/src/test/java/org/sonar/plugins/cxx/squid/CxxSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/plugins/cxx/squid/CxxSquidSensorTest.java index 9130f72e1f..ba1309bba4 100644 --- a/cxx-sensors/src/test/java/org/sonar/plugins/cxx/squid/CxxSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/plugins/cxx/squid/CxxSquidSensorTest.java @@ -37,6 +37,7 @@ import org.sonar.api.batch.rule.ActiveRules; import org.sonar.api.batch.rule.CheckFactory; import org.sonar.api.batch.sensor.internal.SensorContextTester; +import org.sonar.api.issue.NoSonarFilter; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.FileLinesContext; import org.sonar.api.measures.FileLinesContextFactory; @@ -69,6 +70,7 @@ public void setUp() { language, fileLinesContextFactory, checkFactory, + new NoSonarFilter(), null); } diff --git a/cxx-squid/src/main/java/org/sonar/cxx/visitors/CxxLinesOfCodeVisitor.java b/cxx-squid/src/main/java/org/sonar/cxx/visitors/CxxLinesOfCodeVisitor.java index 5bcca44cdd..c71530ca7f 100644 --- a/cxx-squid/src/main/java/org/sonar/cxx/visitors/CxxLinesOfCodeVisitor.java +++ b/cxx-squid/src/main/java/org/sonar/cxx/visitors/CxxLinesOfCodeVisitor.java @@ -24,8 +24,11 @@ import static com.sonar.sslr.api.GenericTokenType.EOF; import com.sonar.sslr.api.Grammar; import com.sonar.sslr.api.Token; +import com.sonar.sslr.api.Trivia; import java.util.regex.Pattern; import org.sonar.squidbridge.SquidAstVisitor; +import org.sonar.squidbridge.api.SourceCode; +import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.measures.MetricDef; /** @@ -34,7 +37,7 @@ * @param */ public class CxxLinesOfCodeVisitor - extends SquidAstVisitor implements AstAndTokenVisitor { + extends SquidAstVisitor implements AstAndTokenVisitor { public static final Pattern EOL_PATTERN = Pattern.compile("\\R"); @@ -58,14 +61,42 @@ public void visitFile(AstNode node) { */ @Override public void visitToken(Token token) { - if (!token.getType().equals(EOF)) { - /* Handle all the lines of the token */ - String[] tokenLines = EOL_PATTERN.split(token.getValue(), -1); + if (token.getType().equals(EOF)) { + return; + } + + // handle all the lines of the token + String[] tokenLines = EOL_PATTERN.split(token.getValue(), -1); + + int firstLineAlreadyCounted = lastTokenLine == token.getLine() ? 1 : 0; + getContext().peekSourceCode().add(metric, (double) tokenLines.length - firstLineAlreadyCounted); - int firstLineAlreadyCounted = lastTokenLine == token.getLine() ? 1 : 0; - getContext().peekSourceCode().add(metric, (double) tokenLines.length - firstLineAlreadyCounted); + lastTokenLine = token.getLine() + tokenLines.length - 1; + + // handle comments + for (Trivia trivia : token.getTrivia()) { + if (trivia.isComment()) { + visitComment(trivia); + } + } + } + + /** + * Search in comments for NOSONAR + */ + public void visitComment(Trivia trivia) { + String[] commentLines = EOL_PATTERN + .split(getContext().getCommentAnalyser().getContents(trivia.getToken().getOriginalValue()), -1); + int line = trivia.getToken().getLine(); - lastTokenLine = token.getLine() + tokenLines.length - 1; + for (String commentLine : commentLines) { + if (commentLine.contains("NOSONAR")) { + SourceCode sourceCode = getContext().peekSourceCode(); + if (sourceCode instanceof SourceFile) { + ((SourceFile) sourceCode).hasNoSonarTagAtLine(line); + } + } + line++; } } diff --git a/cxx-squid/src/test/java/org/sonar/cxx/CxxAstScannerTest.java b/cxx-squid/src/test/java/org/sonar/cxx/CxxAstScannerTest.java index 0acb900eb1..620a38a6b5 100644 --- a/cxx-squid/src/test/java/org/sonar/cxx/CxxAstScannerTest.java +++ b/cxx-squid/src/test/java/org/sonar/cxx/CxxAstScannerTest.java @@ -25,6 +25,8 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; +import java.util.List; +import java.util.Set; import static org.assertj.core.api.Assertions.assertThat; import org.assertj.core.api.SoftAssertions; import org.junit.Test; @@ -125,4 +127,11 @@ public void error_recovery_declaration() throws UnsupportedEncodingException, IO assertThat(file.getInt(CxxMetric.FUNCTIONS)).isEqualTo(2); } + @Test + public void nosonar_comments() throws UnsupportedEncodingException, IOException { + CxxFileTester tester = CxxFileTesterHelper.CreateCxxFileTester("src/test/resources/metrics/nosonar.cc", ".", ""); + SourceFile file = CxxAstScanner.scanSingleFile(tester.cxxFile, tester.sensorContext, CxxFileTesterHelper.mockCxxLanguage()); + assertThat(file.getNoSonarTagLines()).containsOnlyElementsOf(Arrays.asList(3, 6, 9, 11)); + } + } diff --git a/cxx-squid/src/test/resources/metrics/nosonar.cc b/cxx-squid/src/test/resources/metrics/nosonar.cc new file mode 100644 index 0000000000..83538969b8 --- /dev/null +++ b/cxx-squid/src/test/resources/metrics/nosonar.cc @@ -0,0 +1,13 @@ +/* Header */ + +/* NOSONAR */ +int a; + +// NOSONAR +int b; + +int c; /* NOSONAR */ + +int d; // NOSONAR + +/* EOF '/ diff --git a/sonar-c-plugin/src/main/java/org/sonar/plugins/c/CPlugin.java b/sonar-c-plugin/src/main/java/org/sonar/plugins/c/CPlugin.java index b00add4de7..02c73eec55 100644 --- a/sonar-c-plugin/src/main/java/org/sonar/plugins/c/CPlugin.java +++ b/sonar-c-plugin/src/main/java/org/sonar/plugins/c/CPlugin.java @@ -30,6 +30,7 @@ import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.config.Configuration; import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.issue.NoSonarFilter; import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metrics; @@ -688,15 +689,17 @@ public static class CxxSquidSensorImpl extends CxxSquidSensor { public CxxSquidSensorImpl(Configuration settings, FileLinesContextFactory fileLinesContextFactory, - CheckFactory checkFactory) { - super(new CLanguage(settings), fileLinesContextFactory, checkFactory); + CheckFactory checkFactory, + NoSonarFilter noSonarFilter) { + super(new CLanguage(settings), fileLinesContextFactory, checkFactory, noSonarFilter); } public CxxSquidSensorImpl(Configuration settings, FileLinesContextFactory fileLinesContextFactory, CheckFactory checkFactory, + NoSonarFilter noSonarFilter, @Nullable CustomCxxRulesDefinition[] customRulesDefinition) { - super(new CLanguage(settings), fileLinesContextFactory, checkFactory, customRulesDefinition); + super(new CLanguage(settings), fileLinesContextFactory, checkFactory, noSonarFilter, customRulesDefinition); } } diff --git a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java index a958d64e78..9718a295ad 100644 --- a/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java +++ b/sonar-cxx-plugin/src/main/java/org/sonar/plugins/cxx/CxxPlugin.java @@ -30,6 +30,7 @@ import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.config.Configuration; import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.issue.NoSonarFilter; import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metrics; @@ -741,15 +742,17 @@ public static class CxxSquidSensorImpl extends CxxSquidSensor { public CxxSquidSensorImpl(Configuration settings, FileLinesContextFactory fileLinesContextFactory, - CheckFactory checkFactory) { - super(new CppLanguage(settings), fileLinesContextFactory, checkFactory); + CheckFactory checkFactory, + NoSonarFilter noSonarFilter) { + super(new CppLanguage(settings), fileLinesContextFactory, checkFactory, noSonarFilter); } public CxxSquidSensorImpl(Configuration settings, FileLinesContextFactory fileLinesContextFactory, CheckFactory checkFactory, + NoSonarFilter noSonarFilter, @Nullable CustomCxxRulesDefinition[] customRulesDefinition) { - super(new CppLanguage(settings), fileLinesContextFactory, checkFactory, customRulesDefinition); + super(new CppLanguage(settings), fileLinesContextFactory, checkFactory, noSonarFilter, customRulesDefinition); } }