34import org.sonar.cxx.parser.CxxPunctuator;
35import org.sonar.cxx.squidbridge.api.SourceCode;
36
37public class CxxCognitiveComplexityVisitor<G extends Grammar> extends MultiLocatitionSquidCheck<G> { 38 39 private static final AstNodeType[] DESCENDANT_TYPES = new AstNodeType[]{ 40 CxxGrammarImpl.handler, 41 CxxGrammarImpl.iterationStatement, 42 CxxGrammarImpl.lambdaExpression, 43 CxxGrammarImpl.logicalAndExpression, 44 CxxGrammarImpl.logicalOrExpression, 45 CxxGrammarImpl.selectionStatement, 46 CxxKeyword.ELSE, 47 CxxKeyword.GOTO, 48 CxxPunctuator.QUEST, 49 IDENTIFIER}; 50 51 private static final AstNodeType[] INCREMENT_TYPES = new AstNodeType[]{ 52 CxxGrammarImpl.handler, 53 CxxGrammarImpl.iterationStatement, 54 CxxGrammarImpl.logicalAndExpression, 55 CxxGrammarImpl.logicalOrExpression, 56 CxxGrammarImpl.selectionStatement, 57 CxxKeyword.ELSE, 58 CxxKeyword.GOTO, 59 CxxPunctuator.QUEST}; 60 61 private static final AstNodeType[] NESTING_LEVEL_TYPES = new AstNodeType[]{ 62 CxxGrammarImpl.handler, 63 CxxGrammarImpl.iterationStatement, 64 CxxGrammarImpl.lambdaExpression, 65 CxxGrammarImpl.selectionStatement, 66 CxxPunctuator.QUEST}; 67 68 private static final AstNodeType[] NESTING_INCREMENTS_TYPES = new AstNodeType[]{ 69 CxxGrammarImpl.handler, 70 CxxGrammarImpl.iterationStatement, 71 CxxGrammarImpl.selectionStatement, 72 CxxPunctuator.QUEST}; 73 74 private static final Set<AstNodeType> SUBSCRIPTION_NODES = new HashSet<>(); 75 76 static { 77 SUBSCRIPTION_NODES.add(CxxGrammarImpl.functionBody); // root node for Cognitive Complexity 78 79 SUBSCRIPTION_NODES.addAll(Arrays.asList(DESCENDANT_TYPES)); 80 SUBSCRIPTION_NODES.addAll(Arrays.asList(INCREMENT_TYPES)); 81 SUBSCRIPTION_NODES.addAll(Arrays.asList(NESTING_LEVEL_TYPES)); 82 SUBSCRIPTION_NODES.addAll(Arrays.asList(NESTING_INCREMENTS_TYPES)); 83 } 84 85 private Deque<CxxComplexityScope> complexityScopes = null; 86 87 private static boolean isElseIf(AstNode node) { 88 return node.is(CxxGrammarImpl.selectionStatement) && node.getToken().getType().equals(CxxKeyword.IF) 89 && node.getParent().getPreviousAstNode().getType().equals(CxxKeyword.ELSE); 90 } 91 92 @Override 93 public void init() { 94 for (var astNodeType : SUBSCRIPTION_NODES) { 95 subscribeTo(astNodeType); 96 } 97 complexityScopes = new LinkedList<>(); 98 } 99100 @Override101 public void visitNode(AstNode node) {102 if (node.getToken().isGeneratedCode()) {103 return;104 }105106 if (node.is(CxxGrammarImpl.functionBody) && node.hasDirectChildren(CxxGrammarImpl.compoundStatement)) {107 complexityScopes.addFirst(new CxxComplexityScope(node.getTokenLine()));108 return;109 }110111 if (complexityScopes.isEmpty()) {112 return;113 }114115 if (isElseIf(node)) {116 return;117 }118119 if (node.is(NESTING_INCREMENTS_TYPES)) {120 complexityScopes.getFirst().addComplexitySourceWithNesting(node);121 } else if (node.is(INCREMENT_TYPES)) {122 complexityScopes.getFirst().addComplexitySource(node);123 }124125 if (node.is(NESTING_LEVEL_TYPES)) {126 for (var scope : complexityScopes) {127 scope.increaseNesting();128 }129 }130 }131132 @Override133 public void leaveNode(AstNode node) {134 if (!complexityScopes.isEmpty()) {135 if (node.getToken().isGeneratedCode()) {136 return;137 }138139 if (node.is(CxxGrammarImpl.functionBody)) {140 analyzeComplexity(complexityScopes.removeFirst());141 }142143 if (complexityScopes.isEmpty()) {144 return;145 }146147 if (isElseIf(node)) {148 return;149 }150151 if (node.is(NESTING_LEVEL_TYPES)) {152 for (var scope : complexityScopes) {153 scope.decreaseNesting();154 }155 }156 }157 }158159 protected void analyzeComplexity(CxxComplexityScope scope) {160 SourceCode code = getContext().peekSourceCode();161 code.setMeasure(CxxMetric.COGNITIVE_COMPLEXITY, scope.getComplexity());162 }163164}
30import org.sonar.api.utils.log.Logger;
31import org.sonar.api.utils.log.Loggers;
32
33@Phase(name = Phase.Name.PRE) 34public class DroppedPropertiesSensor implements ProjectSensor { 35 36 private static final Logger LOG = Loggers.get(DroppedPropertiesSensor.class); 37 38 private static final String MSG_COMPILER = "Use 'sonar.cxx.vc' or 'sonar.cxx.gcc' instead." 39 + " Use 'sonar.cxx.msbuild' to read includes and defines from MSBuild log file."; 40 41 private static final Map<String, String> ALL_REMOVED_PROPERTIES = initRemovedProperties(); 42 private final AnalysisWarnings analysisWarnings; 43 44 public DroppedPropertiesSensor(AnalysisWarnings analysisWarnings) { 45 this.analysisWarnings = analysisWarnings; 46 } 47 48 private static Map<String, String> initRemovedProperties() { 49 var map = new HashMap<String, String>(); 50 map.put("sonar.cxx.include_directories", "Use 'sonar.cxx.includeDirectories' instead."); // V0.9.1 51 map.put("sonar.cxx.externalrules.reportPaths", "Use 'sonar.cxx.other.reportPaths' instead."); // V0.9.1 52 map.put("sonar.cxx.cppncss.reportPaths", ""); // V0.9.1 53 map.put("sonar.cxx.other.sqales", ""); // V0.9.6 54 map.put("sonar.cxx.xunit.provideDetails", ""); // V0.9.7 55 map.put("sonar.cxx.coverage.itReportPaths", ""); // V0.9.8 56 map.put("sonar.cxx.coverage.overallReportPaths", ""); // V0.9.8 57 map.put("sonar.cxx.forceZeroCoverage", ""); // V0.9.8 58 map.put("sonar.cxx.scanOnlySpecifiedSources", ""); // V1.0.0 59 map.put("sonar.cxx.compiler.parser", MSG_COMPILER); // V1.2.0 60 map.put("sonar.cxx.compiler.reportPaths", MSG_COMPILER); // V1.2.0 61 map.put("sonar.cxx.compiler.regex", MSG_COMPILER); // V1.2.0 62 map.put("sonar.cxx.compiler.charset", MSG_COMPILER); // V1.2.0 63 map.put("sonar.cxx.missingIncludeWarnings", "Turn debug info on to get the information."); // V1.2.0 64 map.put("sonar.cxx.cFilesPatterns", 65 "Define C++ keywords in an own header file and include it with 'sonar.cxx.forceIncludes' instead."); // V2.0.0 66 map.put("sonar.cxx.suffixes.sources", "Use key 'sonar.cxx.file.suffixes' instead."); // V2.0.0 67 map.put("sonar.cxx.suffixes.headers", 68 "Use key 'sonar.cxx.file.suffixes' instead. For API detection use 'sonar.cxx.metric.api.file.suffixes'."); // V2.0.0 69 map.put("sonar.cxx.other.xslt.1.stylesheet", "Use 'sonar.cxx.xslt.1.stylesheet' instead."); // V2.0.0 70 map.put("sonar.cxx.other.xslt.1.inputs", "Use 'sonar.cxx.xslt.1.inputs' instead."); // V2.0.0 71 map.put("sonar.cxx.other.xslt.1.outputs", "Use 'sonar.cxx.xslt.1.outputs' instead."); // V2.0.0 72 map.put("sonar.cxx.xunit.xsltURL", "Use 'sonar.cxx.xslt.xxx' instead."); // V2.0.0 73 map.put("sonar.cxx.clangsa.reportPath", "Use 'sonar.cxx.clangsa.reportPaths' instead."); // V2.0.0 74 map.put("sonar.cxx.clangtidy.reportPath", "Use 'sonar.cxx.clangtidy.reportPaths' instead."); // V2.0.0 75 map.put("sonar.cxx.gcc.reportPath", "Use 'sonar.cxx.gcc.reportPaths' instead."); // V2.0.0 76 map.put("sonar.cxx.vc.reportPath", "Use 'sonar.cxx.vc.reportPaths' instead."); // V2.0.0 77 map.put("sonar.cxx.cppcheck.reportPath", "Use 'sonar.cxx.cppcheck.reportPaths' instead."); // V2.0.0 78 map.put("sonar.cxx.drmemory.reportPath", "Use 'sonar.cxx.drmemory.reportPaths' instead."); // V2.0.0 79 map.put("sonar.cxx.other.reportPath", "Use 'sonar.cxx.other.reportPaths' instead."); // V2.0.0 80 map.put("sonar.cxx.pclint.reportPath", "Use 'sonar.cxx.pclint.reportPaths' instead."); // V2.0.0 81 map.put("sonar.cxx.xunit.reportPath", "Use 'sonar.cxx.xunit.reportPaths' instead."); // V2.0.0 82 map.put("sonar.cxx.valgrind.reportPath", "Use 'sonar.cxx.valgrind.reportPaths' instead."); // V2.0.0 83 map.put("sonar.cxx.vera.reportPath", "Use 'sonar.cxx.vera.reportPaths' instead."); // V2.0.0 84 map.put("sonar.cxx.msbuild.reportPath", "Use 'sonar.cxx.msbuild.reportPaths' instead."); // V2.0.0 85 map.put("sonar.cxx.coverage.reportPath", "Use 'sonar.cxx.bullseye.reportPaths'" 86 + ", 'sonar.cxx.cobertura.reportPaths', 'sonar.cxx.vscoveragexml.reportPaths' or 'sonar.cxx.ctctxt.reportPaths'" 87 + " instead."); // V2.0.0 88 map.put("sonar.cxx.funccomplexity.threshold", 89 "Use 'sonar.cxx.metric.func.complexity.threshold' instead."); // V2.0.0 90 map.put("sonar.cxx.funcsize.threshold", "Use 'sonar.cxx.metric.func.size.threshold' instead."); // V2.0.0 91 map.put("sonar.cxx.vstest.reportsPaths", "Use 'sonar.cxx.vstest.reportPaths' instead."); // V2.0.0 92 map.put("sonar.cxx.xunit.reportsPaths", "Use 'sonar.cxx.xunit.reportPaths' instead."); // V2.0.0 93 map.put("sonar.cxx.nunit.reportsPaths", "Use 'sonar.cxx.nunit.reportPaths' instead."); // V2.0.0 94 map.put("sonar.cxx.clangtidy.charset", "Use 'sonar.cxx.clangtidy.encoding' instead."); // V2.0.0 95 map.put("sonar.cxx.gcc.charset", "Use 'sonar.cxx.gcc.encoding' instead."); // V2.0.0 96 map.put("sonar.cxx.vc.charset", "Use 'sonar.cxx.vc.encoding' instead."); // V2.0.0 97 map.put("sonar.cxx.ctctxt.charset", "Use 'sonar.cxx.ctctxt.encoding' instead."); // V2.0.0 98 map.put("sonar.cxx.msbuild.charset", "Use 'sonar.cxx.msbuild.encoding' instead."); // V2.0.0 99 map.put("sonar.cxx.cpd.ignoreLiterals", "Use 'sonar.cxx.metric.cpd.ignoreLiterals' instead."); // V2.0.0100 map.put("sonar.cxx.cpd.ignoreIdentifiers", "Use 'sonar.cxx.metric.cpd.ignoreIdentifiers' instead."); // V2.0.0101 map.put("sonar.cxx.nunit.reportPaths", "If possible use 'sonar.cs.nunit.reportsPaths' instead."); // V2.0.0102 map.put("sonar.cxx.vstest.reportPaths", "If possible use 'sonar.cs.vstest.reportsPaths' instead."); // V2.0.0103104 return Collections.unmodifiableMap(map);105 }106107 @Override108 public void describe(SensorDescriptor descriptor) {109 descriptor110 .onlyOnLanguage("cxx")111 .onlyWhenConfiguration(configuration -> ALL_REMOVED_PROPERTIES.keySet().stream().anyMatch(configuration::hasKey))112 .name("CXX verify analysis parameters");113 }114115 @Override116 public void execute(SensorContext context) {117 ALL_REMOVED_PROPERTIES.forEach((key, info) -> {118 if (context.config().hasKey(key)) {119 var msg = "CXX property '" + key + "' is no longer supported.";120 if (!info.isEmpty()) {121 msg += " " + info;122 }123 analysisWarnings.addUnique(msg);124 LOG.warn(msg);125 }126 });127 }128129}
59 sonarWay.done();
60 }
61
62 static class Profile {6364 public String name;65 public List<String> ruleKeys;66 }67
68}
23import org.sonar.cxx.checks.CheckList;
24import org.sonar.cxx.squidbridge.annotations.AnnotationBasedRulesDefinition;
25
26public class CxxRuleRepository implements RulesDefinition {2728 private static final String REPOSITORY_NAME = "SonarQube";2930 @Override31 public void define(Context context) {32 var repository = context.createRepository("cxx", CxxLanguage.KEY).33 setName(REPOSITORY_NAME);34 new AnnotationBasedRulesDefinition(repository, CxxLanguage.KEY).addRuleClasses(false, CheckList.getChecks());35 repository.done();36 }3738}
25import org.sonar.api.measures.Metrics;
26import org.sonar.cxx.CxxMetrics;
27
28public class CxxMetricDefinition implements Metrics {2930 @Override31 public List<Metric> getMetrics() {32 return Collections.unmodifiableList(33 CxxMetrics.getMetrics()34 );35 }36}
This class does not have any documentation.
Consider adding a documentation comment to explain its use.
While it may seem like the functionality of a class is perfectly obvious, any consumers of your API may not be able to pick up on certain details.
Consider a case where the class given below can be instantiated and provides certain functionalities within each instance in a thread-safe manner, perhaps it is a rest API client.
If there is no documentation comment on the class, it is not immediately obvious that the class is thread safe. Thus, multiple instances of the class may be created to perform operations concurrently, using up both memory as well as OS resources like sockets. If it were known from the beginning that the class were thread safe, the user would not need to create unnecessary extra instances of SomeClass
.
class SomeClass {
// ...
}
Make sure to add useful information regarding the usage or implementation of a particular declaration, so that anything about it which can't be understood from the name or some other cue is correctly conveyed.
/**
* Instances of this class are used to perform xyz action.
*
* This class is thread safe and the same instance can be used over multiple threads.
*/
class SomeClass {
// ...
}
This issue will not be reported for model entity classes. If there is any non-obvious behavior associated with a particular class however, do consider documenting it.