From 165f8e96631980aef749ec4fd946995f6b23c99e Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Thu, 18 Jan 2018 13:27:19 +0000 Subject: [PATCH 01/19] Adding extension point to CxxSquidSensor --- .../cxx/sensors/squid/CxxSquidSensor.java | 15 ++++++++ .../sonar/cxx/sensors/squid/SquidSensor.java | 33 +++++++++++++++++ .../plugins/cxx/squid/CxxSquidSensorTest.java | 37 ++++++++++++++++++- 3 files changed, 83 insertions(+), 2 deletions(-) create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java 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 5eeaff5692..d2dbca8e71 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 @@ -84,6 +84,12 @@ public class CxxSquidSensor implements Sensor { private final CxxChecks checks; private final CxxLanguage language; + + private List squidSensors = new ArrayList<>(); + + public List getSquidSensors(){ + return this.squidSensors; + } /** * {@inheritDoc} @@ -135,6 +141,9 @@ public void execute(SensorContext context) { context, this.language.getBooleanOption(CPD_IGNORE_LITERALS_KEY).orElse(Boolean.FALSE), this.language.getBooleanOption(CPD_IGNORE_IDENTIFIERS_KEY).orElse(Boolean.FALSE))); + + for (SquidSensor sensor : squidSensors) + visitors.add(sensor.getVisitor()); CxxConfiguration cxxConf = createConfiguration(context.fileSystem(), context); AstScanner scanner = CxxAstScanner.create(this.language, cxxConf, @@ -214,6 +223,9 @@ private void save(Collection squidSourceFiles, SensorContext context .withValue(violationsCount) .save(); } + + for(SquidSensor sensor: squidSensors) + sensor.publishMeasureForProject(context.module(), context); } private void saveMeasures(InputFile inputFile, SourceFile squidFile, SensorContext context) { @@ -249,6 +261,9 @@ private void saveMeasures(InputFile inputFile, SourceFile squidFile, SensorConte context.newMeasure().forMetric(language.getMetric(CxxMetrics.PUBLIC_DOCUMENTED_API_DENSITY_KEY)) .on(inputFile).withValue(densityOfPublicDocumentedApi).save(); } + + for(SquidSensor sensor: squidSensors) + sensor.publishMeasureForFile(inputFile, squidFile, context); } private int saveViolations(InputFile inputFile, SourceFile squidFile, SensorContext sensorContext) { diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java new file mode 100644 index 0000000000..5418fa5e2f --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java @@ -0,0 +1,33 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.squid; + +import com.sonar.sslr.api.Grammar; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputModule; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.squidbridge.SquidAstVisitor; +import org.sonar.squidbridge.api.SourceFile; + +public interface SquidSensor { + SquidAstVisitor getVisitor(); + void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context); + void publishMeasureForProject(InputModule module, SensorContext context); +} 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 494d4e7609..715c57ab67 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 @@ -19,6 +19,8 @@ */ package org.sonar.plugins.cxx.squid; +import com.sonar.sslr.api.AstVisitor; +import com.sonar.sslr.api.Grammar; import java.io.File; import java.io.IOException; import java.io.UnsupportedEncodingException; @@ -29,9 +31,9 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; +import static org.mockito.Mockito.*; import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.batch.rule.ActiveRules; @@ -45,7 +47,10 @@ import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.sensors.coverage.CxxCoverageSensor; import org.sonar.cxx.sensors.squid.CxxSquidSensor; +import org.sonar.cxx.sensors.squid.SquidSensor; import org.sonar.cxx.sensors.utils.TestUtils; +import org.sonar.squidbridge.SquidAstVisitor; +import org.sonar.squidbridge.api.SourceFile; public class CxxSquidSensorTest { @@ -210,6 +215,34 @@ public void testBehaviourOnCircularIncludes() throws UnsupportedEncodingExceptio assertThat(GetIntegerMeasureByKey(measures, CoreMetrics.NCLOC).value()).isEqualTo(1); } + + @Test + public void testSquidSensors() throws IOException{ + File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors/codechunks-project"); + File target = new File(baseDir, "code_chunks.cc"); + SensorContextTester context = SensorContextTester.create(baseDir); + + String content = new String(Files.readAllBytes(target.toPath()), "UTF-8"); + DefaultInputFile inputFile = TestInputFileBuilder.create("ProjectKey", baseDir, target).setContents(content) + .setCharset(Charset.forName("UTF-8")).setLanguage(language.getKey()) + .setType(InputFile.Type.MAIN).build(); + + SquidAstVisitor mockVisitor = (SquidAstVisitor) mock(SquidAstVisitor.class); + SquidSensor squidSensorMock = mock(SquidSensor.class); + when(squidSensorMock.getVisitor()).thenReturn(mockVisitor); + + sensor.getSquidSensors().clear(); + sensor.getSquidSensors().add(squidSensorMock); + + context.fileSystem().add(inputFile); + sensor.execute(context); + + verify(squidSensorMock, times(1)).getVisitor(); + verify(squidSensorMock, times(1)).publishMeasureForFile(eq(inputFile), any(SourceFile.class), eq(context)); + verify(squidSensorMock, times(1)).publishMeasureForProject(any(InputModule.class), eq(context)); + } + + private Measure GetIntegerMeasureByKey(Collection measures, Metric metric) { for (Measure measure : measures) { From 0a77b27027179956fa94f96389381336b38935c8 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Thu, 18 Jan 2018 17:21:44 +0000 Subject: [PATCH 02/19] Adding Complex Functions metrics, returning number of functions over a threshold of cyclomatic complexity. The threshold is controlled by the property sonar.cxx.funccomplexity.threshold --- .../CxxFunctionComplexitySquidSensor.java | 127 ++++++++++++++++ .../FunctionComplexityMetrics.java | 42 ++++++ .../functioncomplexity/FunctionCount.java | 26 ++++ .../cxx/sensors/squid/CxxSquidSensor.java | 7 + .../CxxFunctionComplexitySquidSensorTest.java | 136 ++++++++++++++++++ .../sonar/cxx/sensors/FunctionComplexity.cc | 87 +++++++++++ .../main/java/org/sonar/cxx/CxxLanguage.java | 6 +- .../java/org/sonar/plugins/c/CPlugin.java | 16 ++- .../java/org/sonar/plugins/c/CPluginTest.java | 3 +- .../java/org/sonar/plugins/cxx/CxxPlugin.java | 17 ++- .../org/sonar/plugins/cxx/CxxPluginTest.java | 3 +- 11 files changed, 463 insertions(+), 7 deletions(-) create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java create mode 100644 cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java create mode 100644 cxx-sensors/src/test/resources/org/sonar/cxx/sensors/FunctionComplexity.cc diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java new file mode 100644 index 0000000000..a95a0485db --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -0,0 +1,127 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functioncomplexity; + +import com.sonar.sslr.api.AstNode; +import com.sonar.sslr.api.Grammar; +import java.util.Hashtable; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputModule; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.config.Configuration; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.cxx.CxxLanguage; +import org.sonar.cxx.api.CxxMetric; +import org.sonar.cxx.parser.CxxGrammarImpl; +import static org.sonar.cxx.sensors.clangtidy.CxxClangTidySensor.REPORT_PATH_KEY; +import org.sonar.cxx.sensors.squid.SquidSensor; +import org.sonar.squidbridge.SquidAstVisitor; +import org.sonar.squidbridge.api.SourceFile; +import org.sonar.squidbridge.api.SourceFunction; +import org.sonar.squidbridge.checks.ChecksHelper; + +public class CxxFunctionComplexitySquidSensor extends SquidAstVisitor implements SquidSensor { + + private static final Logger LOG = Loggers.get(CxxFunctionComplexitySquidSensor.class); + + public static final String FUNCTION_COMPLEXITY_THRESHOLD_KEY = "funccomplexity.threshold"; + + private int cyclomaticComplexityThreshold; + + private int functionsBelowThreshold; + + public int getFunctionsBelowThreshold(){ + return this.functionsBelowThreshold; + } + + private int functionsOverThreshold; + + public int getFunctionsOverThreshold(){ + return this.functionsOverThreshold; + } + + private Hashtable complexFunctionsPerFile = new Hashtable<>(); + + public CxxFunctionComplexitySquidSensor(CxxLanguage language){ + this.cyclomaticComplexityThreshold = language.getIntegerOption(FUNCTION_COMPLEXITY_THRESHOLD_KEY).orElse(10); + LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); + } + + @Override + public SquidAstVisitor getVisitor() { + return this; + } + + @Override + public void init() { + subscribeTo(CxxGrammarImpl.functionDefinition); + } + + @Override + public void leaveNode(AstNode node) { + SourceFunction sourceFunction = (SourceFunction) getContext().peekSourceCode(); + SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class); + + int complexity = ChecksHelper.getRecursiveMeasureInt(sourceFunction, CxxMetric.COMPLEXITY); + + incrementFunctionByThresholdForAllFiles(complexity); + incrementFunctionByThresholdForFile(sourceFile, complexity); + } + + private void incrementFunctionByThresholdForAllFiles(int complexity){ + if (complexity > this.cyclomaticComplexityThreshold) + this.functionsOverThreshold++; + else + this.functionsBelowThreshold++; + } + + private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int complexity){ + if (!complexFunctionsPerFile.containsKey(sourceFile)) + complexFunctionsPerFile.put(sourceFile, new FunctionCount()); + + FunctionCount count = complexFunctionsPerFile.get(sourceFile); + if (complexity > this.cyclomaticComplexityThreshold) + count.functionsOverThreshold++; + else + count.functionsBelowThreshold++; + } + + @Override + public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { + FunctionCount c = complexFunctionsPerFile.get(squidFile); + if (c != null) + context.newMeasure() + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(c.functionsOverThreshold) + .save(); + } + + @Override + public void publishMeasureForProject(InputModule module, SensorContext context) { + context.newMeasure() + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + .on(module) + .withValue(functionsOverThreshold) + .save(); + } + +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java new file mode 100644 index 0000000000..615c99b4f3 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -0,0 +1,42 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functioncomplexity; + +import static java.util.Arrays.asList; +import java.util.List; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.Metrics; + +public class FunctionComplexityMetrics implements Metrics { + + public static final Metric COMPLEX_FUNCTIONS = new Metric.Builder("complex_functions", "Complex Functions", Metric.ValueType.INT) + .setDescription("Number of functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); + + @Override + public List getMetrics() { + return asList(COMPLEX_FUNCTIONS); + } + +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java new file mode 100644 index 0000000000..201c339739 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java @@ -0,0 +1,26 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functioncomplexity; + +public class FunctionCount { + public int functionsOverThreshold; + + public int functionsBelowThreshold +} 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 d2dbca8e71..4b871111b1 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 @@ -46,6 +46,7 @@ import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.api.CxxMetric; import org.sonar.cxx.sensors.compiler.CxxCompilerSensor; +import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; import org.sonar.cxx.sensors.utils.CxxMetrics; import org.sonar.cxx.sensors.utils.CxxReportSensor; import org.sonar.cxx.sensors.utils.JsonCompilationDatabase; @@ -116,6 +117,12 @@ public CxxSquidSensor(CxxLanguage language, if (this.language.getMetricsCache().isEmpty()) { new CxxMetrics(this.language); } + + registerSquidSensors(); + } + + protected void registerSquidSensors(){ + this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); } @Override diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java new file mode 100644 index 0000000000..1f6e1a57cf --- /dev/null +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -0,0 +1,136 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functioncomplexity; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.Collection; +import java.util.Optional; +import static org.assertj.core.api.Assertions.*; +import org.junit.*; +import static org.mockito.Mockito.*; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.TestInputFileBuilder; +import org.sonar.api.batch.measure.Metric; +import org.sonar.api.batch.rule.ActiveRules; +import org.sonar.api.batch.rule.CheckFactory; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.batch.sensor.internal.SensorContextTester; +import org.sonar.api.batch.sensor.measure.Measure; +import org.sonar.api.config.Configuration; +import org.sonar.api.measures.FileLinesContext; +import org.sonar.api.measures.FileLinesContextFactory; +import org.sonar.cxx.CxxAstScanner; +import org.sonar.cxx.CxxLanguage; +import org.sonar.cxx.sensors.squid.CxxSquidSensor; +import org.sonar.cxx.sensors.utils.TestUtils; +import org.sonar.squidbridge.api.SourceFile; + +public class CxxFunctionComplexitySquidSensorTest { + + private FileLinesContextFactory fileLinesContextFactory; + private FileLinesContext fileLinesContext; + private CxxLanguage language; + private SensorContextTester sensorContext; + private CxxFunctionComplexitySquidSensor sensor; + private Configuration configuration; + //private CxxSquidSensor squidSensor; + + @Before + public void setUp(){ + fileLinesContextFactory = mock(FileLinesContextFactory.class); + fileLinesContext = mock(FileLinesContext.class); + + language = TestUtils.mockCxxLanguage(); + when(language.getIntegerOption(CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_THRESHOLD_KEY)).thenReturn(Optional.of(5)); + + sensor = new CxxFunctionComplexitySquidSensor(language); + + // ActiveRules rules = mock(ActiveRules.class); + // CheckFactory checkFactory = new CheckFactory(rules); + // squidSensor = new CxxSquidSensor(language, fileLinesContextFactory, checkFactory); + } + + private DefaultInputFile getInputFile() throws IOException{ + File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); + File target = new File(baseDir, "FunctionComplexity.cc"); + + String content = new String(Files.readAllBytes(target.toPath()), "UTF-8"); + DefaultInputFile inputFile = TestInputFileBuilder.create("ProjectKey", baseDir, target).setContents(content) + .setCharset(Charset.forName("UTF-8")).setLanguage(language.getKey()) + .setType(InputFile.Type.MAIN).build(); + + sensorContext = SensorContextTester.create(baseDir); + sensorContext.fileSystem().add(inputFile); + + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + + return inputFile; + } + + public boolean containsAll(Collection c){ + return false; + } + + private T getMeasureValue(SensorContextTester sensorContext, String componentKey, Metric metric){ + Collection measures = sensorContext.measures(componentKey); + T value = null; + for(Measure m : measures){ + if (m.metric() == FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + value = (T) m.value(); + } + return value; + } + + @Test + public void testFunctionsOverAndBelowThresholdForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + + assertThat(sensor.getFunctionsBelowThreshold()).isEqualTo(6); + assertThat(sensor.getFunctionsOverThreshold()).isEqualTo(4); + } + + @Test + public void testPublishMeasuresForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + } + + @Test + public void testPublishMeasuresForFile() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + } + +} diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/sensors/FunctionComplexity.cc b/cxx-sensors/src/test/resources/org/sonar/cxx/sensors/FunctionComplexity.cc new file mode 100644 index 0000000000..62c6a1d609 --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/sensors/FunctionComplexity.cc @@ -0,0 +1,87 @@ +void func1() { + return; +} + +int func2(int a) { + if( a ) { + return 1; + } else { + return 0; + } +} + +int func3(int a, int b) { + if( a ) { + if( b ) { + return a+b ? 1 : 2; + } else { + return a+b ? 3 : 4; + } + } else { + if( b ) { + return a+b ? 5 : 6; + } else { + return a+b ? 7 : 8; + } + } +} + +class MyClass { +public: + MyClass() {}; + int Method1(int a, int b) {} + int Method2(int a, int b) { + if( a ) { + if( b ) { + return a+b ? 1 : 2; + } else { + return a+b ? 3 : 4; + } + } else { + if( b ) { + return a+b ? 5 : 6; + } else { + return a+b ? 7 : 8; + } + } + } + int Method3(int a, int b); +}; + +int MyClass::Method3(int a, int b) { + if( a ) { + if( b ) { + return a+b ? 1 : 2; + } else { + return a+b ? 3 : 4; + } + } else { + if( b ) { + return a+b ? 5 : 6; + } else { + return a+b ? 7 : 8; + } + } +} + +template +class MyTemplate { +public: + MyTemplate() {}; + int Method1(T a, T b) {} + int Method2(T a, T b) { + if( a ) { + if( b ) { + return a+b ? 1 : 2; + } else { + return a+b ? 3 : 4; + } + } else { + if( b ) { + return a+b ? 5 : 6; + } else { + return a+b ? 7 : 8; + } + } + } +}; diff --git a/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java b/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java index f3507b706d..34ccb0d865 100644 --- a/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java +++ b/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java @@ -43,7 +43,7 @@ public abstract class CxxLanguage extends AbstractLanguage { public CxxLanguage(String key, Configuration settings) { super(key); this.settings = settings; - this.MetricsCache = new HashMap<>(); + this.MetricsCache = new HashMap<>(); } public CxxLanguage(String key, String name, Configuration settings) { @@ -72,6 +72,10 @@ public String getRepositorySuffix() { public String getPluginProperty(String key) { return "sonar." + getPropertiesKey() + "." + key; } + + public Optional getIntegerOption(String key){ + return this.settings.getInt(getPluginProperty(key)); + } public Optional getBooleanOption(String key) { return this.settings.getBoolean(getPluginProperty(key)); 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 9f404eb253..a3e520669c 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 @@ -48,6 +48,8 @@ import org.sonar.cxx.sensors.cppcheck.CxxCppCheckSensor; import org.sonar.cxx.sensors.drmemory.CxxDrMemoryRuleRepository; import org.sonar.cxx.sensors.drmemory.CxxDrMemorySensor; +import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; +import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.other.CxxOtherRepository; import org.sonar.cxx.sensors.other.CxxOtherSensor; import org.sonar.cxx.sensors.pclint.CxxPCLintRuleRepository; @@ -324,7 +326,16 @@ private static List codeAnalysisProperties() { .type(PropertyType.TEXT) .subCategory(subcateg) .index(17) - .build() + .build(), + PropertyDefinition.builder(LANG_PROP_PREFIX + CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_THRESHOLD_KEY) + .defaultValue("10") + .name("Cyclomatic complexity threshold") + .description("Cyclomatic complexity threshold used to classify a function as complex") + .subCategory(subcateg) + .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) + .type(PropertyType.INTEGER) + .index(18) + .build() )); } @@ -466,6 +477,9 @@ public void define(Context context) { l.addAll(testingAndCoverageProperties()); l.addAll(compilerWarningsProperties()); l.addAll(duplicationsProperties()); + + //extra metrics + l.add(FunctionComplexityMetrics.class); context.addExtensions(l); } diff --git a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java index 9933913597..f26bcb2a8e 100644 --- a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java +++ b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java @@ -35,6 +35,5 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CPlugin plugin = new CPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(67); - } + assertThat(context.getExtensions()).hasSize(71); } } 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 09d375643c..3f242f4419 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 @@ -50,6 +50,8 @@ import org.sonar.cxx.sensors.cppcheck.CxxCppCheckSensor; import org.sonar.cxx.sensors.drmemory.CxxDrMemoryRuleRepository; import org.sonar.cxx.sensors.drmemory.CxxDrMemorySensor; +import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; +import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.other.CxxOtherRepository; import org.sonar.cxx.sensors.other.CxxOtherSensor; import org.sonar.cxx.sensors.pclint.CxxPCLintRuleRepository; @@ -88,7 +90,7 @@ public final class CxxPlugin implements Plugin { public static final String MISSING_INCLUDE_WARN = LANG_PROP_PREFIX + "missingIncludeWarnings"; public static final String JSON_COMPILATION_DATABASE_KEY = LANG_PROP_PREFIX + "jsonCompilationDatabase"; public static final String CPD_IGNORE_LITERALS_KEY = LANG_PROP_PREFIX + "cpd.ignoreLiterals"; - public static final String CPD_IGNORE_IDENTIFIERS_KEY = LANG_PROP_PREFIX + "cpd.ignoreIdentifiers"; + public static final String CPD_IGNORE_IDENTIFIERS_KEY = LANG_PROP_PREFIX + "cpd.ignoreIdentifiers"; private static List generalProperties() { String subcateg = "(1) General"; @@ -330,6 +332,15 @@ private static List codeAnalysisProperties() { .type(PropertyType.TEXT) .subCategory(subcateg) .index(17) + .build(), + PropertyDefinition.builder(LANG_PROP_PREFIX + CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_THRESHOLD_KEY) + .defaultValue("10") + .name("Cyclomatic complexity threshold") + .description("Cyclomatic complexity threshold used to classify a function as complex") + .subCategory(subcateg) + .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) + .type(PropertyType.INTEGER) + .index(18) .build() )); } @@ -495,6 +506,10 @@ public void define(Context context) { l.addAll(testingAndCoverageProperties()); l.addAll(compilerWarningsProperties()); l.addAll(duplicationsProperties()); + + //extra metrics + l.add(FunctionComplexityMetrics.class); + context.addExtensions(l); } diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java index 9d880c787e..b100a18d30 100644 --- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java +++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java @@ -35,6 +35,5 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CxxPlugin plugin = new CxxPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(71); - } + assertThat(context.getExtensions()).hasSize(74); } } From c7eac3544be4dfd8aa8a3e3ecaec5784433e3a49 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 19 Jan 2018 12:39:48 +0000 Subject: [PATCH 03/19] Implementing % of complex functions metric. --- .../CxxFunctionComplexitySquidSensor.java | 30 +++++++++++++++---- .../FunctionComplexityMetrics.java | 9 +++++- .../functioncomplexity/FunctionCount.java | 2 +- .../CxxFunctionComplexitySquidSensorTest.java | 4 ++- 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index a95a0485db..51c1cac939 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -107,12 +107,20 @@ private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int comp @Override public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { FunctionCount c = complexFunctionsPerFile.get(squidFile); - if (c != null) - context.newMeasure() - .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) - .on(inputFile) - .withValue(c.functionsOverThreshold) - .save(); + if (c == null) + return; + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(c.functionsOverThreshold) + .save(); + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(calculatePercComplexFunctions(c.functionsOverThreshold, c.functionsBelowThreshold)) + .save(); } @Override @@ -122,6 +130,16 @@ public void publishMeasureForProject(InputModule module, SensorContext context) .on(module) .withValue(functionsOverThreshold) .save(); + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .on(module) + .withValue(calculatePercComplexFunctions(functionsOverThreshold, functionsBelowThreshold)) + .save(); + } + + private double calculatePercComplexFunctions(int functionsOverThreshold, int functionsBelowThreshold){ + return ((float)functionsOverThreshold * 100.0) / ((float)functionsOverThreshold + (float)functionsBelowThreshold); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java index 615c99b4f3..bb946c22e9 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -33,10 +33,17 @@ public class FunctionComplexityMetrics implements Metrics { .setQualitative(false) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) .create(); + + public static final Metric PERC_COMPLEX_FUNCTIONS = new Metric.Builder("perc_complex_functions", "% of Complex Functions", Metric.ValueType.PERCENT) + .setDescription("% of functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); @Override public List getMetrics() { - return asList(COMPLEX_FUNCTIONS); + return asList(COMPLEX_FUNCTIONS, PERC_COMPLEX_FUNCTIONS); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java index 201c339739..fdbcd9dc43 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java @@ -22,5 +22,5 @@ public class FunctionCount { public int functionsOverThreshold; - public int functionsBelowThreshold + public int functionsBelowThreshold; } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index 1f6e1a57cf..8f6274b765 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -97,7 +97,7 @@ private T getMeasureValue(SensorContextTester sensorCon Collection measures = sensorContext.measures(componentKey); T value = null; for(Measure m : measures){ - if (m.metric() == FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + if (m.metric() == metric) value = (T) m.value(); } return value; @@ -121,6 +121,7 @@ public void testPublishMeasuresForProject() throws IOException { sensor.publishMeasureForProject(sensorContext.module(), sensorContext); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); } @Test @@ -131,6 +132,7 @@ public void testPublishMeasuresForFile() throws IOException { sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); } } From aa912aecca57a04dd49abc31f1ef56b9e3085106 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Thu, 18 Jan 2018 17:21:44 +0000 Subject: [PATCH 04/19] Adding Complex Functions metrics, returning number of functions over a threshold of cyclomatic complexity. The threshold is controlled by the property sonar.cxx.funccomplexity.threshold --- .../CxxFunctionComplexitySquidSensor.java | 30 ++++--------------- .../FunctionComplexityMetrics.java | 9 +----- .../functioncomplexity/FunctionCount.java | 2 +- .../CxxFunctionComplexitySquidSensorTest.java | 4 +-- .../java/org/sonar/plugins/c/CPluginTest.java | 5 ++-- .../org/sonar/plugins/cxx/CxxPluginTest.java | 5 ++-- 6 files changed, 15 insertions(+), 40 deletions(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index 51c1cac939..a95a0485db 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -107,20 +107,12 @@ private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int comp @Override public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { FunctionCount c = complexFunctionsPerFile.get(squidFile); - if (c == null) - return; - - context.newMeasure() - .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) - .on(inputFile) - .withValue(c.functionsOverThreshold) - .save(); - - context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) - .on(inputFile) - .withValue(calculatePercComplexFunctions(c.functionsOverThreshold, c.functionsBelowThreshold)) - .save(); + if (c != null) + context.newMeasure() + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(c.functionsOverThreshold) + .save(); } @Override @@ -130,16 +122,6 @@ public void publishMeasureForProject(InputModule module, SensorContext context) .on(module) .withValue(functionsOverThreshold) .save(); - - context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) - .on(module) - .withValue(calculatePercComplexFunctions(functionsOverThreshold, functionsBelowThreshold)) - .save(); - } - - private double calculatePercComplexFunctions(int functionsOverThreshold, int functionsBelowThreshold){ - return ((float)functionsOverThreshold * 100.0) / ((float)functionsOverThreshold + (float)functionsBelowThreshold); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java index bb946c22e9..615c99b4f3 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -33,17 +33,10 @@ public class FunctionComplexityMetrics implements Metrics { .setQualitative(false) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) .create(); - - public static final Metric PERC_COMPLEX_FUNCTIONS = new Metric.Builder("perc_complex_functions", "% of Complex Functions", Metric.ValueType.PERCENT) - .setDescription("% of functions with high cyclomatic complexity") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); @Override public List getMetrics() { - return asList(COMPLEX_FUNCTIONS, PERC_COMPLEX_FUNCTIONS); + return asList(COMPLEX_FUNCTIONS); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java index fdbcd9dc43..201c339739 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java @@ -22,5 +22,5 @@ public class FunctionCount { public int functionsOverThreshold; - public int functionsBelowThreshold; + public int functionsBelowThreshold } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index 8f6274b765..1f6e1a57cf 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -97,7 +97,7 @@ private T getMeasureValue(SensorContextTester sensorCon Collection measures = sensorContext.measures(componentKey); T value = null; for(Measure m : measures){ - if (m.metric() == metric) + if (m.metric() == FunctionComplexityMetrics.COMPLEX_FUNCTIONS) value = (T) m.value(); } return value; @@ -121,7 +121,6 @@ public void testPublishMeasuresForProject() throws IOException { sensor.publishMeasureForProject(sensorContext.module(), sensorContext); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); } @Test @@ -132,7 +131,6 @@ public void testPublishMeasuresForFile() throws IOException { sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); } } diff --git a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java index f26bcb2a8e..3c40346088 100644 --- a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java +++ b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2018 SonarOpenCommunity + * Copyright (C) 2010-2017 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or @@ -35,5 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CPlugin plugin = new CPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(71); } + assertThat(context.getExtensions()).hasSize(70); + } } diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java index b100a18d30..b4b9b6fb1d 100644 --- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java +++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2018 SonarOpenCommunity + * Copyright (C) 2010-2017 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or @@ -35,5 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CxxPlugin plugin = new CxxPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(74); } + assertThat(context.getExtensions()).hasSize(74); + } } From 0b1e6f37630d67e84c469af71c523f8bfea7a7d6 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 19 Jan 2018 14:41:13 +0000 Subject: [PATCH 05/19] Implements Big Functions and % of Big Functions metrics, controlled by the property sonar.cxx.funcsize.threshold. --- .../CxxFunctionSizeSquidSensor.java | 145 ++++++++++++++++++ .../functionsize/FunctionSizeMetrics.java | 50 ++++++ .../cxx/sensors/squid/CxxSquidSensor.java | 2 + .../CxxFunctionSizeSquidSensorTest.java | 127 +++++++++++++++ .../java/org/sonar/plugins/c/CPlugin.java | 14 +- .../java/org/sonar/plugins/c/CPluginTest.java | 2 +- .../java/org/sonar/plugins/cxx/CxxPlugin.java | 14 +- .../org/sonar/plugins/cxx/CxxPluginTest.java | 2 +- 8 files changed, 352 insertions(+), 4 deletions(-) create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java create mode 100644 cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java new file mode 100644 index 0000000000..637af20883 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -0,0 +1,145 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functionsize; + +import com.sonar.sslr.api.AstNode; +import com.sonar.sslr.api.Grammar; +import java.util.Hashtable; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.InputModule; +import org.sonar.api.batch.sensor.SensorContext; +import org.sonar.api.utils.log.Logger; +import org.sonar.api.utils.log.Loggers; +import org.sonar.cxx.CxxLanguage; +import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine; +import org.sonar.cxx.parser.CxxGrammarImpl; +import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; +import org.sonar.cxx.sensors.functioncomplexity.FunctionCount; +import org.sonar.cxx.sensors.squid.SquidSensor; +import org.sonar.squidbridge.SquidAstVisitor; +import org.sonar.squidbridge.api.SourceFile; +import org.sonar.squidbridge.api.SourceFunction; + +public class CxxFunctionSizeSquidSensor extends SquidAstVisitor implements SquidSensor { + + private static final Logger LOG = Loggers.get(CxxFunctionSizeSquidSensor.class); + + public static final String FUNCTION_SIZE_THRESHOLD_KEY = "funcsize.threshold"; + + private int functionsBelowThreshold; + + private int sizeThreshold; + + public int getFunctionsBelowThreshold(){ + return this.functionsBelowThreshold; + } + + private int functionsOverThreshold; + + public int getFunctionsOverThreshold(){ + return this.functionsOverThreshold; + } + + private Hashtable bigFunctionsPerFile = new Hashtable<>(); + + public CxxFunctionSizeSquidSensor(CxxLanguage language){ + this.sizeThreshold = language.getIntegerOption(FUNCTION_SIZE_THRESHOLD_KEY).orElse(20); + LOG.debug("Function size threshold: " + this.sizeThreshold); + } + + @Override + public void init() { + subscribeTo(CxxGrammarImpl.functionBody); + } + + @Override + public void leaveNode(AstNode node) { + SourceFunction sourceFunction = (SourceFunction) getContext().peekSourceCode(); + SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class); + + int lineCount = getNumberOfLine(node); + + incrementFunctionByThresholdForProject(lineCount); + incrementFunctionByThresholdForFile(sourceFile, lineCount); + } + + private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int complexity){ + if (!bigFunctionsPerFile.containsKey(sourceFile)) + bigFunctionsPerFile.put(sourceFile, new FunctionCount()); + + FunctionCount count = bigFunctionsPerFile.get(sourceFile); + if (complexity > this.sizeThreshold) + count.functionsOverThreshold++; + else + count.functionsBelowThreshold++; + } + + private void incrementFunctionByThresholdForProject(int lineCount){ + if (lineCount > sizeThreshold) + this.functionsOverThreshold++; + else + this.functionsBelowThreshold++; + } + + + @Override + public SquidAstVisitor getVisitor() { + return this; + } + + @Override + public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { + FunctionCount c = bigFunctionsPerFile.get(squidFile); + if (c == null) + return; + + context.newMeasure() + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) + .on(inputFile) + .withValue(c.functionsOverThreshold) + .save(); + + context.newMeasure() + .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) + .on(inputFile) + .withValue(calculatePercComplexFunctions(c.functionsOverThreshold, c.functionsBelowThreshold)) + .save(); + } + + @Override + public void publishMeasureForProject(InputModule module, SensorContext context) { + context.newMeasure() + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) + .on(module) + .withValue(functionsOverThreshold) + .save(); + + context.newMeasure() + .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) + .on(module) + .withValue(calculatePercComplexFunctions(functionsOverThreshold, functionsBelowThreshold)) + .save(); + } + + private double calculatePercComplexFunctions(int functionsOverThreshold, int functionsBelowThreshold){ + return ((float)functionsOverThreshold * 100.0) / ((float)functionsOverThreshold + (float)functionsBelowThreshold); + } + +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java new file mode 100644 index 0000000000..f7e73c0f1b --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java @@ -0,0 +1,50 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functionsize; + +import static java.util.Arrays.asList; +import java.util.List; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.Metrics; + +public class FunctionSizeMetrics implements Metrics { + + public static final Metric BIG_FUNCTIONS = new Metric.Builder("big_functions", "Big Functions", Metric.ValueType.INT) + .setDescription("Number of functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + + public static final Metric PERC_BIG_FUNCTIONS = new Metric.Builder("perc_big_functions", "% of Big Functions", Metric.ValueType.PERCENT) + .setDescription("% of functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + + @Override + public List getMetrics() { + return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS); + } + +} 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 4b871111b1..8077d27ee1 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 @@ -47,6 +47,7 @@ import org.sonar.cxx.api.CxxMetric; import org.sonar.cxx.sensors.compiler.CxxCompilerSensor; import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; +import org.sonar.cxx.sensors.functionsize.CxxFunctionSizeSquidSensor; import org.sonar.cxx.sensors.utils.CxxMetrics; import org.sonar.cxx.sensors.utils.CxxReportSensor; import org.sonar.cxx.sensors.utils.JsonCompilationDatabase; @@ -123,6 +124,7 @@ public CxxSquidSensor(CxxLanguage language, protected void registerSquidSensors(){ this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); + this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); } @Override diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java new file mode 100644 index 0000000000..5835791d5f --- /dev/null +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -0,0 +1,127 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functionsize; + +import java.io.File; +import java.io.IOException; +import java.io.Serializable; +import java.nio.charset.Charset; +import java.nio.file.Files; +import java.util.Collection; +import java.util.Optional; +import static org.assertj.core.api.Assertions.assertThat; +import org.junit.Before; +import org.junit.Test; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; +import org.sonar.api.batch.fs.InputFile; +import org.sonar.api.batch.fs.internal.DefaultInputFile; +import org.sonar.api.batch.fs.internal.TestInputFileBuilder; +import org.sonar.api.batch.measure.Metric; +import org.sonar.api.batch.sensor.internal.SensorContextTester; +import org.sonar.api.batch.sensor.measure.Measure; +import org.sonar.api.config.Configuration; +import org.sonar.api.measures.FileLinesContext; +import org.sonar.api.measures.FileLinesContextFactory; +import org.sonar.cxx.CxxAstScanner; +import org.sonar.cxx.CxxLanguage; +import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; +import org.sonar.cxx.sensors.utils.TestUtils; +import org.sonar.squidbridge.api.SourceFile; + +public class CxxFunctionSizeSquidSensorTest { + private FileLinesContextFactory fileLinesContextFactory; + private FileLinesContext fileLinesContext; + private CxxLanguage language; + private SensorContextTester sensorContext; + private CxxFunctionSizeSquidSensor sensor; + private Configuration configuration; + + @Before + public void setUp(){ + fileLinesContextFactory = mock(FileLinesContextFactory.class); + fileLinesContext = mock(FileLinesContext.class); + + language = TestUtils.mockCxxLanguage(); + when(language.getIntegerOption(CxxFunctionSizeSquidSensor.FUNCTION_SIZE_THRESHOLD_KEY)).thenReturn(Optional.of(10)); + + sensor = new CxxFunctionSizeSquidSensor(this.language); + } + + private DefaultInputFile getInputFile() throws IOException{ + File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); + File target = new File(baseDir, "FunctionComplexity.cc"); + + String content = new String(Files.readAllBytes(target.toPath()), "UTF-8"); + DefaultInputFile inputFile = TestInputFileBuilder.create("ProjectKey", baseDir, target).setContents(content) + .setCharset(Charset.forName("UTF-8")).setLanguage(language.getKey()) + .setType(InputFile.Type.MAIN).build(); + + sensorContext = SensorContextTester.create(baseDir); + sensorContext.fileSystem().add(inputFile); + + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + + return inputFile; + } + + @Test + public void testFunctionsOverAndBelowThresholdForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + + assertThat(sensor.getFunctionsBelowThreshold()).isEqualTo(6); + assertThat(sensor.getFunctionsOverThreshold()).isEqualTo(4); + } + + private T getMeasureValue(SensorContextTester sensorContext, String componentKey, Metric metric){ + Collection measures = sensorContext.measures(componentKey); + T value = null; + for(Measure m : measures){ + if (m.metric() == metric) + value = (T) m.value(); + } + return value; + } + + @Test + public void testPublishMeasuresForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); + } + + @Test + public void testPublishMeasuresForFile() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); + } + +} 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 a3e520669c..616d02edd2 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 @@ -50,6 +50,8 @@ import org.sonar.cxx.sensors.drmemory.CxxDrMemorySensor; import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; +import org.sonar.cxx.sensors.functionsize.CxxFunctionSizeSquidSensor; +import org.sonar.cxx.sensors.functionsize.FunctionSizeMetrics; import org.sonar.cxx.sensors.other.CxxOtherRepository; import org.sonar.cxx.sensors.other.CxxOtherSensor; import org.sonar.cxx.sensors.pclint.CxxPCLintRuleRepository; @@ -335,7 +337,16 @@ private static List codeAnalysisProperties() { .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) .type(PropertyType.INTEGER) .index(18) - .build() + .build(), + PropertyDefinition.builder(LANG_PROP_PREFIX + CxxFunctionSizeSquidSensor.FUNCTION_SIZE_THRESHOLD_KEY) + .defaultValue("20") + .name("Function size threshold") + .description("Function size threshold to consider a function to be too big") + .subCategory(subcateg) + .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) + .type(PropertyType.INTEGER) + .index(19) + .build() )); } @@ -480,6 +491,7 @@ public void define(Context context) { //extra metrics l.add(FunctionComplexityMetrics.class); + l.add(FunctionSizeMetrics.class); context.addExtensions(l); } diff --git a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java index 3c40346088..04d948c5d2 100644 --- a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java +++ b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java @@ -35,6 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CPlugin plugin = new CPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(70); + assertThat(context.getExtensions()).hasSize(72); } } 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 3f242f4419..e96d775df1 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 @@ -52,6 +52,8 @@ import org.sonar.cxx.sensors.drmemory.CxxDrMemorySensor; import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; +import org.sonar.cxx.sensors.functionsize.CxxFunctionSizeSquidSensor; +import org.sonar.cxx.sensors.functionsize.FunctionSizeMetrics; import org.sonar.cxx.sensors.other.CxxOtherRepository; import org.sonar.cxx.sensors.other.CxxOtherSensor; import org.sonar.cxx.sensors.pclint.CxxPCLintRuleRepository; @@ -341,7 +343,16 @@ private static List codeAnalysisProperties() { .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) .type(PropertyType.INTEGER) .index(18) - .build() + .build(), + PropertyDefinition.builder(LANG_PROP_PREFIX + CxxFunctionSizeSquidSensor.FUNCTION_SIZE_THRESHOLD_KEY) + .defaultValue("20") + .name("Function size threshold") + .description("Function size threshold to consider a function to be too big") + .subCategory(subcateg) + .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) + .type(PropertyType.INTEGER) + .index(19) + .build() )); } @@ -509,6 +520,7 @@ public void define(Context context) { //extra metrics l.add(FunctionComplexityMetrics.class); + l.add(FunctionSizeMetrics.class); context.addExtensions(l); } diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java index b4b9b6fb1d..a709b75faa 100644 --- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java +++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java @@ -35,6 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CxxPlugin plugin = new CxxPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(74); + assertThat(context.getExtensions()).hasSize(76); } } From 53817929b1c1b8305c5efa50111d5628f2412457 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 19 Jan 2018 16:53:34 +0000 Subject: [PATCH 06/19] Dumping list of ranked functions by cyclomatic complexity and lines of code. Both controled by properties (sonar.cxx.funccomplexity.filename and sonar.cxx.funcsize.filename) --- .../CxxFunctionComplexitySquidSensor.java | 87 +++++++++++++++++-- .../functioncomplexity/FunctionScore.java | 62 +++++++++++++ .../FunctionScoreComparator.java | 37 ++++++++ .../CxxFunctionSizeSquidSensor.java | 62 ++++++++++++- .../cxx/sensors/utils/FileStreamFactory.java | 35 ++++++++ .../cxx/sensors/utils/StreamFactory.java | 27 ++++++ .../CxxFunctionComplexitySquidSensorTest.java | 31 +++++-- .../CxxFunctionSizeSquidSensorTest.java | 22 +++++ 8 files changed, 347 insertions(+), 16 deletions(-) create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index a95a0485db..cdf82cac04 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -21,7 +21,12 @@ import com.sonar.sslr.api.AstNode; import com.sonar.sslr.api.Grammar; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.OutputStream; import java.util.Hashtable; +import java.util.SortedSet; +import java.util.TreeSet; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.sensor.SensorContext; @@ -33,6 +38,8 @@ import org.sonar.cxx.parser.CxxGrammarImpl; import static org.sonar.cxx.sensors.clangtidy.CxxClangTidySensor.REPORT_PATH_KEY; import org.sonar.cxx.sensors.squid.SquidSensor; +import org.sonar.cxx.sensors.utils.FileStreamFactory; +import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -43,6 +50,7 @@ public class CxxFunctionComplexitySquidSensor extends SquidAstVisitor i private static final Logger LOG = Loggers.get(CxxFunctionComplexitySquidSensor.class); public static final String FUNCTION_COMPLEXITY_THRESHOLD_KEY = "funccomplexity.threshold"; + public static final String FUNCTION_COMPLEXITY_FILE_NAME_KEY = "funccomplexity.filename"; private int cyclomaticComplexityThreshold; @@ -60,9 +68,27 @@ public int getFunctionsOverThreshold(){ private Hashtable complexFunctionsPerFile = new Hashtable<>(); + private String fileName; + + private StreamFactory streamFactory; + + private TreeSet rankedList = new TreeSet(new FunctionScoreComparator()); + public SortedSet getRankedList(){ + return this.rankedList; + } + public CxxFunctionComplexitySquidSensor(CxxLanguage language){ this.cyclomaticComplexityThreshold = language.getIntegerOption(FUNCTION_COMPLEXITY_THRESHOLD_KEY).orElse(10); LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); + + this.fileName = language.getStringOption(FUNCTION_COMPLEXITY_FILE_NAME_KEY).orElse(""); + LOG.debug("File name to dump CC data: " + this.fileName); + + this.streamFactory = new FileStreamFactory(); + } + + public void setFileStreamFactory(StreamFactory factory){ + this.streamFactory = factory; } @Override @@ -84,8 +110,37 @@ public void leaveNode(AstNode node) { incrementFunctionByThresholdForAllFiles(complexity); incrementFunctionByThresholdForFile(sourceFile, complexity); + appendRankedList(sourceFunction, complexity); } + private void appendRankedList(SourceFunction sourceFunction, int complexity){ + if (fileName.equals("")) + return; + + FunctionScore score = new FunctionScore(complexity, getContext().getFile().getName(), sourceFunction.getKey()); + this.rankedList.add(score); + } + + private void writeScore(OutputStream stream, FunctionScore score) throws IOException{ + stream.write((score.getComponentName() + "\t" + score.getFunctionId() + "\t" + score.getScore() + System.lineSeparator()).getBytes()); + } + + private void dumpRankedList(){ + if (fileName.equals("")) + return; + + try { + OutputStream stream = streamFactory.createOutputFileStream(this.fileName); + for(FunctionScore score : rankedList) + writeScore(stream, score); + stream.flush(); + stream.close(); + } + catch (Exception e){ + LOG.error("Couldn't write ranked list to " + fileName + ". Exception text: " + e.getMessage()); + } + } + private void incrementFunctionByThresholdForAllFiles(int complexity){ if (complexity > this.cyclomaticComplexityThreshold) this.functionsOverThreshold++; @@ -107,12 +162,20 @@ private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int comp @Override public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { FunctionCount c = complexFunctionsPerFile.get(squidFile); - if (c != null) - context.newMeasure() - .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) - .on(inputFile) - .withValue(c.functionsOverThreshold) - .save(); + if (c == null) + return; + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(c.functionsOverThreshold) + .save(); + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(calculatePercComplexFunctions(c.functionsOverThreshold, c.functionsBelowThreshold)) + .save(); } @Override @@ -122,6 +185,18 @@ public void publishMeasureForProject(InputModule module, SensorContext context) .on(module) .withValue(functionsOverThreshold) .save(); + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .on(module) + .withValue(calculatePercComplexFunctions(functionsOverThreshold, functionsBelowThreshold)) + .save(); + + dumpRankedList(); + } + + private double calculatePercComplexFunctions(int functionsOverThreshold, int functionsBelowThreshold){ + return ((float)functionsOverThreshold * 100.0) / ((float)functionsOverThreshold + (float)functionsBelowThreshold); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java new file mode 100644 index 0000000000..2aa596ec18 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java @@ -0,0 +1,62 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functioncomplexity; + +public class FunctionScore { + private int score; + + public int getScore(){ + return this.score; + } + + public void setScore(int value){ + this.score = value; + } + + private String componentName; + + public String getComponentName(){ + return this.componentName; + } + + public void setComponentName(String value){ + this.componentName = value; + } + + private String functionId; + + public String getFunctionId(){ + return this.functionId; + } + + public void setFunctionId(String value){ + this.functionId = value; + } + + public FunctionScore(){ + + } + + public FunctionScore(int score, String componentName, String functionId){ + this.score = score; + this.componentName = componentName; + this.functionId = functionId; + } +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java new file mode 100644 index 0000000000..e50341daa1 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java @@ -0,0 +1,37 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functioncomplexity; + +import java.util.Comparator; + +public class FunctionScoreComparator implements Comparator{ + + @Override + public int compare(FunctionScore o1, FunctionScore o2) { + if (o1 == o2) + return 0; + else if (o1.getScore() > o2.getScore()) + return -1; + else + return 1; + } + +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 637af20883..8b73e0a75f 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -21,7 +21,11 @@ import com.sonar.sslr.api.AstNode; import com.sonar.sslr.api.Grammar; +import java.io.IOException; +import java.io.OutputStream; import java.util.Hashtable; +import java.util.SortedSet; +import java.util.TreeSet; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.sensor.SensorContext; @@ -32,7 +36,11 @@ import org.sonar.cxx.parser.CxxGrammarImpl; import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.functioncomplexity.FunctionCount; +import org.sonar.cxx.sensors.functioncomplexity.FunctionScore; +import org.sonar.cxx.sensors.functioncomplexity.FunctionScoreComparator; import org.sonar.cxx.sensors.squid.SquidSensor; +import org.sonar.cxx.sensors.utils.FileStreamFactory; +import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -42,6 +50,7 @@ public class CxxFunctionSizeSquidSensor extends SquidAstVisitor impleme private static final Logger LOG = Loggers.get(CxxFunctionSizeSquidSensor.class); public static final String FUNCTION_SIZE_THRESHOLD_KEY = "funcsize.threshold"; + public static final String FUNCTION_SIZE_FILE_NAME_KEY = "funcsize.filename"; private int functionsBelowThreshold; @@ -57,14 +66,32 @@ public int getFunctionsOverThreshold(){ return this.functionsOverThreshold; } - private Hashtable bigFunctionsPerFile = new Hashtable<>(); + private Hashtable bigFunctionsPerFile = new Hashtable<>(); + + private String fileName; + + private StreamFactory streamFactory; + + private TreeSet rankedList = new TreeSet(new FunctionScoreComparator()); + public SortedSet getRankedList(){ + return this.rankedList; + } + + public void setFileStreamFactory(StreamFactory factory){ + this.streamFactory = factory; + } public CxxFunctionSizeSquidSensor(CxxLanguage language){ this.sizeThreshold = language.getIntegerOption(FUNCTION_SIZE_THRESHOLD_KEY).orElse(20); LOG.debug("Function size threshold: " + this.sizeThreshold); + + this.fileName = language.getStringOption(FUNCTION_SIZE_FILE_NAME_KEY).orElse(""); + LOG.debug("File name to dump function size data: " + this.fileName); + + this.streamFactory = new FileStreamFactory(); } - @Override + @Override public void init() { subscribeTo(CxxGrammarImpl.functionBody); } @@ -78,8 +105,37 @@ public void leaveNode(AstNode node) { incrementFunctionByThresholdForProject(lineCount); incrementFunctionByThresholdForFile(sourceFile, lineCount); + appendRankedList(sourceFunction, lineCount); + } + + private void appendRankedList(SourceFunction sourceFunction, int complexity){ + if (fileName.equals("")) + return; + + FunctionScore score = new FunctionScore(complexity, getContext().getFile().getName(), sourceFunction.getKey()); + this.rankedList.add(score); + } + + private void writeScore(OutputStream stream, FunctionScore score) throws IOException{ + stream.write((score.getComponentName() + "\t" + score.getFunctionId() + "\t" + score.getScore() + System.lineSeparator()).getBytes()); } + private void dumpRankedList(){ + if (fileName.equals("")) + return; + + try { + OutputStream stream = streamFactory.createOutputFileStream(this.fileName); + for(FunctionScore score : rankedList) + writeScore(stream, score); + stream.flush(); + stream.close(); + } + catch (Exception e){ + LOG.error("Couldn't write ranked list to " + fileName + ". Exception text: " + e.getMessage()); + } + } + private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int complexity){ if (!bigFunctionsPerFile.containsKey(sourceFile)) bigFunctionsPerFile.put(sourceFile, new FunctionCount()); @@ -136,6 +192,8 @@ public void publishMeasureForProject(InputModule module, SensorContext context) .on(module) .withValue(calculatePercComplexFunctions(functionsOverThreshold, functionsBelowThreshold)) .save(); + + dumpRankedList(); } private double calculatePercComplexFunctions(int functionsOverThreshold, int functionsBelowThreshold){ diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java new file mode 100644 index 0000000000..059182c86f --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java @@ -0,0 +1,35 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.utils; + +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.OutputStream; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class FileStreamFactory implements StreamFactory { + + @Override + public OutputStream createOutputFileStream(String fileName) throws FileNotFoundException{ + return new FileOutputStream(fileName); + } + +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java new file mode 100644 index 0000000000..c75a54eccf --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java @@ -0,0 +1,27 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.utils; + +import java.io.FileNotFoundException; +import java.io.OutputStream; + +public interface StreamFactory { + OutputStream createOutputFileStream(String fileName) throws FileNotFoundException; +} diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index 1f6e1a57cf..db10484442 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -19,6 +19,7 @@ */ package org.sonar.cxx.sensors.functioncomplexity; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.Serializable; @@ -44,6 +45,7 @@ import org.sonar.cxx.CxxAstScanner; import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.sensors.squid.CxxSquidSensor; +import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.cxx.sensors.utils.TestUtils; import org.sonar.squidbridge.api.SourceFile; @@ -53,9 +55,7 @@ public class CxxFunctionComplexitySquidSensorTest { private FileLinesContext fileLinesContext; private CxxLanguage language; private SensorContextTester sensorContext; - private CxxFunctionComplexitySquidSensor sensor; - private Configuration configuration; - //private CxxSquidSensor squidSensor; + private CxxFunctionComplexitySquidSensor sensor; @Before public void setUp(){ @@ -65,11 +65,7 @@ public void setUp(){ language = TestUtils.mockCxxLanguage(); when(language.getIntegerOption(CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_THRESHOLD_KEY)).thenReturn(Optional.of(5)); - sensor = new CxxFunctionComplexitySquidSensor(language); - - // ActiveRules rules = mock(ActiveRules.class); - // CheckFactory checkFactory = new CheckFactory(rules); - // squidSensor = new CxxSquidSensor(language, fileLinesContextFactory, checkFactory); + sensor = new CxxFunctionComplexitySquidSensor(language); } private DefaultInputFile getInputFile() throws IOException{ @@ -132,5 +128,24 @@ public void testPublishMeasuresForFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); } + + @Test + public void testSaveRankedListToFile() throws IOException{ + DefaultInputFile inputFile = getInputFile(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + StreamFactory streamFactory = mock(StreamFactory.class); + when(streamFactory.createOutputFileStream("complex_functions.txt")).thenReturn(outputStream); + + when(language.getStringOption(CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_FILE_NAME_KEY)).thenReturn(Optional.of("complex_functions.txt")); + + this.sensor = new CxxFunctionComplexitySquidSensor(this.language); + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.setFileStreamFactory(streamFactory); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + String fileData = new String(outputStream.toByteArray(), "UTF-8"); + assertThat(fileData).isNotEmpty(); + } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 5835791d5f..7d3c9f53bc 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -19,6 +19,7 @@ */ package org.sonar.cxx.sensors.functionsize; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.Serializable; @@ -42,7 +43,9 @@ import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.cxx.CxxAstScanner; import org.sonar.cxx.CxxLanguage; +import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; +import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.cxx.sensors.utils.TestUtils; import org.sonar.squidbridge.api.SourceFile; @@ -123,5 +126,24 @@ public void testPublishMeasuresForFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); } + + @Test + public void testSaveRankedListToFile() throws IOException{ + DefaultInputFile inputFile = getInputFile(); + + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + StreamFactory streamFactory = mock(StreamFactory.class); + when(streamFactory.createOutputFileStream("big_functions.txt")).thenReturn(outputStream); + + when(language.getStringOption(CxxFunctionSizeSquidSensor.FUNCTION_SIZE_FILE_NAME_KEY)).thenReturn(Optional.of("big_functions.txt")); + + this.sensor = new CxxFunctionSizeSquidSensor(this.language); + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.setFileStreamFactory(streamFactory); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + String fileData = new String(outputStream.toByteArray(), "UTF-8"); + assertThat(fileData).isNotEmpty(); + } } From f2940bd322707f63d48d366854a550ab44f77cb8 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 26 Jan 2018 10:14:19 +0000 Subject: [PATCH 07/19] More metrics. % of Lines of Code in Big Functions % of Lines of Code in Complex Functions. --- .../CxxFunctionComplexitySquidSensor.java | 109 ++++++++++++----- .../FunctionComplexityMetrics.java | 23 +++- .../functioncomplexity/FunctionCount.java | 4 +- .../CxxFunctionSizeSquidSensor.java | 113 +++++++++++++----- .../functionsize/FunctionSizeMetrics.java | 16 ++- .../CxxFunctionComplexitySquidSensorTest.java | 22 ++-- .../CxxFunctionSizeSquidSensorTest.java | 16 +-- 7 files changed, 217 insertions(+), 86 deletions(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index cdf82cac04..ecb539850d 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -35,6 +35,7 @@ import org.sonar.api.utils.log.Loggers; import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.api.CxxMetric; +import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine; import org.sonar.cxx.parser.CxxGrammarImpl; import static org.sonar.cxx.sensors.clangtidy.CxxClangTidySensor.REPORT_PATH_KEY; import org.sonar.cxx.sensors.squid.SquidSensor; @@ -55,19 +56,17 @@ public class CxxFunctionComplexitySquidSensor extends SquidAstVisitor i private int cyclomaticComplexityThreshold; private int functionsBelowThreshold; - - public int getFunctionsBelowThreshold(){ - return this.functionsBelowThreshold; - } - + private int functionsOverThreshold; - public int getFunctionsOverThreshold(){ - return this.functionsOverThreshold; - } + private int linesOfCodeBelowThreshold; + + private int linesOfCodeOverThreshold; private Hashtable complexFunctionsPerFile = new Hashtable<>(); + private Hashtable locInComplexFunctionsPerFile = new Hashtable<>(); + private String fileName; private StreamFactory streamFactory; @@ -107,9 +106,10 @@ public void leaveNode(AstNode node) { SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class); int complexity = ChecksHelper.getRecursiveMeasureInt(sourceFunction, CxxMetric.COMPLEXITY); + int lineCount = getNumberOfLine(node); - incrementFunctionByThresholdForAllFiles(complexity); - incrementFunctionByThresholdForFile(sourceFile, complexity); + incrementFunctionByThresholdForAllFiles(complexity, lineCount); + incrementFunctionByThresholdForFile(sourceFile, complexity, lineCount); appendRankedList(sourceFunction, complexity); } @@ -141,45 +141,88 @@ private void dumpRankedList(){ } } - private void incrementFunctionByThresholdForAllFiles(int complexity){ - if (complexity > this.cyclomaticComplexityThreshold) + private void incrementFunctionByThresholdForAllFiles(int complexity, int lineCount){ + if (complexity > this.cyclomaticComplexityThreshold){ this.functionsOverThreshold++; - else + this.linesOfCodeOverThreshold += lineCount; + } + else { this.functionsBelowThreshold++; + this.linesOfCodeBelowThreshold += lineCount; + } } - private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int complexity){ + private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int complexity, int loc){ if (!complexFunctionsPerFile.containsKey(sourceFile)) complexFunctionsPerFile.put(sourceFile, new FunctionCount()); + + if (!locInComplexFunctionsPerFile.containsKey(sourceFile)) + locInComplexFunctionsPerFile.put(sourceFile, new FunctionCount()); - FunctionCount count = complexFunctionsPerFile.get(sourceFile); - if (complexity > this.cyclomaticComplexityThreshold) - count.functionsOverThreshold++; - else - count.functionsBelowThreshold++; + FunctionCount functionCount = complexFunctionsPerFile.get(sourceFile); + FunctionCount locCount = locInComplexFunctionsPerFile.get(sourceFile); + if (complexity > this.cyclomaticComplexityThreshold){ + functionCount.countOverThreshold++; + locCount.countOverThreshold += loc; + } + else { + functionCount.countBelowThreshold++; + locCount.countBelowThreshold += loc; + } } @Override public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { + publishComplexFunctionMetricsForFile(inputFile, squidFile, context); + publishLocInComplexFunctionMetricsForFile(inputFile, squidFile, context); + } + + private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFile squidFile, SensorContext context){ FunctionCount c = complexFunctionsPerFile.get(squidFile); if (c == null) - return; + return; context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) .on(inputFile) - .withValue(c.functionsOverThreshold) - .save(); + .withValue((int)c.countOverThreshold) + .save(); context.newMeasure() .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) .on(inputFile) - .withValue(calculatePercComplexFunctions(c.functionsOverThreshold, c.functionsBelowThreshold)) + .withValue(calculatePercentage((int)c.countOverThreshold, (int)c.countBelowThreshold)) .save(); } + + private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, SourceFile squidFile, SensorContext context){ + FunctionCount locCount = locInComplexFunctionsPerFile.get(squidFile); + + if (locCount == null) + return; + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(locCount.countOverThreshold) + .save(); + + context.newMeasure() + .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) + .on(inputFile) + .withValue(calculatePercentage((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold)) + .save(); + } @Override public void publishMeasureForProject(InputModule module, SensorContext context) { + publishComplexFunctionMetrics(module, context); + publishLinesOfCodeInComplexFunctionMetrics(module, context); + + dumpRankedList(); + } + + private void publishComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) .on(module) @@ -189,14 +232,26 @@ public void publishMeasureForProject(InputModule module, SensorContext context) context.newMeasure() .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) .on(module) - .withValue(calculatePercComplexFunctions(functionsOverThreshold, functionsBelowThreshold)) + .withValue(calculatePercentage(functionsOverThreshold, functionsBelowThreshold)) .save(); + } + + private void publishLinesOfCodeInComplexFunctionMetrics(InputModule module, SensorContext context){ + context.newMeasure() + .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) + .on(module) + .withValue(linesOfCodeOverThreshold) + .save(); - dumpRankedList(); + context.newMeasure() + .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) + .on(module) + .withValue(calculatePercentage(linesOfCodeOverThreshold, linesOfCodeBelowThreshold)) + .save(); } - private double calculatePercComplexFunctions(int functionsOverThreshold, int functionsBelowThreshold){ - return ((float)functionsOverThreshold * 100.0) / ((float)functionsOverThreshold + (float)functionsBelowThreshold); + private double calculatePercentage(int overThreshold, int belowThreshold){ + return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java index 615c99b4f3..5425c8c98a 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -33,10 +33,31 @@ public class FunctionComplexityMetrics implements Metrics { .setQualitative(false) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) .create(); + + public static final Metric PERC_COMPLEX_FUNCTIONS = new Metric.Builder("perc_complex_functions", "% of Complex Functions", Metric.ValueType.PERCENT) + .setDescription("% of functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); + + public static final Metric LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("loc_in_complex_functions", "LoC in Complex Functions", Metric.ValueType.INT) + .setDescription("Number of lines of code in functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); + + public static final Metric PERC_LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("perc_loc_in_complex_functions", "% of LoC in Complex Functions", Metric.ValueType.PERCENT) + .setDescription("% of lines of code in functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); @Override public List getMetrics() { - return asList(COMPLEX_FUNCTIONS); + return asList(COMPLEX_FUNCTIONS, PERC_COMPLEX_FUNCTIONS, LOC_IN_COMPLEX_FUNCTIONS, PERC_LOC_IN_COMPLEX_FUNCTIONS); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java index 201c339739..d085446577 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java @@ -20,7 +20,7 @@ package org.sonar.cxx.sensors.functioncomplexity; public class FunctionCount { - public int functionsOverThreshold; + public int countOverThreshold; - public int functionsBelowThreshold + public int countBelowThreshold; } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 8b73e0a75f..4066385510 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -56,18 +56,16 @@ public class CxxFunctionSizeSquidSensor extends SquidAstVisitor impleme private int sizeThreshold; - public int getFunctionsBelowThreshold(){ - return this.functionsBelowThreshold; - } - private int functionsOverThreshold; - public int getFunctionsOverThreshold(){ - return this.functionsOverThreshold; - } + private int locBelowThreshold; + + private int locOverThreshold; private Hashtable bigFunctionsPerFile = new Hashtable<>(); + private Hashtable locInBigFunctionsPerFile = new Hashtable<>(); + private String fileName; private StreamFactory streamFactory; @@ -136,22 +134,34 @@ private void dumpRankedList(){ } } - private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int complexity){ + private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int lineCount){ if (!bigFunctionsPerFile.containsKey(sourceFile)) bigFunctionsPerFile.put(sourceFile, new FunctionCount()); + + if (!locInBigFunctionsPerFile.containsKey(sourceFile)) + locInBigFunctionsPerFile.put(sourceFile, new FunctionCount()); FunctionCount count = bigFunctionsPerFile.get(sourceFile); - if (complexity > this.sizeThreshold) - count.functionsOverThreshold++; - else - count.functionsBelowThreshold++; + FunctionCount locCount = locInBigFunctionsPerFile.get(sourceFile); + if (lineCount > this.sizeThreshold){ + count.countOverThreshold++; + locCount.countOverThreshold += lineCount; + } + else { + count.countBelowThreshold++; + locCount.countBelowThreshold += lineCount; + } } private void incrementFunctionByThresholdForProject(int lineCount){ - if (lineCount > sizeThreshold) + if (lineCount > sizeThreshold) { this.functionsOverThreshold++; - else + this.locOverThreshold += lineCount; + } + else { this.functionsBelowThreshold++; + this.locBelowThreshold += lineCount; + } } @@ -162,6 +172,50 @@ public SquidAstVisitor getVisitor() { @Override public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { + publishBigFunctionMetrics(inputFile, squidFile, context); + publishLocInBigFunctionMetrics(inputFile, squidFile, context); + } + + @Override + public void publishMeasureForProject(InputModule module, SensorContext context) { + publishBigFunctionCountForProject(module, context); + publishLocInBigFunctionForProject(module, context); + dumpRankedList(); + } + + private void publishBigFunctionCountForProject(InputModule module, SensorContext context){ + context.newMeasure() + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) + .on(module) + .withValue(functionsOverThreshold) + .save(); + + context.newMeasure() + .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) + .on(module) + .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) + .save(); + } + + private void publishLocInBigFunctionForProject(InputModule module, SensorContext context){ + context.newMeasure() + .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) + .on(module) + .withValue(locOverThreshold) + .save(); + + context.newMeasure() + .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) + .on(module) + .withValue(calculatePercentual(locOverThreshold, locBelowThreshold)) + .save(); + } + + private double calculatePercentual(int overThreshold, int belowThreshold){ + return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); + } + + private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile, SensorContext context) { FunctionCount c = bigFunctionsPerFile.get(squidFile); if (c == null) return; @@ -169,35 +223,32 @@ public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, Sen context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) .on(inputFile) - .withValue(c.functionsOverThreshold) + .withValue((int)c.countOverThreshold) .save(); context.newMeasure() .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) .on(inputFile) - .withValue(calculatePercComplexFunctions(c.functionsOverThreshold, c.functionsBelowThreshold)) + .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); } - @Override - public void publishMeasureForProject(InputModule module, SensorContext context) { + private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squidFile, SensorContext context) { + FunctionCount c = locInBigFunctionsPerFile.get(squidFile); + if (c == null) + return; + context.newMeasure() - .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) - .on(module) - .withValue(functionsOverThreshold) + .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) + .on(inputFile) + .withValue((int)c.countOverThreshold) .save(); - + context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) - .on(module) - .withValue(calculatePercComplexFunctions(functionsOverThreshold, functionsBelowThreshold)) + .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) + .on(inputFile) + .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); - - dumpRankedList(); - } - - private double calculatePercComplexFunctions(int functionsOverThreshold, int functionsBelowThreshold){ - return ((float)functionsOverThreshold * 100.0) / ((float)functionsOverThreshold + (float)functionsBelowThreshold); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java index f7e73c0f1b..f40d57dd64 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java @@ -35,16 +35,30 @@ public class FunctionSizeMetrics implements Metrics { .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); + public static final Metric LOC_IN_BIG_FUNCTIONS = new Metric.Builder("loc_in_big_functions", "LoC in Big Functions", Metric.ValueType.INT) + .setDescription("Number of lines of code in functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + public static final Metric PERC_BIG_FUNCTIONS = new Metric.Builder("perc_big_functions", "% of Big Functions", Metric.ValueType.PERCENT) .setDescription("% of functions with too many lines") .setDirection(Metric.DIRECTION_WORST) .setQualitative(false) .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); + +public static final Metric PERC_LOC_IN_BIG_FUNCTIONS = new Metric.Builder("perc_loc_in_big_functions", "% of LoC in Big Functions", Metric.ValueType.PERCENT) + .setDescription("% of lines of code in functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); @Override public List getMetrics() { - return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS); + return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS, LOC_IN_BIG_FUNCTIONS, PERC_LOC_IN_BIG_FUNCTIONS); } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index db10484442..db10810121 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -93,21 +93,11 @@ private T getMeasureValue(SensorContextTester sensorCon Collection measures = sensorContext.measures(componentKey); T value = null; for(Measure m : measures){ - if (m.metric() == FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + if (m.metric() == metric) value = (T) m.value(); } return value; - } - - @Test - public void testFunctionsOverAndBelowThresholdForProject() throws IOException { - DefaultInputFile inputFile = getInputFile(); - - CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - - assertThat(sensor.getFunctionsBelowThreshold()).isEqualTo(6); - assertThat(sensor.getFunctionsOverThreshold()).isEqualTo(4); - } + } @Test public void testPublishMeasuresForProject() throws IOException { @@ -116,7 +106,10 @@ public void testPublishMeasuresForProject() throws IOException { CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); } @Test @@ -127,6 +120,9 @@ public void testPublishMeasuresForFile() throws IOException { sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); } @Test diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 7d3c9f53bc..1ae2361fb3 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -83,17 +83,7 @@ private DefaultInputFile getInputFile() throws IOException{ when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); return inputFile; - } - - @Test - public void testFunctionsOverAndBelowThresholdForProject() throws IOException { - DefaultInputFile inputFile = getInputFile(); - - CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - - assertThat(sensor.getFunctionsBelowThreshold()).isEqualTo(6); - assertThat(sensor.getFunctionsOverThreshold()).isEqualTo(4); - } + } private T getMeasureValue(SensorContextTester sensorContext, String componentKey, Metric metric){ Collection measures = sensorContext.measures(componentKey); @@ -113,7 +103,9 @@ public void testPublishMeasuresForProject() throws IOException { sensor.publishMeasureForProject(sensorContext.module(), sensorContext); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); } @Test @@ -124,7 +116,9 @@ public void testPublishMeasuresForFile() throws IOException { sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); } @Test From d09de2c05a51da868c321534b2335acace96b2f5 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Wed, 31 Jan 2018 11:44:36 +0000 Subject: [PATCH 08/19] Implementing lines of code in functions metric. --- .../functionsize/CxxFunctionSizeSquidSensor.java | 14 +++++++++++++- .../sensors/functionsize/FunctionSizeMetrics.java | 11 +++++++++-- .../CxxFunctionSizeSquidSensorTest.java | 2 ++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 4066385510..1b8fc4cbac 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -198,6 +198,12 @@ private void publishBigFunctionCountForProject(InputModule module, SensorContext } private void publishLocInBigFunctionForProject(InputModule module, SensorContext context){ + context.newMeasure() + .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) + .on(module) + .withValue(locOverThreshold + locBelowThreshold) + .save(); + context.newMeasure() .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) .on(module) @@ -238,10 +244,16 @@ private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squi if (c == null) return; + context.newMeasure() + .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) + .on(inputFile) + .withValue(c.countOverThreshold + c.countBelowThreshold) + .save(); + context.newMeasure() .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) .on(inputFile) - .withValue((int)c.countOverThreshold) + .withValue(c.countOverThreshold) .save(); context.newMeasure() diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java index f40d57dd64..d9033e2b9b 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java @@ -49,16 +49,23 @@ public class FunctionSizeMetrics implements Metrics { .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); -public static final Metric PERC_LOC_IN_BIG_FUNCTIONS = new Metric.Builder("perc_loc_in_big_functions", "% of LoC in Big Functions", Metric.ValueType.PERCENT) + public static final Metric PERC_LOC_IN_BIG_FUNCTIONS = new Metric.Builder("perc_loc_in_big_functions", "% of LoC in Big Functions", Metric.ValueType.PERCENT) .setDescription("% of lines of code in functions with too many lines") .setDirection(Metric.DIRECTION_WORST) .setQualitative(false) .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); + + public static final Metric LOC_IN_FUNCTIONS = new Metric.Builder("loc_in_functions", "LoC in Functions", Metric.ValueType.INT) + .setDescription("Number of lines of code in function bodies") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); @Override public List getMetrics() { - return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS, LOC_IN_BIG_FUNCTIONS, PERC_LOC_IN_BIG_FUNCTIONS); + return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS, LOC_IN_BIG_FUNCTIONS, PERC_LOC_IN_BIG_FUNCTIONS, LOC_IN_FUNCTIONS); } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 1ae2361fb3..37f06479d5 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -103,6 +103,7 @@ public void testPublishMeasuresForProject() throws IOException { sensor.publishMeasureForProject(sensorContext.module(), sensorContext); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); @@ -116,6 +117,7 @@ public void testPublishMeasuresForFile() throws IOException { sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); From 15c1c63adf1bfc549b5c230138cb70451080eaef Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Wed, 31 Jan 2018 14:04:50 +0000 Subject: [PATCH 09/19] Removing new metrics from C Plugin --- .../java/org/sonar/plugins/c/CPlugin.java | 30 ++----------------- .../java/org/sonar/plugins/c/CPluginTest.java | 2 +- 2 files changed, 3 insertions(+), 29 deletions(-) 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 616d02edd2..1e2f5b2e1a 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 @@ -48,10 +48,6 @@ import org.sonar.cxx.sensors.cppcheck.CxxCppCheckSensor; import org.sonar.cxx.sensors.drmemory.CxxDrMemoryRuleRepository; import org.sonar.cxx.sensors.drmemory.CxxDrMemorySensor; -import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; -import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; -import org.sonar.cxx.sensors.functionsize.CxxFunctionSizeSquidSensor; -import org.sonar.cxx.sensors.functionsize.FunctionSizeMetrics; import org.sonar.cxx.sensors.other.CxxOtherRepository; import org.sonar.cxx.sensors.other.CxxOtherSensor; import org.sonar.cxx.sensors.pclint.CxxPCLintRuleRepository; @@ -328,25 +324,7 @@ private static List codeAnalysisProperties() { .type(PropertyType.TEXT) .subCategory(subcateg) .index(17) - .build(), - PropertyDefinition.builder(LANG_PROP_PREFIX + CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_THRESHOLD_KEY) - .defaultValue("10") - .name("Cyclomatic complexity threshold") - .description("Cyclomatic complexity threshold used to classify a function as complex") - .subCategory(subcateg) - .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) - .type(PropertyType.INTEGER) - .index(18) - .build(), - PropertyDefinition.builder(LANG_PROP_PREFIX + CxxFunctionSizeSquidSensor.FUNCTION_SIZE_THRESHOLD_KEY) - .defaultValue("20") - .name("Function size threshold") - .description("Function size threshold to consider a function to be too big") - .subCategory(subcateg) - .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) - .type(PropertyType.INTEGER) - .index(19) - .build() + .build() )); } @@ -487,11 +465,7 @@ public void define(Context context) { l.addAll(codeAnalysisProperties()); l.addAll(testingAndCoverageProperties()); l.addAll(compilerWarningsProperties()); - l.addAll(duplicationsProperties()); - - //extra metrics - l.add(FunctionComplexityMetrics.class); - l.add(FunctionSizeMetrics.class); + l.addAll(duplicationsProperties()); context.addExtensions(l); } diff --git a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java index 04d948c5d2..6549e09140 100644 --- a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java +++ b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java @@ -35,6 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CPlugin plugin = new CPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(72); + assertThat(context.getExtensions()).hasSize(68); } } From 7696b0d43dd9d12417e66e89a459b6cbb0224936 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Wed, 31 Jan 2018 14:17:19 +0000 Subject: [PATCH 10/19] Removing the Scanner side file dumps. --- .../CxxFunctionComplexitySquidSensor.java | 64 ++----------------- .../CxxFunctionSizeSquidSensor.java | 55 +--------------- .../cxx/sensors/utils/FileStreamFactory.java | 35 ---------- .../cxx/sensors/utils/StreamFactory.java | 27 -------- .../CxxFunctionComplexitySquidSensorTest.java | 23 +------ .../CxxFunctionSizeSquidSensorTest.java | 25 +------- .../java/org/sonar/plugins/c/CPlugin.java | 2 +- 7 files changed, 12 insertions(+), 219 deletions(-) delete mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java delete mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index ecb539850d..47ea12a8c8 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -39,8 +39,6 @@ import org.sonar.cxx.parser.CxxGrammarImpl; import static org.sonar.cxx.sensors.clangtidy.CxxClangTidySensor.REPORT_PATH_KEY; import org.sonar.cxx.sensors.squid.SquidSensor; -import org.sonar.cxx.sensors.utils.FileStreamFactory; -import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -50,8 +48,7 @@ public class CxxFunctionComplexitySquidSensor extends SquidAstVisitor i private static final Logger LOG = Loggers.get(CxxFunctionComplexitySquidSensor.class); - public static final String FUNCTION_COMPLEXITY_THRESHOLD_KEY = "funccomplexity.threshold"; - public static final String FUNCTION_COMPLEXITY_FILE_NAME_KEY = "funccomplexity.filename"; + public static final String FUNCTION_COMPLEXITY_THRESHOLD_KEY = "funccomplexity.threshold"; private int cyclomaticComplexityThreshold; @@ -67,28 +64,12 @@ public class CxxFunctionComplexitySquidSensor extends SquidAstVisitor i private Hashtable locInComplexFunctionsPerFile = new Hashtable<>(); - private String fileName; - - private StreamFactory streamFactory; - - private TreeSet rankedList = new TreeSet(new FunctionScoreComparator()); - public SortedSet getRankedList(){ - return this.rankedList; - } + private String fileName; public CxxFunctionComplexitySquidSensor(CxxLanguage language){ this.cyclomaticComplexityThreshold = language.getIntegerOption(FUNCTION_COMPLEXITY_THRESHOLD_KEY).orElse(10); - LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); - - this.fileName = language.getStringOption(FUNCTION_COMPLEXITY_FILE_NAME_KEY).orElse(""); - LOG.debug("File name to dump CC data: " + this.fileName); - - this.streamFactory = new FileStreamFactory(); - } - - public void setFileStreamFactory(StreamFactory factory){ - this.streamFactory = factory; - } + LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); + } @Override public SquidAstVisitor getVisitor() { @@ -109,37 +90,8 @@ public void leaveNode(AstNode node) { int lineCount = getNumberOfLine(node); incrementFunctionByThresholdForAllFiles(complexity, lineCount); - incrementFunctionByThresholdForFile(sourceFile, complexity, lineCount); - appendRankedList(sourceFunction, complexity); - } - - private void appendRankedList(SourceFunction sourceFunction, int complexity){ - if (fileName.equals("")) - return; - - FunctionScore score = new FunctionScore(complexity, getContext().getFile().getName(), sourceFunction.getKey()); - this.rankedList.add(score); - } - - private void writeScore(OutputStream stream, FunctionScore score) throws IOException{ - stream.write((score.getComponentName() + "\t" + score.getFunctionId() + "\t" + score.getScore() + System.lineSeparator()).getBytes()); - } - - private void dumpRankedList(){ - if (fileName.equals("")) - return; - - try { - OutputStream stream = streamFactory.createOutputFileStream(this.fileName); - for(FunctionScore score : rankedList) - writeScore(stream, score); - stream.flush(); - stream.close(); - } - catch (Exception e){ - LOG.error("Couldn't write ranked list to " + fileName + ". Exception text: " + e.getMessage()); - } - } + incrementFunctionByThresholdForFile(sourceFile, complexity, lineCount); + } private void incrementFunctionByThresholdForAllFiles(int complexity, int lineCount){ if (complexity > this.cyclomaticComplexityThreshold){ @@ -217,9 +169,7 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour @Override public void publishMeasureForProject(InputModule module, SensorContext context) { publishComplexFunctionMetrics(module, context); - publishLinesOfCodeInComplexFunctionMetrics(module, context); - - dumpRankedList(); + publishLinesOfCodeInComplexFunctionMetrics(module, context); } private void publishComplexFunctionMetrics(InputModule module, SensorContext context){ diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 1b8fc4cbac..90a7f6bdb7 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -39,8 +39,6 @@ import org.sonar.cxx.sensors.functioncomplexity.FunctionScore; import org.sonar.cxx.sensors.functioncomplexity.FunctionScoreComparator; import org.sonar.cxx.sensors.squid.SquidSensor; -import org.sonar.cxx.sensors.utils.FileStreamFactory; -import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -50,7 +48,6 @@ public class CxxFunctionSizeSquidSensor extends SquidAstVisitor impleme private static final Logger LOG = Loggers.get(CxxFunctionSizeSquidSensor.class); public static final String FUNCTION_SIZE_THRESHOLD_KEY = "funcsize.threshold"; - public static final String FUNCTION_SIZE_FILE_NAME_KEY = "funcsize.filename"; private int functionsBelowThreshold; @@ -64,29 +61,11 @@ public class CxxFunctionSizeSquidSensor extends SquidAstVisitor impleme private Hashtable bigFunctionsPerFile = new Hashtable<>(); - private Hashtable locInBigFunctionsPerFile = new Hashtable<>(); - - private String fileName; - - private StreamFactory streamFactory; - - private TreeSet rankedList = new TreeSet(new FunctionScoreComparator()); - public SortedSet getRankedList(){ - return this.rankedList; - } - - public void setFileStreamFactory(StreamFactory factory){ - this.streamFactory = factory; - } + private Hashtable locInBigFunctionsPerFile = new Hashtable<>(); public CxxFunctionSizeSquidSensor(CxxLanguage language){ this.sizeThreshold = language.getIntegerOption(FUNCTION_SIZE_THRESHOLD_KEY).orElse(20); LOG.debug("Function size threshold: " + this.sizeThreshold); - - this.fileName = language.getStringOption(FUNCTION_SIZE_FILE_NAME_KEY).orElse(""); - LOG.debug("File name to dump function size data: " + this.fileName); - - this.streamFactory = new FileStreamFactory(); } @Override @@ -102,38 +81,9 @@ public void leaveNode(AstNode node) { int lineCount = getNumberOfLine(node); incrementFunctionByThresholdForProject(lineCount); - incrementFunctionByThresholdForFile(sourceFile, lineCount); - appendRankedList(sourceFunction, lineCount); + incrementFunctionByThresholdForFile(sourceFile, lineCount); } - private void appendRankedList(SourceFunction sourceFunction, int complexity){ - if (fileName.equals("")) - return; - - FunctionScore score = new FunctionScore(complexity, getContext().getFile().getName(), sourceFunction.getKey()); - this.rankedList.add(score); - } - - private void writeScore(OutputStream stream, FunctionScore score) throws IOException{ - stream.write((score.getComponentName() + "\t" + score.getFunctionId() + "\t" + score.getScore() + System.lineSeparator()).getBytes()); - } - - private void dumpRankedList(){ - if (fileName.equals("")) - return; - - try { - OutputStream stream = streamFactory.createOutputFileStream(this.fileName); - for(FunctionScore score : rankedList) - writeScore(stream, score); - stream.flush(); - stream.close(); - } - catch (Exception e){ - LOG.error("Couldn't write ranked list to " + fileName + ". Exception text: " + e.getMessage()); - } - } - private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int lineCount){ if (!bigFunctionsPerFile.containsKey(sourceFile)) bigFunctionsPerFile.put(sourceFile, new FunctionCount()); @@ -180,7 +130,6 @@ public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, Sen public void publishMeasureForProject(InputModule module, SensorContext context) { publishBigFunctionCountForProject(module, context); publishLocInBigFunctionForProject(module, context); - dumpRankedList(); } private void publishBigFunctionCountForProject(InputModule module, SensorContext context){ diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java deleted file mode 100644 index 059182c86f..0000000000 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/FileStreamFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity - * http://github.com/SonarOpenCommunity/sonar-cxx - * - * This program 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. - * - * This program 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.cxx.sensors.utils; - -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.OutputStream; -import java.util.logging.Level; -import java.util.logging.Logger; - -public class FileStreamFactory implements StreamFactory { - - @Override - public OutputStream createOutputFileStream(String fileName) throws FileNotFoundException{ - return new FileOutputStream(fileName); - } - -} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java deleted file mode 100644 index c75a54eccf..0000000000 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/utils/StreamFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity - * http://github.com/SonarOpenCommunity/sonar-cxx - * - * This program 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. - * - * This program 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.cxx.sensors.utils; - -import java.io.FileNotFoundException; -import java.io.OutputStream; - -public interface StreamFactory { - OutputStream createOutputFileStream(String fileName) throws FileNotFoundException; -} diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index db10810121..c3e961d690 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -45,7 +45,6 @@ import org.sonar.cxx.CxxAstScanner; import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.sensors.squid.CxxSquidSensor; -import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.cxx.sensors.utils.TestUtils; import org.sonar.squidbridge.api.SourceFile; @@ -123,25 +122,5 @@ public void testPublishMeasuresForFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); - } - - @Test - public void testSaveRankedListToFile() throws IOException{ - DefaultInputFile inputFile = getInputFile(); - - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - StreamFactory streamFactory = mock(StreamFactory.class); - when(streamFactory.createOutputFileStream("complex_functions.txt")).thenReturn(outputStream); - - when(language.getStringOption(CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_FILE_NAME_KEY)).thenReturn(Optional.of("complex_functions.txt")); - - this.sensor = new CxxFunctionComplexitySquidSensor(this.language); - SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - sensor.setFileStreamFactory(streamFactory); - sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - String fileData = new String(outputStream.toByteArray(), "UTF-8"); - assertThat(fileData).isNotEmpty(); - } - + } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 37f06479d5..b651df4618 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -43,9 +43,6 @@ import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.cxx.CxxAstScanner; import org.sonar.cxx.CxxLanguage; -import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; -import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; -import org.sonar.cxx.sensors.utils.StreamFactory; import org.sonar.cxx.sensors.utils.TestUtils; import org.sonar.squidbridge.api.SourceFile; @@ -121,25 +118,5 @@ public void testPublishMeasuresForFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); - } - - @Test - public void testSaveRankedListToFile() throws IOException{ - DefaultInputFile inputFile = getInputFile(); - - ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); - StreamFactory streamFactory = mock(StreamFactory.class); - when(streamFactory.createOutputFileStream("big_functions.txt")).thenReturn(outputStream); - - when(language.getStringOption(CxxFunctionSizeSquidSensor.FUNCTION_SIZE_FILE_NAME_KEY)).thenReturn(Optional.of("big_functions.txt")); - - this.sensor = new CxxFunctionSizeSquidSensor(this.language); - SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - sensor.setFileStreamFactory(streamFactory); - sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - String fileData = new String(outputStream.toByteArray(), "UTF-8"); - assertThat(fileData).isNotEmpty(); - } - + } } 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 1e2f5b2e1a..9f404eb253 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 @@ -465,7 +465,7 @@ public void define(Context context) { l.addAll(codeAnalysisProperties()); l.addAll(testingAndCoverageProperties()); l.addAll(compilerWarningsProperties()); - l.addAll(duplicationsProperties()); + l.addAll(duplicationsProperties()); context.addExtensions(l); } From a31b02e73b4a476d7b16aedfd781bbd81177e761 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Thu, 1 Feb 2018 10:36:59 +0000 Subject: [PATCH 11/19] Registering new SquidSensors only for C++ language. --- .../java/org/sonar/cxx/sensors/squid/CxxSquidSensor.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) 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 8077d27ee1..250b5fd705 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 @@ -123,8 +123,10 @@ public CxxSquidSensor(CxxLanguage language, } protected void registerSquidSensors(){ - this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); - this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); + if (this.language.getKey() == "c++"){ + this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); + this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); + } } @Override From 6993e23047f3958e138f219eb28ae4f1a24d59b4 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Thu, 1 Feb 2018 11:30:39 +0000 Subject: [PATCH 12/19] Adding checks and tests to avoid NaN double metrics. --- .../CxxFunctionComplexitySquidSensor.java | 30 ++++++++----- .../CxxFunctionSizeSquidSensor.java | 30 ++++++++----- .../CxxFunctionComplexitySquidSensorTest.java | 45 ++++++++++++++++++- .../CxxFunctionSizeSquidSensorTest.java | 45 +++++++++++++++++++ .../org/sonar/cxx/sensors/EmptyFile.cc | 1 + 5 files changed, 130 insertions(+), 21 deletions(-) create mode 100644 cxx-sensors/src/test/resources/org/sonar/cxx/sensors/EmptyFile.cc diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index 47ea12a8c8..e783f22e5a 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -131,8 +131,11 @@ public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, Sen private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFile squidFile, SensorContext context){ FunctionCount c = complexFunctionsPerFile.get(squidFile); - if (c == null) - return; + if (c == null){ + c = new FunctionCount(); + c.countBelowThreshold = 0; + c.countOverThreshold = 0; + } context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) @@ -143,15 +146,18 @@ private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFil context.newMeasure() .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) .on(inputFile) - .withValue(calculatePercentage((int)c.countOverThreshold, (int)c.countBelowThreshold)) + .withValue(calculatePercentual((int)c.countOverThreshold, (int)c.countBelowThreshold)) .save(); } private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, SourceFile squidFile, SensorContext context){ FunctionCount locCount = locInComplexFunctionsPerFile.get(squidFile); - if (locCount == null) - return; + if (locCount == null){ + locCount = new FunctionCount(); + locCount.countBelowThreshold = 0; + locCount.countOverThreshold = 0; + } context.newMeasure() .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) @@ -162,7 +168,7 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour context.newMeasure() .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) .on(inputFile) - .withValue(calculatePercentage((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold)) + .withValue(calculatePercentual((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold)) .save(); } @@ -182,7 +188,7 @@ private void publishComplexFunctionMetrics(InputModule module, SensorContext con context.newMeasure() .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) .on(module) - .withValue(calculatePercentage(functionsOverThreshold, functionsBelowThreshold)) + .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) .save(); } @@ -196,12 +202,16 @@ private void publishLinesOfCodeInComplexFunctionMetrics(InputModule module, Sens context.newMeasure() .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) .on(module) - .withValue(calculatePercentage(linesOfCodeOverThreshold, linesOfCodeBelowThreshold)) + .withValue(calculatePercentual(linesOfCodeOverThreshold, linesOfCodeBelowThreshold)) .save(); } - private double calculatePercentage(int overThreshold, int belowThreshold){ - return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); + private double calculatePercentual(int overThreshold, int belowThreshold){ + double total = (double)overThreshold + (double)belowThreshold; + if (total > 0) + return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); + else + return 0; } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 90a7f6bdb7..58829090cf 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -49,15 +49,15 @@ public class CxxFunctionSizeSquidSensor extends SquidAstVisitor impleme public static final String FUNCTION_SIZE_THRESHOLD_KEY = "funcsize.threshold"; - private int functionsBelowThreshold; + private int functionsBelowThreshold = 0; - private int sizeThreshold; + private int sizeThreshold = 0; - private int functionsOverThreshold; + private int functionsOverThreshold = 0; - private int locBelowThreshold; + private int locBelowThreshold = 0; - private int locOverThreshold; + private int locOverThreshold = 0; private Hashtable bigFunctionsPerFile = new Hashtable<>(); @@ -167,13 +167,20 @@ private void publishLocInBigFunctionForProject(InputModule module, SensorContext } private double calculatePercentual(int overThreshold, int belowThreshold){ - return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); + double total = (double)overThreshold + (double)belowThreshold; + if (total > 0) + return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); + else + return 0; } private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile, SensorContext context) { FunctionCount c = bigFunctionsPerFile.get(squidFile); - if (c == null) - return; + if (c == null){ + c = new FunctionCount(); + c.countBelowThreshold = 0; + c.countOverThreshold = 0; + } context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) @@ -190,8 +197,11 @@ private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squidFile, SensorContext context) { FunctionCount c = locInBigFunctionsPerFile.get(squidFile); - if (c == null) - return; + if (c == null) { + c = new FunctionCount(); + c.countBelowThreshold = 0; + c.countOverThreshold = 0; + } context.newMeasure() .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index c3e961d690..b3d27661f8 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -84,6 +84,23 @@ private DefaultInputFile getInputFile() throws IOException{ return inputFile; } + private DefaultInputFile getEmptyInputFile() throws IOException{ + File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); + File target = new File(baseDir, "EmptyFile.cc"); + + String content = new String(Files.readAllBytes(target.toPath()), "UTF-8"); + DefaultInputFile inputFile = TestInputFileBuilder.create("ProjectKey", baseDir, target).setContents(content) + .setCharset(Charset.forName("UTF-8")).setLanguage(language.getKey()) + .setType(InputFile.Type.MAIN).build(); + + sensorContext = SensorContextTester.create(baseDir); + sensorContext.fileSystem().add(inputFile); + + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + + return inputFile; + } + public boolean containsAll(Collection c){ return false; } @@ -109,7 +126,20 @@ public void testPublishMeasuresForProject() throws IOException { assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); - } + } + + @Test + public void testPublishMeasuresForEmptyProject() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + } @Test public void testPublishMeasuresForFile() throws IOException { @@ -123,4 +153,17 @@ public void testPublishMeasuresForFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); } + + @Test + public void testPublishMeasuresForEmptyFile() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index b651df4618..7111629f04 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -82,6 +82,23 @@ private DefaultInputFile getInputFile() throws IOException{ return inputFile; } + private DefaultInputFile getEmptyInputFile() throws IOException{ + File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); + File target = new File(baseDir, "EmptyFile.cc"); + + String content = new String(Files.readAllBytes(target.toPath()), "UTF-8"); + DefaultInputFile inputFile = TestInputFileBuilder.create("ProjectKey", baseDir, target).setContents(content) + .setCharset(Charset.forName("UTF-8")).setLanguage(language.getKey()) + .setType(InputFile.Type.MAIN).build(); + + sensorContext = SensorContextTester.create(baseDir); + sensorContext.fileSystem().add(inputFile); + + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + + return inputFile; + } + private T getMeasureValue(SensorContextTester sensorContext, String componentKey, Metric metric){ Collection measures = sensorContext.measures(componentKey); T value = null; @@ -106,6 +123,20 @@ public void testPublishMeasuresForProject() throws IOException { assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); } + @Test + public void testPublishMeasuresForEmptyProject() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + } + @Test public void testPublishMeasuresForFile() throws IOException { DefaultInputFile inputFile = getInputFile(); @@ -119,4 +150,18 @@ public void testPublishMeasuresForFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); } + + @Test + public void testPublishMeasuresForEmptyFile() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + } } diff --git a/cxx-sensors/src/test/resources/org/sonar/cxx/sensors/EmptyFile.cc b/cxx-sensors/src/test/resources/org/sonar/cxx/sensors/EmptyFile.cc new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/cxx-sensors/src/test/resources/org/sonar/cxx/sensors/EmptyFile.cc @@ -0,0 +1 @@ + From dc0cbed4a3d9d99113b680771ede42c4ffd445a9 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Thu, 26 Apr 2018 11:33:53 -0700 Subject: [PATCH 13/19] - Removing metric definitions from this project - Adding reference to sonar-opencommunity-metrics - Changing all code to reference metrics defined in sonar-opencommunity-metrics, which now is responsible for the aggregated numbers. --- cxx-sensors/pom.xml | 5 ++ .../CxxFunctionComplexitySquidSensor.java | 20 +++--- .../FunctionComplexityMetrics.java | 63 ---------------- .../CxxFunctionSizeSquidSensor.java | 31 ++++---- .../functionsize/FunctionSizeMetrics.java | 71 ------------------- .../cxx/sensors/squid/CxxSquidSensor.java | 8 +-- .../CxxFunctionComplexitySquidSensorTest.java | 45 +++--------- .../CxxFunctionSizeSquidSensorTest.java | 51 ++++--------- .../java/org/sonar/plugins/cxx/CxxPlugin.java | 6 -- .../org/sonar/plugins/cxx/CxxPluginTest.java | 2 +- 10 files changed, 53 insertions(+), 249 deletions(-) delete mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java delete mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java diff --git a/cxx-sensors/pom.xml b/cxx-sensors/pom.xml index b1f77ba7c3..6c944d53dc 100644 --- a/cxx-sensors/pom.xml +++ b/cxx-sensors/pom.xml @@ -101,5 +101,10 @@ assertj-core test + + org.sonar.opencommunity.metrics + sonar-opencommunity-metrics + 0.9.9 + diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index e783f22e5a..fbb3470fdf 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -39,6 +39,7 @@ import org.sonar.cxx.parser.CxxGrammarImpl; import static org.sonar.cxx.sensors.clangtidy.CxxClangTidySensor.REPORT_PATH_KEY; import org.sonar.cxx.sensors.squid.SquidSensor; +import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -138,13 +139,13 @@ private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFil } context.newMeasure() - .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS) .on(inputFile) .withValue((int)c.countOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC) .on(inputFile) .withValue(calculatePercentual((int)c.countOverThreshold, (int)c.countBelowThreshold)) .save(); @@ -160,13 +161,13 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour } context.newMeasure() - .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC) .on(inputFile) .withValue(locCount.countOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) .on(inputFile) .withValue(calculatePercentual((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold)) .save(); @@ -174,19 +175,18 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour @Override public void publishMeasureForProject(InputModule module, SensorContext context) { - publishComplexFunctionMetrics(module, context); - publishLinesOfCodeInComplexFunctionMetrics(module, context); + } private void publishComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS) .on(module) .withValue(functionsOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) .save(); @@ -194,13 +194,13 @@ private void publishComplexFunctionMetrics(InputModule module, SensorContext con private void publishLinesOfCodeInComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC) .on(module) .withValue(linesOfCodeOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) .on(module) .withValue(calculatePercentual(linesOfCodeOverThreshold, linesOfCodeBelowThreshold)) .save(); diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java deleted file mode 100644 index 5425c8c98a..0000000000 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity - * http://github.com/SonarOpenCommunity/sonar-cxx - * - * This program 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. - * - * This program 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.cxx.sensors.functioncomplexity; - -import static java.util.Arrays.asList; -import java.util.List; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.Metrics; - -public class FunctionComplexityMetrics implements Metrics { - - public static final Metric COMPLEX_FUNCTIONS = new Metric.Builder("complex_functions", "Complex Functions", Metric.ValueType.INT) - .setDescription("Number of functions with high cyclomatic complexity") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); - - public static final Metric PERC_COMPLEX_FUNCTIONS = new Metric.Builder("perc_complex_functions", "% of Complex Functions", Metric.ValueType.PERCENT) - .setDescription("% of functions with high cyclomatic complexity") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); - - public static final Metric LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("loc_in_complex_functions", "LoC in Complex Functions", Metric.ValueType.INT) - .setDescription("Number of lines of code in functions with high cyclomatic complexity") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); - - public static final Metric PERC_LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("perc_loc_in_complex_functions", "% of LoC in Complex Functions", Metric.ValueType.PERCENT) - .setDescription("% of lines of code in functions with high cyclomatic complexity") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); - - @Override - public List getMetrics() { - return asList(COMPLEX_FUNCTIONS, PERC_COMPLEX_FUNCTIONS, LOC_IN_COMPLEX_FUNCTIONS, PERC_LOC_IN_COMPLEX_FUNCTIONS); - } - -} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 58829090cf..f6da93dbf3 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -34,11 +34,11 @@ import org.sonar.cxx.CxxLanguage; import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine; import org.sonar.cxx.parser.CxxGrammarImpl; -import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.functioncomplexity.FunctionCount; import org.sonar.cxx.sensors.functioncomplexity.FunctionScore; import org.sonar.cxx.sensors.functioncomplexity.FunctionScoreComparator; import org.sonar.cxx.sensors.squid.SquidSensor; +import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -128,39 +128,32 @@ public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, Sen @Override public void publishMeasureForProject(InputModule module, SensorContext context) { - publishBigFunctionCountForProject(module, context); - publishLocInBigFunctionForProject(module, context); + } private void publishBigFunctionCountForProject(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS) .on(module) .withValue(functionsOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_PERC) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) .save(); } - private void publishLocInBigFunctionForProject(InputModule module, SensorContext context){ - context.newMeasure() - .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) - .on(module) - .withValue(locOverThreshold + locBelowThreshold) - .save(); - + private void publishLocInBigFunctionForProject(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC) .on(module) .withValue(locOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC) .on(module) .withValue(calculatePercentual(locOverThreshold, locBelowThreshold)) .save(); @@ -183,13 +176,13 @@ private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile } context.newMeasure() - .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS) .on(inputFile) .withValue((int)c.countOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_PERC) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); @@ -204,19 +197,19 @@ private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squi } context.newMeasure() - .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) + .forMetric(OpenCommunityMetrics.LOC_IN_FUNCTIONS) .on(inputFile) .withValue(c.countOverThreshold + c.countBelowThreshold) .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC) .on(inputFile) .withValue(c.countOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) + .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java deleted file mode 100644 index d9033e2b9b..0000000000 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity - * http://github.com/SonarOpenCommunity/sonar-cxx - * - * This program 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. - * - * This program 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.cxx.sensors.functionsize; - -import static java.util.Arrays.asList; -import java.util.List; -import org.sonar.api.measures.CoreMetrics; -import org.sonar.api.measures.Metric; -import org.sonar.api.measures.Metrics; - -public class FunctionSizeMetrics implements Metrics { - - public static final Metric BIG_FUNCTIONS = new Metric.Builder("big_functions", "Big Functions", Metric.ValueType.INT) - .setDescription("Number of functions with too many lines") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - - public static final Metric LOC_IN_BIG_FUNCTIONS = new Metric.Builder("loc_in_big_functions", "LoC in Big Functions", Metric.ValueType.INT) - .setDescription("Number of lines of code in functions with too many lines") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - - public static final Metric PERC_BIG_FUNCTIONS = new Metric.Builder("perc_big_functions", "% of Big Functions", Metric.ValueType.PERCENT) - .setDescription("% of functions with too many lines") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - - public static final Metric PERC_LOC_IN_BIG_FUNCTIONS = new Metric.Builder("perc_loc_in_big_functions", "% of LoC in Big Functions", Metric.ValueType.PERCENT) - .setDescription("% of lines of code in functions with too many lines") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - - public static final Metric LOC_IN_FUNCTIONS = new Metric.Builder("loc_in_functions", "LoC in Functions", Metric.ValueType.INT) - .setDescription("Number of lines of code in function bodies") - .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) - .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - - @Override - public List getMetrics() { - return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS, LOC_IN_BIG_FUNCTIONS, PERC_LOC_IN_BIG_FUNCTIONS, LOC_IN_FUNCTIONS); - } - -} 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 250b5fd705..bc62dee860 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 @@ -122,11 +122,9 @@ public CxxSquidSensor(CxxLanguage language, registerSquidSensors(); } - protected void registerSquidSensors(){ - if (this.language.getKey() == "c++"){ - this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); - this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); - } + protected void registerSquidSensors(){ + this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); + this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); } @Override diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index b3d27661f8..f7914bc762 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -46,6 +46,7 @@ import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.sensors.squid.CxxSquidSensor; import org.sonar.cxx.sensors.utils.TestUtils; +import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.api.SourceFile; public class CxxFunctionComplexitySquidSensorTest { @@ -113,33 +114,7 @@ private T getMeasureValue(SensorContextTester sensorCon value = (T) m.value(); } return value; - } - - @Test - public void testPublishMeasuresForProject() throws IOException { - DefaultInputFile inputFile = getInputFile(); - - CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); - } - - @Test - public void testPublishMeasuresForEmptyProject() throws IOException { - DefaultInputFile inputFile = getEmptyInputFile(); - - CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); - } + } @Test public void testPublishMeasuresForFile() throws IOException { @@ -148,10 +123,10 @@ public void testPublishMeasuresForFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); } @Test @@ -161,9 +136,9 @@ public void testPublishMeasuresForEmptyFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 7111629f04..312bf547b4 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -44,6 +44,7 @@ import org.sonar.cxx.CxxAstScanner; import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.sensors.utils.TestUtils; +import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.api.SourceFile; public class CxxFunctionSizeSquidSensorTest { @@ -107,35 +108,7 @@ private T getMeasureValue(SensorContextTester sensorCon value = (T) m.value(); } return value; - } - - @Test - public void testPublishMeasuresForProject() throws IOException { - DefaultInputFile inputFile = getInputFile(); - - CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); - } - - @Test - public void testPublishMeasuresForEmptyProject() throws IOException { - DefaultInputFile inputFile = getEmptyInputFile(); - - CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); - sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); - } + } @Test public void testPublishMeasuresForFile() throws IOException { @@ -144,11 +117,11 @@ public void testPublishMeasuresForFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); } @Test @@ -158,10 +131,10 @@ public void testPublishMeasuresForEmptyFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); } } 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 e96d775df1..62045799db 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 @@ -51,9 +51,7 @@ import org.sonar.cxx.sensors.drmemory.CxxDrMemoryRuleRepository; import org.sonar.cxx.sensors.drmemory.CxxDrMemorySensor; import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; -import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.functionsize.CxxFunctionSizeSquidSensor; -import org.sonar.cxx.sensors.functionsize.FunctionSizeMetrics; import org.sonar.cxx.sensors.other.CxxOtherRepository; import org.sonar.cxx.sensors.other.CxxOtherSensor; import org.sonar.cxx.sensors.pclint.CxxPCLintRuleRepository; @@ -518,10 +516,6 @@ public void define(Context context) { l.addAll(compilerWarningsProperties()); l.addAll(duplicationsProperties()); - //extra metrics - l.add(FunctionComplexityMetrics.class); - l.add(FunctionSizeMetrics.class); - context.addExtensions(l); } diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java index a709b75faa..b4b9b6fb1d 100644 --- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java +++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java @@ -35,6 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CxxPlugin plugin = new CxxPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(76); + assertThat(context.getExtensions()).hasSize(74); } } From c37398bdd93e414793134ec372a96df78ae5760e Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 8 Jun 2018 13:37:45 +0100 Subject: [PATCH 14/19] Revert "- Removing metric definitions from this project" This reverts commit 008fd89b655dfbc52f6137199d9d523a3a8d4033. --- cxx-sensors/pom.xml | 5 -- .../CxxFunctionComplexitySquidSensor.java | 20 +++--- .../FunctionComplexityMetrics.java | 63 ++++++++++++++++ .../CxxFunctionSizeSquidSensor.java | 31 ++++---- .../functionsize/FunctionSizeMetrics.java | 71 +++++++++++++++++++ .../cxx/sensors/squid/CxxSquidSensor.java | 8 ++- .../CxxFunctionComplexitySquidSensorTest.java | 45 +++++++++--- .../CxxFunctionSizeSquidSensorTest.java | 51 +++++++++---- .../java/org/sonar/plugins/cxx/CxxPlugin.java | 6 ++ .../org/sonar/plugins/cxx/CxxPluginTest.java | 2 +- 10 files changed, 249 insertions(+), 53 deletions(-) create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java diff --git a/cxx-sensors/pom.xml b/cxx-sensors/pom.xml index 6c944d53dc..b1f77ba7c3 100644 --- a/cxx-sensors/pom.xml +++ b/cxx-sensors/pom.xml @@ -101,10 +101,5 @@ assertj-core test - - org.sonar.opencommunity.metrics - sonar-opencommunity-metrics - 0.9.9 - diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index fbb3470fdf..e783f22e5a 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -39,7 +39,6 @@ import org.sonar.cxx.parser.CxxGrammarImpl; import static org.sonar.cxx.sensors.clangtidy.CxxClangTidySensor.REPORT_PATH_KEY; import org.sonar.cxx.sensors.squid.SquidSensor; -import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -139,13 +138,13 @@ private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFil } context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) .on(inputFile) .withValue((int)c.countOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC) + .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) .on(inputFile) .withValue(calculatePercentual((int)c.countOverThreshold, (int)c.countBelowThreshold)) .save(); @@ -161,13 +160,13 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour } context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC) + .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) .on(inputFile) .withValue(locCount.countOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) + .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) .on(inputFile) .withValue(calculatePercentual((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold)) .save(); @@ -175,18 +174,19 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour @Override public void publishMeasureForProject(InputModule module, SensorContext context) { - + publishComplexFunctionMetrics(module, context); + publishLinesOfCodeInComplexFunctionMetrics(module, context); } private void publishComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) .on(module) .withValue(functionsOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC) + .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) .save(); @@ -194,13 +194,13 @@ private void publishComplexFunctionMetrics(InputModule module, SensorContext con private void publishLinesOfCodeInComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC) + .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) .on(module) .withValue(linesOfCodeOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) + .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) .on(module) .withValue(calculatePercentual(linesOfCodeOverThreshold, linesOfCodeBelowThreshold)) .save(); diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java new file mode 100644 index 0000000000..5425c8c98a --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -0,0 +1,63 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functioncomplexity; + +import static java.util.Arrays.asList; +import java.util.List; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.Metrics; + +public class FunctionComplexityMetrics implements Metrics { + + public static final Metric COMPLEX_FUNCTIONS = new Metric.Builder("complex_functions", "Complex Functions", Metric.ValueType.INT) + .setDescription("Number of functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); + + public static final Metric PERC_COMPLEX_FUNCTIONS = new Metric.Builder("perc_complex_functions", "% of Complex Functions", Metric.ValueType.PERCENT) + .setDescription("% of functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); + + public static final Metric LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("loc_in_complex_functions", "LoC in Complex Functions", Metric.ValueType.INT) + .setDescription("Number of lines of code in functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); + + public static final Metric PERC_LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("perc_loc_in_complex_functions", "% of LoC in Complex Functions", Metric.ValueType.PERCENT) + .setDescription("% of lines of code in functions with high cyclomatic complexity") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) + .create(); + + @Override + public List getMetrics() { + return asList(COMPLEX_FUNCTIONS, PERC_COMPLEX_FUNCTIONS, LOC_IN_COMPLEX_FUNCTIONS, PERC_LOC_IN_COMPLEX_FUNCTIONS); + } + +} diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index f6da93dbf3..58829090cf 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -34,11 +34,11 @@ import org.sonar.cxx.CxxLanguage; import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine; import org.sonar.cxx.parser.CxxGrammarImpl; +import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.functioncomplexity.FunctionCount; import org.sonar.cxx.sensors.functioncomplexity.FunctionScore; import org.sonar.cxx.sensors.functioncomplexity.FunctionScoreComparator; import org.sonar.cxx.sensors.squid.SquidSensor; -import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; import org.sonar.squidbridge.api.SourceFunction; @@ -128,32 +128,39 @@ public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, Sen @Override public void publishMeasureForProject(InputModule module, SensorContext context) { - + publishBigFunctionCountForProject(module, context); + publishLocInBigFunctionForProject(module, context); } private void publishBigFunctionCountForProject(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) .on(module) .withValue(functionsOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_PERC) + .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) .save(); } - private void publishLocInBigFunctionForProject(InputModule module, SensorContext context){ + private void publishLocInBigFunctionForProject(InputModule module, SensorContext context){ + context.newMeasure() + .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) + .on(module) + .withValue(locOverThreshold + locBelowThreshold) + .save(); + context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC) + .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) .on(module) .withValue(locOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC) + .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) .on(module) .withValue(calculatePercentual(locOverThreshold, locBelowThreshold)) .save(); @@ -176,13 +183,13 @@ private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile } context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) .on(inputFile) .withValue((int)c.countOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_PERC) + .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); @@ -197,19 +204,19 @@ private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squi } context.newMeasure() - .forMetric(OpenCommunityMetrics.LOC_IN_FUNCTIONS) + .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) .on(inputFile) .withValue(c.countOverThreshold + c.countBelowThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC) + .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) .on(inputFile) .withValue(c.countOverThreshold) .save(); context.newMeasure() - .forMetric(OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC) + .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java new file mode 100644 index 0000000000..d9033e2b9b --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java @@ -0,0 +1,71 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2017 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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.cxx.sensors.functionsize; + +import static java.util.Arrays.asList; +import java.util.List; +import org.sonar.api.measures.CoreMetrics; +import org.sonar.api.measures.Metric; +import org.sonar.api.measures.Metrics; + +public class FunctionSizeMetrics implements Metrics { + + public static final Metric BIG_FUNCTIONS = new Metric.Builder("big_functions", "Big Functions", Metric.ValueType.INT) + .setDescription("Number of functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + + public static final Metric LOC_IN_BIG_FUNCTIONS = new Metric.Builder("loc_in_big_functions", "LoC in Big Functions", Metric.ValueType.INT) + .setDescription("Number of lines of code in functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + + public static final Metric PERC_BIG_FUNCTIONS = new Metric.Builder("perc_big_functions", "% of Big Functions", Metric.ValueType.PERCENT) + .setDescription("% of functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + + public static final Metric PERC_LOC_IN_BIG_FUNCTIONS = new Metric.Builder("perc_loc_in_big_functions", "% of LoC in Big Functions", Metric.ValueType.PERCENT) + .setDescription("% of lines of code in functions with too many lines") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + + public static final Metric LOC_IN_FUNCTIONS = new Metric.Builder("loc_in_functions", "LoC in Functions", Metric.ValueType.INT) + .setDescription("Number of lines of code in function bodies") + .setDirection(Metric.DIRECTION_WORST) + .setQualitative(false) + .setDomain(CoreMetrics.DOMAIN_SIZE) + .create(); + + @Override + public List getMetrics() { + return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS, LOC_IN_BIG_FUNCTIONS, PERC_LOC_IN_BIG_FUNCTIONS, LOC_IN_FUNCTIONS); + } + +} 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 bc62dee860..250b5fd705 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 @@ -122,9 +122,11 @@ public CxxSquidSensor(CxxLanguage language, registerSquidSensors(); } - protected void registerSquidSensors(){ - this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); - this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); + protected void registerSquidSensors(){ + if (this.language.getKey() == "c++"){ + this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); + this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); + } } @Override diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index f7914bc762..b3d27661f8 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -46,7 +46,6 @@ import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.sensors.squid.CxxSquidSensor; import org.sonar.cxx.sensors.utils.TestUtils; -import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.api.SourceFile; public class CxxFunctionComplexitySquidSensorTest { @@ -114,7 +113,33 @@ private T getMeasureValue(SensorContextTester sensorCon value = (T) m.value(); } return value; - } + } + + @Test + public void testPublishMeasuresForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); + } + + @Test + public void testPublishMeasuresForEmptyProject() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + } @Test public void testPublishMeasuresForFile() throws IOException { @@ -123,10 +148,10 @@ public void testPublishMeasuresForFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); } @Test @@ -136,9 +161,9 @@ public void testPublishMeasuresForEmptyFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 312bf547b4..7111629f04 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -44,7 +44,6 @@ import org.sonar.cxx.CxxAstScanner; import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.sensors.utils.TestUtils; -import org.sonar.opencommunity.metrics.OpenCommunityMetrics; import org.sonar.squidbridge.api.SourceFile; public class CxxFunctionSizeSquidSensorTest { @@ -108,7 +107,35 @@ private T getMeasureValue(SensorContextTester sensorCon value = (T) m.value(); } return value; - } + } + + @Test + public void testPublishMeasuresForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); + } + + @Test + public void testPublishMeasuresForEmptyProject() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); + sensor.publishMeasureForProject(sensorContext.module(), sensorContext); + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + } @Test public void testPublishMeasuresForFile() throws IOException { @@ -117,11 +144,11 @@ public void testPublishMeasuresForFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); } @Test @@ -131,10 +158,10 @@ public void testPublishMeasuresForEmptyFile() throws IOException { SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), OpenCommunityMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); } } 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 62045799db..e96d775df1 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 @@ -51,7 +51,9 @@ import org.sonar.cxx.sensors.drmemory.CxxDrMemoryRuleRepository; import org.sonar.cxx.sensors.drmemory.CxxDrMemorySensor; import org.sonar.cxx.sensors.functioncomplexity.CxxFunctionComplexitySquidSensor; +import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.functionsize.CxxFunctionSizeSquidSensor; +import org.sonar.cxx.sensors.functionsize.FunctionSizeMetrics; import org.sonar.cxx.sensors.other.CxxOtherRepository; import org.sonar.cxx.sensors.other.CxxOtherSensor; import org.sonar.cxx.sensors.pclint.CxxPCLintRuleRepository; @@ -516,6 +518,10 @@ public void define(Context context) { l.addAll(compilerWarningsProperties()); l.addAll(duplicationsProperties()); + //extra metrics + l.add(FunctionComplexityMetrics.class); + l.add(FunctionSizeMetrics.class); + context.addExtensions(l); } diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java index b4b9b6fb1d..a709b75faa 100644 --- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java +++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java @@ -35,6 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CxxPlugin plugin = new CxxPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(74); + assertThat(context.getExtensions()).hasSize(76); } } From 2f729f27da2a205cffc96cfd55f7fc19b9be1d31 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 8 Jun 2018 14:07:41 +0100 Subject: [PATCH 15/19] Fixing license header and tests after rebase. --- .../functioncomplexity/CxxFunctionComplexitySquidSensor.java | 2 +- .../sensors/functioncomplexity/FunctionComplexityMetrics.java | 2 +- .../sonar/cxx/sensors/functioncomplexity/FunctionCount.java | 2 +- .../sonar/cxx/sensors/functioncomplexity/FunctionScore.java | 2 +- .../sensors/functioncomplexity/FunctionScoreComparator.java | 2 +- .../cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java | 2 +- .../sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java | 2 +- .../main/java/org/sonar/cxx/sensors/squid/SquidSensor.java | 2 +- .../CxxFunctionComplexitySquidSensorTest.java | 2 +- .../sensors/functionsize/CxxFunctionSizeSquidSensorTest.java | 2 +- .../src/test/java/org/sonar/plugins/c/CPluginTest.java | 4 ++-- .../src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java | 4 ++-- 12 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index e783f22e5a..3f1766d996 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java index 5425c8c98a..e97359b996 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java index d085446577..1005b56682 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java index 2aa596ec18..8a95e9e557 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java index e50341daa1..1bb63038f5 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 58829090cf..cc09c1b8ae 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java index d9033e2b9b..8df8354111 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java index 5418fa5e2f..9ec255c243 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/squid/SquidSensor.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index b3d27661f8..d8735865bd 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 7111629f04..df940cd3c9 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or diff --git a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java index 6549e09140..9933913597 100644 --- a/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java +++ b/sonar-c-plugin/src/test/java/org/sonar/plugins/c/CPluginTest.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or @@ -35,6 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CPlugin plugin = new CPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(68); + assertThat(context.getExtensions()).hasSize(67); } } diff --git a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java index a709b75faa..95cb8553e4 100644 --- a/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java +++ b/sonar-cxx-plugin/src/test/java/org/sonar/plugins/cxx/CxxPluginTest.java @@ -1,6 +1,6 @@ /* * Sonar C++ Plugin (Community) - * Copyright (C) 2010-2017 SonarOpenCommunity + * Copyright (C) 2010-2018 SonarOpenCommunity * http://github.com/SonarOpenCommunity/sonar-cxx * * This program is free software; you can redistribute it and/or @@ -35,6 +35,6 @@ public void testGetExtensions() throws Exception { Plugin.Context context = new Plugin.Context(runtime); CxxPlugin plugin = new CxxPlugin(); plugin.define(context); - assertThat(context.getExtensions()).hasSize(76); + assertThat(context.getExtensions()).hasSize(75); } } From 5e13013f0f615b3f4d62187cbfac68955c7fb850 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 8 Jun 2018 14:35:37 +0100 Subject: [PATCH 16/19] Fixing a lot of minor requests on the Code Review. --- .../CxxFunctionComplexitySquidSensor.java | 10 ++----- .../functioncomplexity/package-info.java | 27 +++++++++++++++++++ .../CxxFunctionSizeSquidSensor.java | 10 ++----- .../sensors/functionsize/package-info.java | 27 +++++++++++++++++++ .../cxx/sensors/squid/CxxSquidSensor.java | 4 +-- .../CxxFunctionComplexitySquidSensorTest.java | 6 ----- .../CxxFunctionSizeSquidSensorTest.java | 1 - .../plugins/cxx/squid/CxxSquidSensorTest.java | 1 - .../main/java/org/sonar/cxx/CxxLanguage.java | 2 +- .../java/org/sonar/plugins/cxx/CxxPlugin.java | 2 +- 10 files changed, 62 insertions(+), 28 deletions(-) create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/package-info.java create mode 100644 cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index 3f1766d996..eb3af8d302 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -21,23 +21,16 @@ import com.sonar.sslr.api.AstNode; import com.sonar.sslr.api.Grammar; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.OutputStream; import java.util.Hashtable; -import java.util.SortedSet; -import java.util.TreeSet; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.sensor.SensorContext; -import org.sonar.api.config.Configuration; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; import org.sonar.cxx.CxxLanguage; import org.sonar.cxx.api.CxxMetric; import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine; import org.sonar.cxx.parser.CxxGrammarImpl; -import static org.sonar.cxx.sensors.clangtidy.CxxClangTidySensor.REPORT_PATH_KEY; import org.sonar.cxx.sensors.squid.SquidSensor; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; @@ -68,7 +61,8 @@ public class CxxFunctionComplexitySquidSensor extends SquidAstVisitor i public CxxFunctionComplexitySquidSensor(CxxLanguage language){ this.cyclomaticComplexityThreshold = language.getIntegerOption(FUNCTION_COMPLEXITY_THRESHOLD_KEY).orElse(10); - LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); + if (LOG.isDebugEnabled()) + LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); } @Override diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/package-info.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/package-info.java new file mode 100644 index 0000000000..a18698c8e1 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/package-info.java @@ -0,0 +1,27 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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 with sensor to get function complexity metrics + */ +@ParametersAreNonnullByDefault +package org.sonar.cxx.sensors.functioncomplexity; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index cc09c1b8ae..75df7da199 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -21,11 +21,7 @@ import com.sonar.sslr.api.AstNode; import com.sonar.sslr.api.Grammar; -import java.io.IOException; -import java.io.OutputStream; import java.util.Hashtable; -import java.util.SortedSet; -import java.util.TreeSet; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.InputModule; import org.sonar.api.batch.sensor.SensorContext; @@ -34,10 +30,7 @@ import org.sonar.cxx.CxxLanguage; import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine; import org.sonar.cxx.parser.CxxGrammarImpl; -import org.sonar.cxx.sensors.functioncomplexity.FunctionComplexityMetrics; import org.sonar.cxx.sensors.functioncomplexity.FunctionCount; -import org.sonar.cxx.sensors.functioncomplexity.FunctionScore; -import org.sonar.cxx.sensors.functioncomplexity.FunctionScoreComparator; import org.sonar.cxx.sensors.squid.SquidSensor; import org.sonar.squidbridge.SquidAstVisitor; import org.sonar.squidbridge.api.SourceFile; @@ -65,7 +58,8 @@ public class CxxFunctionSizeSquidSensor extends SquidAstVisitor impleme public CxxFunctionSizeSquidSensor(CxxLanguage language){ this.sizeThreshold = language.getIntegerOption(FUNCTION_SIZE_THRESHOLD_KEY).orElse(20); - LOG.debug("Function size threshold: " + this.sizeThreshold); + if (LOG.isDebugEnabled()) + LOG.debug("Function size threshold: " + this.sizeThreshold); } @Override diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java new file mode 100644 index 0000000000..8da1a429e1 --- /dev/null +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java @@ -0,0 +1,27 @@ +/* + * Sonar C++ Plugin (Community) + * Copyright (C) 2010-2018 SonarOpenCommunity + * http://github.com/SonarOpenCommunity/sonar-cxx + * + * This program 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. + * + * This program 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 with sensor to evaluate Dr Memrory specific results files. + */ +@ParametersAreNonnullByDefault +package org.sonar.cxx.sensors.functionsize; + +import javax.annotation.ParametersAreNonnullByDefault; 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 250b5fd705..e3aaf3bc09 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 @@ -122,8 +122,8 @@ public CxxSquidSensor(CxxLanguage language, registerSquidSensors(); } - protected void registerSquidSensors(){ - if (this.language.getKey() == "c++"){ + protected void registerSquidSensors(){ + if (this.language.getKey() == "c++"){ this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index d8735865bd..02a1fca41e 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -19,7 +19,6 @@ */ package org.sonar.cxx.sensors.functioncomplexity; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.Serializable; @@ -34,17 +33,12 @@ import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.batch.fs.internal.TestInputFileBuilder; import org.sonar.api.batch.measure.Metric; -import org.sonar.api.batch.rule.ActiveRules; -import org.sonar.api.batch.rule.CheckFactory; -import org.sonar.api.batch.sensor.SensorContext; import org.sonar.api.batch.sensor.internal.SensorContextTester; import org.sonar.api.batch.sensor.measure.Measure; -import org.sonar.api.config.Configuration; import org.sonar.api.measures.FileLinesContext; import org.sonar.api.measures.FileLinesContextFactory; import org.sonar.cxx.CxxAstScanner; import org.sonar.cxx.CxxLanguage; -import org.sonar.cxx.sensors.squid.CxxSquidSensor; import org.sonar.cxx.sensors.utils.TestUtils; import org.sonar.squidbridge.api.SourceFile; diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index df940cd3c9..6ea0c3b612 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -19,7 +19,6 @@ */ package org.sonar.cxx.sensors.functionsize; -import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.Serializable; 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 715c57ab67..dc5e677dba 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 @@ -19,7 +19,6 @@ */ package org.sonar.plugins.cxx.squid; -import com.sonar.sslr.api.AstVisitor; import com.sonar.sslr.api.Grammar; import java.io.File; import java.io.IOException; diff --git a/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java b/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java index 34ccb0d865..4c6c71bd6b 100644 --- a/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java +++ b/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java @@ -43,7 +43,7 @@ public abstract class CxxLanguage extends AbstractLanguage { public CxxLanguage(String key, Configuration settings) { super(key); this.settings = settings; - this.MetricsCache = new HashMap<>(); + this.MetricsCache = new HashMap<>(); } public CxxLanguage(String key, String name, Configuration settings) { 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 e96d775df1..0ff990fc0b 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 @@ -92,7 +92,7 @@ public final class CxxPlugin implements Plugin { public static final String MISSING_INCLUDE_WARN = LANG_PROP_PREFIX + "missingIncludeWarnings"; public static final String JSON_COMPILATION_DATABASE_KEY = LANG_PROP_PREFIX + "jsonCompilationDatabase"; public static final String CPD_IGNORE_LITERALS_KEY = LANG_PROP_PREFIX + "cpd.ignoreLiterals"; - public static final String CPD_IGNORE_IDENTIFIERS_KEY = LANG_PROP_PREFIX + "cpd.ignoreIdentifiers"; + public static final String CPD_IGNORE_IDENTIFIERS_KEY = LANG_PROP_PREFIX + "cpd.ignoreIdentifiers"; private static List generalProperties() { String subcateg = "(1) General"; From 42d62d319b9549fbede62bc8420e2a01d23c85b8 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 8 Jun 2018 14:38:16 +0100 Subject: [PATCH 17/19] Fixing package-info description --- .../java/org/sonar/cxx/sensors/functionsize/package-info.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java index 8da1a429e1..8e5b24a56c 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/package-info.java @@ -19,7 +19,7 @@ */ /** - * Package with sensor to evaluate Dr Memrory specific results files. + * Package with sensor to get function size metrics */ @ParametersAreNonnullByDefault package org.sonar.cxx.sensors.functionsize; From 3cfc07e5e401047b3a7caf83c5229dd5264db379 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Fri, 8 Jun 2018 15:21:36 +0100 Subject: [PATCH 18/19] Renaming metrics as suggested in the PR review. --- .../CxxFunctionComplexitySquidSensor.java | 12 +++++----- .../FunctionComplexityMetrics.java | 18 +++++++------- .../CxxFunctionSizeSquidSensor.java | 12 +++++----- .../functionsize/FunctionSizeMetrics.java | 22 ++++++++--------- .../CxxFunctionComplexitySquidSensorTest.java | 24 +++++++++---------- .../CxxFunctionSizeSquidSensorTest.java | 24 +++++++++---------- 6 files changed, 56 insertions(+), 56 deletions(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index eb3af8d302..0ef8d51399 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -138,7 +138,7 @@ private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFil .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC) .on(inputFile) .withValue(calculatePercentual((int)c.countOverThreshold, (int)c.countBelowThreshold)) .save(); @@ -154,13 +154,13 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour } context.newMeasure() - .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC) .on(inputFile) .withValue(locCount.countOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) .on(inputFile) .withValue(calculatePercentual((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold)) .save(); @@ -180,7 +180,7 @@ private void publishComplexFunctionMetrics(InputModule module, SensorContext con .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) .save(); @@ -188,13 +188,13 @@ private void publishComplexFunctionMetrics(InputModule module, SensorContext con private void publishLinesOfCodeInComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() - .forMetric(FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC) .on(module) .withValue(linesOfCodeOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS) + .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) .on(module) .withValue(calculatePercentual(linesOfCodeOverThreshold, linesOfCodeBelowThreshold)) .save(); diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java index e97359b996..03affeafcf 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -30,34 +30,34 @@ public class FunctionComplexityMetrics implements Metrics { public static final Metric COMPLEX_FUNCTIONS = new Metric.Builder("complex_functions", "Complex Functions", Metric.ValueType.INT) .setDescription("Number of functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) .create(); - public static final Metric PERC_COMPLEX_FUNCTIONS = new Metric.Builder("perc_complex_functions", "% of Complex Functions", Metric.ValueType.PERCENT) + public static final Metric COMPLEX_FUNCTIONS_PERC = new Metric.Builder("perc_complex_functions", "Complex Functions (%)", Metric.ValueType.PERCENT) .setDescription("% of functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) .create(); - public static final Metric LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("loc_in_complex_functions", "LoC in Complex Functions", Metric.ValueType.INT) + public static final Metric COMPLEX_FUNCTIONS_LOC = new Metric.Builder("loc_in_complex_functions", "Complex Functions Lines of Code", Metric.ValueType.INT) .setDescription("Number of lines of code in functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) .create(); - public static final Metric PERC_LOC_IN_COMPLEX_FUNCTIONS = new Metric.Builder("perc_loc_in_complex_functions", "% of LoC in Complex Functions", Metric.ValueType.PERCENT) + public static final Metric COMPLEX_FUNCTIONS_LOC_PERC = new Metric.Builder("perc_loc_in_complex_functions", "Complex Functions Lines of Code (%)", Metric.ValueType.PERCENT) .setDescription("% of lines of code in functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); + .create(); @Override public List getMetrics() { - return asList(COMPLEX_FUNCTIONS, PERC_COMPLEX_FUNCTIONS, LOC_IN_COMPLEX_FUNCTIONS, PERC_LOC_IN_COMPLEX_FUNCTIONS); + return asList(COMPLEX_FUNCTIONS, COMPLEX_FUNCTIONS_PERC, COMPLEX_FUNCTIONS_LOC, COMPLEX_FUNCTIONS_LOC_PERC); } } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 75df7da199..2f308672a7 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -134,7 +134,7 @@ private void publishBigFunctionCountForProject(InputModule module, SensorContext .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_PERC) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) .save(); @@ -148,13 +148,13 @@ private void publishLocInBigFunctionForProject(InputModule module, SensorContext .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC) .on(module) .withValue(locOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC) .on(module) .withValue(calculatePercentual(locOverThreshold, locBelowThreshold)) .save(); @@ -183,7 +183,7 @@ private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_PERC) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); @@ -204,13 +204,13 @@ private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squi .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC) .on(inputFile) .withValue(c.countOverThreshold) .save(); context.newMeasure() - .forMetric(FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS) + .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) .save(); diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java index 8df8354111..fe1d26eb8d 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java @@ -31,41 +31,41 @@ public class FunctionSizeMetrics implements Metrics { public static final Metric BIG_FUNCTIONS = new Metric.Builder("big_functions", "Big Functions", Metric.ValueType.INT) .setDescription("Number of functions with too many lines") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); - public static final Metric LOC_IN_BIG_FUNCTIONS = new Metric.Builder("loc_in_big_functions", "LoC in Big Functions", Metric.ValueType.INT) + public static final Metric BIG_FUNCTIONS_LOC = new Metric.Builder("loc_in_big_functions", "Big Functions Lines of Code", Metric.ValueType.INT) .setDescription("Number of lines of code in functions with too many lines") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); - public static final Metric PERC_BIG_FUNCTIONS = new Metric.Builder("perc_big_functions", "% of Big Functions", Metric.ValueType.PERCENT) + public static final Metric BIG_FUNCTIONS_PERC = new Metric.Builder("perc_big_functions", "Big Functions (%)", Metric.ValueType.PERCENT) .setDescription("% of functions with too many lines") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); - public static final Metric PERC_LOC_IN_BIG_FUNCTIONS = new Metric.Builder("perc_loc_in_big_functions", "% of LoC in Big Functions", Metric.ValueType.PERCENT) + public static final Metric BIG_FUNCTIONS_LOC_PERC = new Metric.Builder("perc_loc_in_big_functions", "Big Functions Lines of Code (%)", Metric.ValueType.PERCENT) .setDescription("% of lines of code in functions with too many lines") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); - public static final Metric LOC_IN_FUNCTIONS = new Metric.Builder("loc_in_functions", "LoC in Functions", Metric.ValueType.INT) + public static final Metric LOC_IN_FUNCTIONS = new Metric.Builder("loc_in_functions", "Lines of Code in Functions", Metric.ValueType.INT) .setDescription("Number of lines of code in function bodies") .setDirection(Metric.DIRECTION_WORST) - .setQualitative(false) + .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); + .create(); @Override public List getMetrics() { - return asList(BIG_FUNCTIONS, PERC_BIG_FUNCTIONS, LOC_IN_BIG_FUNCTIONS, PERC_LOC_IN_BIG_FUNCTIONS, LOC_IN_FUNCTIONS); + return asList(BIG_FUNCTIONS, BIG_FUNCTIONS_PERC, BIG_FUNCTIONS_LOC, BIG_FUNCTIONS_LOC_PERC, LOC_IN_FUNCTIONS); } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index 02a1fca41e..bd611991d7 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -117,9 +117,9 @@ public void testPublishMeasuresForProject() throws IOException { sensor.publishMeasureForProject(sensorContext.module(), sensorContext); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); } @Test @@ -130,9 +130,9 @@ public void testPublishMeasuresForEmptyProject() throws IOException { sensor.publishMeasureForProject(sensorContext.module(), sensorContext); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); } @Test @@ -143,9 +143,9 @@ public void testPublishMeasuresForFile() throws IOException { sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); } @Test @@ -156,8 +156,8 @@ public void testPublishMeasuresForEmptyFile() throws IOException { sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.PERC_LOC_IN_COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index 6ea0c3b612..d6b0bfa3f3 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -117,9 +117,9 @@ public void testPublishMeasuresForProject() throws IOException { assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); } @Test @@ -131,9 +131,9 @@ public void testPublishMeasuresForEmptyProject() throws IOException { assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); } @Test @@ -145,9 +145,9 @@ public void testPublishMeasuresForFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(80); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); } @Test @@ -159,8 +159,8 @@ public void testPublishMeasuresForEmptyFile() throws IOException { assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.PERC_LOC_IN_BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); } } From 68d6fd747228ea54deb2997208a7f0f1531f6d46 Mon Sep 17 00:00:00 2001 From: Eric Lemes Date: Mon, 11 Jun 2018 10:59:42 +0100 Subject: [PATCH 19/19] Style changes. --- .../CxxFunctionComplexitySquidSensor.java | 121 +++++++++-------- .../FunctionComplexityMetrics.java | 16 +-- .../functioncomplexity/FunctionCount.java | 2 +- .../functioncomplexity/FunctionScore.java | 4 +- .../FunctionScoreComparator.java | 11 +- .../CxxFunctionSizeSquidSensor.java | 105 ++++++++------- .../functionsize/FunctionSizeMetrics.java | 20 +-- .../cxx/sensors/squid/CxxSquidSensor.java | 18 +-- .../CxxFunctionComplexitySquidSensorTest.java | 113 ++++++++-------- .../CxxFunctionSizeSquidSensorTest.java | 125 +++++++++--------- .../plugins/cxx/squid/CxxSquidSensorTest.java | 26 ++-- .../main/java/org/sonar/cxx/CxxLanguage.java | 4 +- .../java/org/sonar/plugins/cxx/CxxPlugin.java | 8 +- 13 files changed, 294 insertions(+), 279 deletions(-) diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java index 0ef8d51399..a2a5278b34 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java @@ -38,73 +38,76 @@ import org.sonar.squidbridge.checks.ChecksHelper; public class CxxFunctionComplexitySquidSensor extends SquidAstVisitor implements SquidSensor { - + private static final Logger LOG = Loggers.get(CxxFunctionComplexitySquidSensor.class); - - public static final String FUNCTION_COMPLEXITY_THRESHOLD_KEY = "funccomplexity.threshold"; - + + public static final String FUNCTION_COMPLEXITY_THRESHOLD_KEY = "funccomplexity.threshold"; + private int cyclomaticComplexityThreshold; - + private int functionsBelowThreshold; - + private int functionsOverThreshold; - + private int linesOfCodeBelowThreshold; private int linesOfCodeOverThreshold; - - private Hashtable complexFunctionsPerFile = new Hashtable<>(); - - private Hashtable locInComplexFunctionsPerFile = new Hashtable<>(); - - private String fileName; - - public CxxFunctionComplexitySquidSensor(CxxLanguage language){ + + private Hashtable complexFunctionsPerFile = new Hashtable<>(); + + private Hashtable locInComplexFunctionsPerFile = new Hashtable<>(); + + private String fileName; + + public CxxFunctionComplexitySquidSensor(CxxLanguage language){ this.cyclomaticComplexityThreshold = language.getIntegerOption(FUNCTION_COMPLEXITY_THRESHOLD_KEY).orElse(10); - if (LOG.isDebugEnabled()) - LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); - } + if (LOG.isDebugEnabled()) { + LOG.debug("Cyclomatic complexity threshold: " + this.cyclomaticComplexityThreshold); + } + } @Override public SquidAstVisitor getVisitor() { return this; } - + @Override public void init() { subscribeTo(CxxGrammarImpl.functionDefinition); - } - + } + @Override - public void leaveNode(AstNode node) { + public void leaveNode(AstNode node) { SourceFunction sourceFunction = (SourceFunction) getContext().peekSourceCode(); SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class); - int complexity = ChecksHelper.getRecursiveMeasureInt(sourceFunction, CxxMetric.COMPLEXITY); + int complexity = ChecksHelper.getRecursiveMeasureInt(sourceFunction, CxxMetric.COMPLEXITY); int lineCount = getNumberOfLine(node); - incrementFunctionByThresholdForAllFiles(complexity, lineCount); - incrementFunctionByThresholdForFile(sourceFile, complexity, lineCount); - } - + incrementFunctionByThresholdForAllFiles(complexity, lineCount); + incrementFunctionByThresholdForFile(sourceFile, complexity, lineCount); + } + private void incrementFunctionByThresholdForAllFiles(int complexity, int lineCount){ if (complexity > this.cyclomaticComplexityThreshold){ this.functionsOverThreshold++; this.linesOfCodeOverThreshold += lineCount; } else { - this.functionsBelowThreshold++; + this.functionsBelowThreshold++; this.linesOfCodeBelowThreshold += lineCount; } - } - + } + private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int complexity, int loc){ - if (!complexFunctionsPerFile.containsKey(sourceFile)) + if (!complexFunctionsPerFile.containsKey(sourceFile)) { complexFunctionsPerFile.put(sourceFile, new FunctionCount()); - - if (!locInComplexFunctionsPerFile.containsKey(sourceFile)) - locInComplexFunctionsPerFile.put(sourceFile, new FunctionCount()); - + } + + if (!locInComplexFunctionsPerFile.containsKey(sourceFile)) { + locInComplexFunctionsPerFile.put(sourceFile, new FunctionCount()); + } + FunctionCount functionCount = complexFunctionsPerFile.get(sourceFile); FunctionCount locCount = locInComplexFunctionsPerFile.get(sourceFile); if (complexity > this.cyclomaticComplexityThreshold){ @@ -112,7 +115,7 @@ private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int comp locCount.countOverThreshold += loc; } else { - functionCount.countBelowThreshold++; + functionCount.countBelowThreshold++; locCount.countBelowThreshold += loc; } } @@ -122,90 +125,92 @@ public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, Sen publishComplexFunctionMetricsForFile(inputFile, squidFile, context); publishLocInComplexFunctionMetricsForFile(inputFile, squidFile, context); } - + private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFile squidFile, SensorContext context){ FunctionCount c = complexFunctionsPerFile.get(squidFile); if (c == null){ c = new FunctionCount(); c.countBelowThreshold = 0; c.countOverThreshold = 0; - } - + } + context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) .on(inputFile) .withValue((int)c.countOverThreshold) - .save(); + .save(); context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC) .on(inputFile) .withValue(calculatePercentual((int)c.countOverThreshold, (int)c.countBelowThreshold)) - .save(); + .save(); } - + private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, SourceFile squidFile, SensorContext context){ FunctionCount locCount = locInComplexFunctionsPerFile.get(squidFile); - + if (locCount == null){ locCount = new FunctionCount(); locCount.countBelowThreshold = 0; locCount.countOverThreshold = 0; } - + context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC) .on(inputFile) .withValue(locCount.countOverThreshold) .save(); - + context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) .on(inputFile) .withValue(calculatePercentual((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold)) - .save(); + .save(); } @Override public void publishMeasureForProject(InputModule module, SensorContext context) { - publishComplexFunctionMetrics(module, context); - publishLinesOfCodeInComplexFunctionMetrics(module, context); + publishComplexFunctionMetrics(module, context); + publishLinesOfCodeInComplexFunctionMetrics(module, context); } - + private void publishComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS) .on(module) .withValue(functionsOverThreshold) .save(); - + context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) - .save(); + .save(); } - + private void publishLinesOfCodeInComplexFunctionMetrics(InputModule module, SensorContext context){ context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC) .on(module) .withValue(linesOfCodeOverThreshold) .save(); - + context.newMeasure() .forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC) .on(module) .withValue(calculatePercentual(linesOfCodeOverThreshold, linesOfCodeBelowThreshold)) - .save(); + .save(); } - + private double calculatePercentual(int overThreshold, int belowThreshold){ double total = (double)overThreshold + (double)belowThreshold; - if (total > 0) + if (total > 0) { return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); - else + } + else { return 0; + } } - + } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java index 03affeafcf..1af73a714f 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionComplexityMetrics.java @@ -26,38 +26,38 @@ import org.sonar.api.measures.Metrics; public class FunctionComplexityMetrics implements Metrics { - + public static final Metric COMPLEX_FUNCTIONS = new Metric.Builder("complex_functions", "Complex Functions", Metric.ValueType.INT) .setDescription("Number of functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) .create(); - + public static final Metric COMPLEX_FUNCTIONS_PERC = new Metric.Builder("perc_complex_functions", "Complex Functions (%)", Metric.ValueType.PERCENT) .setDescription("% of functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); - + .create(); + public static final Metric COMPLEX_FUNCTIONS_LOC = new Metric.Builder("loc_in_complex_functions", "Complex Functions Lines of Code", Metric.ValueType.INT) .setDescription("Number of lines of code in functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); - + .create(); + public static final Metric COMPLEX_FUNCTIONS_LOC_PERC = new Metric.Builder("perc_loc_in_complex_functions", "Complex Functions Lines of Code (%)", Metric.ValueType.PERCENT) .setDescription("% of lines of code in functions with high cyclomatic complexity") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_COMPLEXITY) - .create(); + .create(); @Override public List getMetrics() { return asList(COMPLEX_FUNCTIONS, COMPLEX_FUNCTIONS_PERC, COMPLEX_FUNCTIONS_LOC, COMPLEX_FUNCTIONS_LOC_PERC); } - + } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java index 1005b56682..ab912c0bb3 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionCount.java @@ -21,6 +21,6 @@ public class FunctionCount { public int countOverThreshold; - + public int countBelowThreshold; } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java index 8a95e9e557..a827486c57 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScore.java @@ -28,7 +28,7 @@ public int getScore(){ public void setScore(int value){ this.score = value; - } + } private String componentName; @@ -52,7 +52,7 @@ public void setFunctionId(String value){ public FunctionScore(){ - } + } public FunctionScore(int score, String componentName, String functionId){ this.score = score; diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java index 1bb63038f5..d5404b1178 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/FunctionScoreComparator.java @@ -26,12 +26,15 @@ public class FunctionScoreComparator implements Comparator{ @Override public int compare(FunctionScore o1, FunctionScore o2) { - if (o1 == o2) + if (o1 == o2) { return 0; - else if (o1.getScore() > o2.getScore()) + } + else if (o1.getScore() > o2.getScore()) { return -1; - else + } + else { return 1; + } } - + } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java index 2f308672a7..c9659c07e6 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java @@ -37,31 +37,32 @@ import org.sonar.squidbridge.api.SourceFunction; public class CxxFunctionSizeSquidSensor extends SquidAstVisitor implements SquidSensor { - + private static final Logger LOG = Loggers.get(CxxFunctionSizeSquidSensor.class); - - public static final String FUNCTION_SIZE_THRESHOLD_KEY = "funcsize.threshold"; - + + public static final String FUNCTION_SIZE_THRESHOLD_KEY = "funcsize.threshold"; + private int functionsBelowThreshold = 0; - + private int sizeThreshold = 0; - + private int functionsOverThreshold = 0; - + private int locBelowThreshold = 0; - + private int locOverThreshold = 0; - + private Hashtable bigFunctionsPerFile = new Hashtable<>(); - - private Hashtable locInBigFunctionsPerFile = new Hashtable<>(); - + + private Hashtable locInBigFunctionsPerFile = new Hashtable<>(); + public CxxFunctionSizeSquidSensor(CxxLanguage language){ this.sizeThreshold = language.getIntegerOption(FUNCTION_SIZE_THRESHOLD_KEY).orElse(20); - if (LOG.isDebugEnabled()) - LOG.debug("Function size threshold: " + this.sizeThreshold); + if (LOG.isDebugEnabled()) { + LOG.debug("Function size threshold: " + this.sizeThreshold); + } } - + @Override public void init() { subscribeTo(CxxGrammarImpl.functionBody); @@ -70,21 +71,23 @@ public void init() { @Override public void leaveNode(AstNode node) { SourceFunction sourceFunction = (SourceFunction) getContext().peekSourceCode(); - SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class); - + SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class); + int lineCount = getNumberOfLine(node); - + incrementFunctionByThresholdForProject(lineCount); - incrementFunctionByThresholdForFile(sourceFile, lineCount); + incrementFunctionByThresholdForFile(sourceFile, lineCount); } - + private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int lineCount){ - if (!bigFunctionsPerFile.containsKey(sourceFile)) + if (!bigFunctionsPerFile.containsKey(sourceFile)) { bigFunctionsPerFile.put(sourceFile, new FunctionCount()); - - if (!locInBigFunctionsPerFile.containsKey(sourceFile)) - locInBigFunctionsPerFile.put(sourceFile, new FunctionCount()); - + } + + if (!locInBigFunctionsPerFile.containsKey(sourceFile)) { + locInBigFunctionsPerFile.put(sourceFile, new FunctionCount()); + } + FunctionCount count = bigFunctionsPerFile.get(sourceFile); FunctionCount locCount = locInBigFunctionsPerFile.get(sourceFile); if (lineCount > this.sizeThreshold){ @@ -92,11 +95,11 @@ private void incrementFunctionByThresholdForFile(SourceFile sourceFile, int line locCount.countOverThreshold += lineCount; } else { - count.countBelowThreshold++; + count.countBelowThreshold++; locCount.countBelowThreshold += lineCount; } - } - + } + private void incrementFunctionByThresholdForProject(int lineCount){ if (lineCount > sizeThreshold) { this.functionsOverThreshold++; @@ -116,66 +119,68 @@ public SquidAstVisitor getVisitor() { @Override public void publishMeasureForFile(InputFile inputFile, SourceFile squidFile, SensorContext context) { - publishBigFunctionMetrics(inputFile, squidFile, context); - publishLocInBigFunctionMetrics(inputFile, squidFile, context); + publishBigFunctionMetrics(inputFile, squidFile, context); + publishLocInBigFunctionMetrics(inputFile, squidFile, context); } @Override public void publishMeasureForProject(InputModule module, SensorContext context) { - publishBigFunctionCountForProject(module, context); + publishBigFunctionCountForProject(module, context); publishLocInBigFunctionForProject(module, context); } - + private void publishBigFunctionCountForProject(InputModule module, SensorContext context){ context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) .on(module) .withValue(functionsOverThreshold) .save(); - + context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_PERC) .on(module) .withValue(calculatePercentual(functionsOverThreshold, functionsBelowThreshold)) - .save(); + .save(); } - + private void publishLocInBigFunctionForProject(InputModule module, SensorContext context){ context.newMeasure() .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) .on(module) .withValue(locOverThreshold + locBelowThreshold) - .save(); - + .save(); + context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC) .on(module) .withValue(locOverThreshold) .save(); - + context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC) .on(module) .withValue(calculatePercentual(locOverThreshold, locBelowThreshold)) - .save(); + .save(); } - + private double calculatePercentual(int overThreshold, int belowThreshold){ double total = (double)overThreshold + (double)belowThreshold; - if (total > 0) + if (total > 0) { return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold); - else + } + else { return 0; + } } private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile, SensorContext context) { FunctionCount c = bigFunctionsPerFile.get(squidFile); - if (c == null){ + if (c == null){ c = new FunctionCount(); c.countBelowThreshold = 0; c.countOverThreshold = 0; } - + context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS) .on(inputFile) @@ -186,7 +191,7 @@ private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_PERC) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) - .save(); + .save(); } private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squidFile, SensorContext context) { @@ -196,13 +201,13 @@ private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squi c.countBelowThreshold = 0; c.countOverThreshold = 0; } - + context.newMeasure() .forMetric(FunctionSizeMetrics.LOC_IN_FUNCTIONS) .on(inputFile) .withValue(c.countOverThreshold + c.countBelowThreshold) - .save(); - + .save(); + context.newMeasure() .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC) .on(inputFile) @@ -213,7 +218,7 @@ private void publishLocInBigFunctionMetrics(InputFile inputFile, SourceFile squi .forMetric(FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC) .on(inputFile) .withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold)) - .save(); + .save(); } - + } diff --git a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java index fe1d26eb8d..11c9b636f7 100644 --- a/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java +++ b/cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/FunctionSizeMetrics.java @@ -27,45 +27,45 @@ import org.sonar.api.measures.Metrics; public class FunctionSizeMetrics implements Metrics { - + public static final Metric BIG_FUNCTIONS = new Metric.Builder("big_functions", "Big Functions", Metric.ValueType.INT) .setDescription("Number of functions with too many lines") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) .create(); - + public static final Metric BIG_FUNCTIONS_LOC = new Metric.Builder("loc_in_big_functions", "Big Functions Lines of Code", Metric.ValueType.INT) .setDescription("Number of lines of code in functions with too many lines") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - + .create(); + public static final Metric BIG_FUNCTIONS_PERC = new Metric.Builder("perc_big_functions", "Big Functions (%)", Metric.ValueType.PERCENT) .setDescription("% of functions with too many lines") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - + .create(); + public static final Metric BIG_FUNCTIONS_LOC_PERC = new Metric.Builder("perc_loc_in_big_functions", "Big Functions Lines of Code (%)", Metric.ValueType.PERCENT) .setDescription("% of lines of code in functions with too many lines") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); - + .create(); + public static final Metric LOC_IN_FUNCTIONS = new Metric.Builder("loc_in_functions", "Lines of Code in Functions", Metric.ValueType.INT) .setDescription("Number of lines of code in function bodies") .setDirection(Metric.DIRECTION_WORST) .setQualitative(Boolean.FALSE) .setDomain(CoreMetrics.DOMAIN_SIZE) - .create(); + .create(); @Override public List getMetrics() { return asList(BIG_FUNCTIONS, BIG_FUNCTIONS_PERC, BIG_FUNCTIONS_LOC, BIG_FUNCTIONS_LOC_PERC, LOC_IN_FUNCTIONS); } - + } 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 e3aaf3bc09..5e8c6627c9 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 @@ -86,9 +86,9 @@ public class CxxSquidSensor implements Sensor { private final CxxChecks checks; private final CxxLanguage language; - + private List squidSensors = new ArrayList<>(); - + public List getSquidSensors(){ return this.squidSensors; } @@ -118,11 +118,11 @@ public CxxSquidSensor(CxxLanguage language, if (this.language.getMetricsCache().isEmpty()) { new CxxMetrics(this.language); } - + registerSquidSensors(); } - - protected void registerSquidSensors(){ + + protected void registerSquidSensors(){ if (this.language.getKey() == "c++"){ this.squidSensors.add(new CxxFunctionComplexitySquidSensor(this.language)); this.squidSensors.add(new CxxFunctionSizeSquidSensor(this.language)); @@ -152,9 +152,9 @@ public void execute(SensorContext context) { context, this.language.getBooleanOption(CPD_IGNORE_LITERALS_KEY).orElse(Boolean.FALSE), this.language.getBooleanOption(CPD_IGNORE_IDENTIFIERS_KEY).orElse(Boolean.FALSE))); - + for (SquidSensor sensor : squidSensors) - visitors.add(sensor.getVisitor()); + visitors.add(sensor.getVisitor()); CxxConfiguration cxxConf = createConfiguration(context.fileSystem(), context); AstScanner scanner = CxxAstScanner.create(this.language, cxxConf, @@ -234,7 +234,7 @@ private void save(Collection squidSourceFiles, SensorContext context .withValue(violationsCount) .save(); } - + for(SquidSensor sensor: squidSensors) sensor.publishMeasureForProject(context.module(), context); } @@ -272,7 +272,7 @@ private void saveMeasures(InputFile inputFile, SourceFile squidFile, SensorConte context.newMeasure().forMetric(language.getMetric(CxxMetrics.PUBLIC_DOCUMENTED_API_DENSITY_KEY)) .on(inputFile).withValue(densityOfPublicDocumentedApi).save(); } - + for(SquidSensor sensor: squidSensors) sensor.publishMeasureForFile(inputFile, squidFile, context); } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java index bd611991d7..017cf2f000 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensorTest.java @@ -43,24 +43,24 @@ import org.sonar.squidbridge.api.SourceFile; public class CxxFunctionComplexitySquidSensorTest { - + private FileLinesContextFactory fileLinesContextFactory; private FileLinesContext fileLinesContext; private CxxLanguage language; private SensorContextTester sensorContext; - private CxxFunctionComplexitySquidSensor sensor; - + private CxxFunctionComplexitySquidSensor sensor; + @Before public void setUp(){ fileLinesContextFactory = mock(FileLinesContextFactory.class); - fileLinesContext = mock(FileLinesContext.class); - - language = TestUtils.mockCxxLanguage(); + fileLinesContext = mock(FileLinesContext.class); + + language = TestUtils.mockCxxLanguage(); when(language.getIntegerOption(CxxFunctionComplexitySquidSensor.FUNCTION_COMPLEXITY_THRESHOLD_KEY)).thenReturn(Optional.of(5)); - - sensor = new CxxFunctionComplexitySquidSensor(language); + + sensor = new CxxFunctionComplexitySquidSensor(language); } - + private DefaultInputFile getInputFile() throws IOException{ File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); File target = new File(baseDir, "FunctionComplexity.cc"); @@ -73,11 +73,11 @@ private DefaultInputFile getInputFile() throws IOException{ sensorContext = SensorContextTester.create(baseDir); sensorContext.fileSystem().add(inputFile); - when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); - + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + return inputFile; } - + private DefaultInputFile getEmptyInputFile() throws IOException{ File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); File target = new File(baseDir, "EmptyFile.cc"); @@ -90,74 +90,75 @@ private DefaultInputFile getEmptyInputFile() throws IOException{ sensorContext = SensorContextTester.create(baseDir); sensorContext.fileSystem().add(inputFile); - when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); - + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + return inputFile; - } - + } + public boolean containsAll(Collection c){ return false; } - + private T getMeasureValue(SensorContextTester sensorContext, String componentKey, Metric metric){ Collection measures = sensorContext.measures(componentKey); T value = null; for(Measure m : measures){ - if (m.metric() == metric) + if (m.metric() == metric) { value = (T) m.value(); + } } return value; - } - + } + @Test - public void testPublishMeasuresForProject() throws IOException { - DefaultInputFile inputFile = getInputFile(); - + public void testPublishMeasuresForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); - } - + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); + } + @Test - public void testPublishMeasuresForEmptyProject() throws IOException { - DefaultInputFile inputFile = getEmptyInputFile(); - + public void testPublishMeasuresForEmptyProject() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); - } - + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); + } + @Test - public void testPublishMeasuresForFile() throws IOException { - DefaultInputFile inputFile = getInputFile(); - + public void testPublishMeasuresForFile() throws IOException { + DefaultInputFile inputFile = getInputFile(); + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); - } + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(80); + } @Test public void testPublishMeasuresForEmptyFile() throws IOException { DefaultInputFile inputFile = getEmptyInputFile(); - + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); - } + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)).isEqualTo(0); + } } diff --git a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java index d6b0bfa3f3..2149f8d47b 100644 --- a/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java +++ b/cxx-sensors/src/test/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensorTest.java @@ -52,18 +52,18 @@ public class CxxFunctionSizeSquidSensorTest { private SensorContextTester sensorContext; private CxxFunctionSizeSquidSensor sensor; private Configuration configuration; - + @Before public void setUp(){ fileLinesContextFactory = mock(FileLinesContextFactory.class); - fileLinesContext = mock(FileLinesContext.class); - - language = TestUtils.mockCxxLanguage(); + fileLinesContext = mock(FileLinesContext.class); + + language = TestUtils.mockCxxLanguage(); when(language.getIntegerOption(CxxFunctionSizeSquidSensor.FUNCTION_SIZE_THRESHOLD_KEY)).thenReturn(Optional.of(10)); - - sensor = new CxxFunctionSizeSquidSensor(this.language); - } - + + sensor = new CxxFunctionSizeSquidSensor(this.language); + } + private DefaultInputFile getInputFile() throws IOException{ File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); File target = new File(baseDir, "FunctionComplexity.cc"); @@ -76,11 +76,11 @@ private DefaultInputFile getInputFile() throws IOException{ sensorContext = SensorContextTester.create(baseDir); sensorContext.fileSystem().add(inputFile); - when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); - + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + return inputFile; - } - + } + private DefaultInputFile getEmptyInputFile() throws IOException{ File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors"); File target = new File(baseDir, "EmptyFile.cc"); @@ -93,74 +93,75 @@ private DefaultInputFile getEmptyInputFile() throws IOException{ sensorContext = SensorContextTester.create(baseDir); sensorContext.fileSystem().add(inputFile); - when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); - + when(fileLinesContextFactory.createFor(inputFile)).thenReturn(fileLinesContext); + return inputFile; - } - + } + private T getMeasureValue(SensorContextTester sensorContext, String componentKey, Metric metric){ Collection measures = sensorContext.measures(componentKey); T value = null; for(Measure m : measures){ - if (m.metric() == metric) + if (m.metric() == metric) { value = (T) m.value(); + } } return value; - } - + } + @Test - public void testPublishMeasuresForProject() throws IOException { - DefaultInputFile inputFile = getInputFile(); - + public void testPublishMeasuresForProject() throws IOException { + DefaultInputFile inputFile = getInputFile(); + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); - } - + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); + } + @Test - public void testPublishMeasuresForEmptyProject() throws IOException { - DefaultInputFile inputFile = getEmptyInputFile(); - + public void testPublishMeasuresForEmptyProject() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForProject(sensorContext.module(), sensorContext); - - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); - } - + + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, sensorContext.module().key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); + } + @Test - public void testPublishMeasuresForFile() throws IOException { - DefaultInputFile inputFile = getInputFile(); - + public void testPublishMeasuresForFile() throws IOException { + DefaultInputFile inputFile = getInputFile(); + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); - } - + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(4); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(55); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(44); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(40.0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(80); + } + @Test - public void testPublishMeasuresForEmptyFile() throws IOException { - DefaultInputFile inputFile = getEmptyInputFile(); - + public void testPublishMeasuresForEmptyFile() throws IOException { + DefaultInputFile inputFile = getEmptyInputFile(); + SourceFile squidFile = CxxAstScanner.scanSingleFile(inputFile, sensorContext, TestUtils.mockCxxLanguage(), sensor.getVisitor()); sensor.publishMeasureForFile(inputFile, squidFile, sensorContext); - - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); - assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); - } + + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.LOC_IN_FUNCTIONS)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_PERC)).isEqualTo(0); + assertThat(getMeasureValue(sensorContext, inputFile.key(), FunctionSizeMetrics.BIG_FUNCTIONS_LOC_PERC)).isEqualTo(0); + } } 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 dc5e677dba..89846f342e 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 @@ -186,7 +186,7 @@ public void testForceIncludedFiles() throws UnsupportedEncodingException, IOExce Collection measures = context.measures("ProjectKey:src/src1.cc"); - // These checks actually check the force include feature, since only if it works the metric values will be like follows + // These checks actually check the force include feature, since only if it works the metric values will be like follows assertThat(GetIntegerMeasureByKey(measures, CoreMetrics.FILES).value()).isEqualTo(1); assertThat(GetIntegerMeasureByKey(measures, CoreMetrics.NCLOC).value()).isEqualTo(1); assertThat(GetIntegerMeasureByKey(measures, CoreMetrics.STATEMENTS).value()).isEqualTo(2); @@ -214,34 +214,34 @@ public void testBehaviourOnCircularIncludes() throws UnsupportedEncodingExceptio assertThat(GetIntegerMeasureByKey(measures, CoreMetrics.NCLOC).value()).isEqualTo(1); } - + @Test public void testSquidSensors() throws IOException{ - File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors/codechunks-project"); + File baseDir = TestUtils.loadResource("/org/sonar/cxx/sensors/codechunks-project"); File target = new File(baseDir, "code_chunks.cc"); SensorContextTester context = SensorContextTester.create(baseDir); - + String content = new String(Files.readAllBytes(target.toPath()), "UTF-8"); DefaultInputFile inputFile = TestInputFileBuilder.create("ProjectKey", baseDir, target).setContents(content) .setCharset(Charset.forName("UTF-8")).setLanguage(language.getKey()) .setType(InputFile.Type.MAIN).build(); - + SquidAstVisitor mockVisitor = (SquidAstVisitor) mock(SquidAstVisitor.class); SquidSensor squidSensorMock = mock(SquidSensor.class); when(squidSensorMock.getVisitor()).thenReturn(mockVisitor); - - sensor.getSquidSensors().clear(); - sensor.getSquidSensors().add(squidSensorMock); - + + sensor.getSquidSensors().clear(); + sensor.getSquidSensors().add(squidSensorMock); + context.fileSystem().add(inputFile); - sensor.execute(context); - + sensor.execute(context); + verify(squidSensorMock, times(1)).getVisitor(); verify(squidSensorMock, times(1)).publishMeasureForFile(eq(inputFile), any(SourceFile.class), eq(context)); verify(squidSensorMock, times(1)).publishMeasureForProject(any(InputModule.class), eq(context)); } - - + + private Measure GetIntegerMeasureByKey(Collection measures, Metric metric) { for (Measure measure : measures) { diff --git a/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java b/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java index 4c6c71bd6b..f39da974ae 100644 --- a/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java +++ b/cxx-squid/src/main/java/org/sonar/cxx/CxxLanguage.java @@ -72,10 +72,10 @@ public String getRepositorySuffix() { public String getPluginProperty(String key) { return "sonar." + getPropertiesKey() + "." + key; } - + public Optional getIntegerOption(String key){ return this.settings.getInt(getPluginProperty(key)); - } + } public Optional getBooleanOption(String key) { return this.settings.getBoolean(getPluginProperty(key)); 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 0ff990fc0b..1b68988346 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 @@ -352,7 +352,7 @@ private static List codeAnalysisProperties() { .onQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE) .type(PropertyType.INTEGER) .index(19) - .build() + .build() )); } @@ -517,11 +517,11 @@ public void define(Context context) { l.addAll(testingAndCoverageProperties()); l.addAll(compilerWarningsProperties()); l.addAll(duplicationsProperties()); - + //extra metrics l.add(FunctionComplexityMetrics.class); l.add(FunctionSizeMetrics.class); - + context.addExtensions(l); } @@ -532,7 +532,7 @@ public List getSensorsImpl() { l.add(CxxCoverageAggregator.class); l.add(CxxUnitTestResultsAggregator.class); - // metrics + // metrics l.add(CxxMetricsImp.class); // issue sensors