Skip to content

Commit f992687

Browse files
committed
cache TooManyLinesOfCodeInFunctionCheck.getNumberOfLine
this function is called 3 times for each function declaration * TooManyLinesOfCodeInFunctionCheck * CxxFunctionComplexitySquidSensor * CxxFunctionSizeSquidSensor solution: calculate only once and store this metric in CxxMetric.LINES_OF_CODE_IN_FUNCION_BODY
1 parent c30efb3 commit f992687

File tree

7 files changed

+86
-40
lines changed

7 files changed

+86
-40
lines changed

cxx-checks/src/main/java/org/sonar/cxx/checks/metrics/TooManyLinesOfCodeInFunctionCheck.java

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,12 @@
2626
import org.sonar.check.Rule;
2727
import org.sonar.check.RuleProperty;
2828
import org.sonar.cxx.api.CppPunctuator;
29+
import org.sonar.cxx.api.CxxMetric;
2930
import org.sonar.cxx.parser.CxxGrammarImpl;
3031
import org.sonar.cxx.tag.Tag;
3132
import org.sonar.squidbridge.annotations.ActivatedByDefault;
3233
import org.sonar.squidbridge.annotations.SqaleConstantRemediation;
34+
import org.sonar.squidbridge.api.SourceFunction;
3335
import org.sonar.squidbridge.checks.SquidCheck;
3436

3537
@Rule(key = "TooManyLinesOfCodeInFunction",
@@ -56,7 +58,8 @@ public void init() {
5658

5759
@Override
5860
public void leaveNode(AstNode node) {
59-
int lineCount = getNumberOfLine(node);
61+
SourceFunction sourceFunction = (SourceFunction) getContext().peekSourceCode();
62+
int lineCount = sourceFunction.getInt(CxxMetric.LINES_OF_CODE_IN_FUNCTION_BODY);
6063
if (lineCount > max) {
6164
getContext().createLineViolation(this,
6265
"The number of code lines in this function is {0,number,integer} which is greater than "
@@ -65,31 +68,6 @@ public void leaveNode(AstNode node) {
6568
}
6669
}
6770

68-
/**
69-
* aggregates lines for child nodes
70-
*
71-
* @param node with child nodes
72-
* @return number of lines
73-
*/
74-
public static int getNumberOfLine(AstNode node) {
75-
List<AstNode> allChilds = node.getDescendants(CxxGrammarImpl.statement, CppPunctuator.CURLBR_LEFT,
76-
CppPunctuator.CURLBR_RIGHT);
77-
int lines = 1;
78-
int firstLine = node.getTokenLine();
79-
if (allChilds != null && !allChilds.isEmpty()) {
80-
int previousLine = firstLine;
81-
int currentLine = 0;
82-
for (AstNode child : allChilds) {
83-
currentLine = child.getTokenLine();
84-
if (currentLine != previousLine) {
85-
lines++;
86-
previousLine = currentLine;
87-
}
88-
}
89-
}
90-
return lines;
91-
}
92-
9371
public void setMax(int max) {
9472
this.max = max;
9573
}

cxx-sensors/src/main/java/org/sonar/cxx/sensors/functioncomplexity/CxxFunctionComplexitySquidSensor.java

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.sonar.api.utils.log.Loggers;
3030
import org.sonar.cxx.CxxLanguage;
3131
import org.sonar.cxx.api.CxxMetric;
32-
import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine;
3332
import org.sonar.cxx.parser.CxxGrammarImpl;
3433
import org.sonar.cxx.sensors.squid.SquidSensor;
3534
import org.sonar.squidbridge.SquidAstVisitor;
@@ -73,16 +72,16 @@ public SquidAstVisitor<Grammar> getVisitor() {
7372

7473
@Override
7574
public void init() {
76-
subscribeTo(CxxGrammarImpl.functionDefinition);
75+
subscribeTo(CxxGrammarImpl.functionBody);
7776
}
7877

7978
@Override
8079
public void leaveNode(AstNode node) {
8180
SourceFunction sourceFunction = (SourceFunction) getContext().peekSourceCode();
82-
SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class);
81+
SourceFile sourceFile = sourceFunction.getAncestor(SourceFile.class);
8382

8483
int complexity = ChecksHelper.getRecursiveMeasureInt(sourceFunction, CxxMetric.COMPLEXITY);
85-
int lineCount = getNumberOfLine(node);
84+
int lineCount = sourceFunction.getInt(CxxMetric.LINES_OF_CODE_IN_FUNCTION_BODY);
8685

8786
incrementFunctionByThresholdForAllFiles(complexity, lineCount);
8887
incrementFunctionByThresholdForFile(sourceFile, complexity, lineCount);
@@ -137,13 +136,13 @@ private void publishComplexFunctionMetricsForFile(InputFile inputFile, SourceFil
137136
context.<Integer>newMeasure()
138137
.forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS)
139138
.on(inputFile)
140-
.withValue((int)c.countOverThreshold)
139+
.withValue(c.countOverThreshold)
141140
.save();
142141

143142
context.<Double>newMeasure()
144143
.forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_PERC)
145144
.on(inputFile)
146-
.withValue(calculatePercentual((int)c.countOverThreshold, (int)c.countBelowThreshold))
145+
.withValue(calculatePercentual(c.countOverThreshold, c.countBelowThreshold))
147146
.save();
148147
}
149148

@@ -165,7 +164,7 @@ private void publishLocInComplexFunctionMetricsForFile(InputFile inputFile, Sour
165164
context.<Double>newMeasure()
166165
.forMetric(FunctionComplexityMetrics.COMPLEX_FUNCTIONS_LOC_PERC)
167166
.on(inputFile)
168-
.withValue(calculatePercentual((int)locCount.countOverThreshold, (int)locCount.countBelowThreshold))
167+
.withValue(calculatePercentual(locCount.countOverThreshold, locCount.countBelowThreshold))
169168
.save();
170169
}
171170

@@ -206,7 +205,7 @@ private void publishLinesOfCodeInComplexFunctionMetrics(InputModule module, Sens
206205
private double calculatePercentual(int overThreshold, int belowThreshold){
207206
double total = (double)overThreshold + (double)belowThreshold;
208207
if (total > 0) {
209-
return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold);
208+
return (overThreshold * 100.0) / ((double)overThreshold + (double)belowThreshold);
210209
}
211210
else {
212211
return 0;

cxx-sensors/src/main/java/org/sonar/cxx/sensors/functionsize/CxxFunctionSizeSquidSensor.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@
2828
import org.sonar.api.utils.log.Logger;
2929
import org.sonar.api.utils.log.Loggers;
3030
import org.sonar.cxx.CxxLanguage;
31-
import static org.sonar.cxx.checks.TooManyLinesOfCodeInFunctionCheck.getNumberOfLine;
31+
import org.sonar.cxx.api.CxxMetric;
32+
3233
import org.sonar.cxx.parser.CxxGrammarImpl;
3334
import org.sonar.cxx.sensors.functioncomplexity.FunctionCount;
3435
import org.sonar.cxx.sensors.squid.SquidSensor;
@@ -71,9 +72,9 @@ public void init() {
7172
@Override
7273
public void leaveNode(AstNode node) {
7374
SourceFunction sourceFunction = (SourceFunction) getContext().peekSourceCode();
74-
SourceFile sourceFile = (SourceFile)sourceFunction.getAncestor(SourceFile.class);
75+
SourceFile sourceFile = sourceFunction.getAncestor(SourceFile.class);
7576

76-
int lineCount = getNumberOfLine(node);
77+
int lineCount = sourceFunction.getInt(CxxMetric.LINES_OF_CODE_IN_FUNCTION_BODY);
7778

7879
incrementFunctionByThresholdForProject(lineCount);
7980
incrementFunctionByThresholdForFile(sourceFile, lineCount);
@@ -166,7 +167,7 @@ private void publishLocInBigFunctionForProject(InputModule module, SensorContext
166167
private double calculatePercentual(int overThreshold, int belowThreshold){
167168
double total = (double)overThreshold + (double)belowThreshold;
168169
if (total > 0) {
169-
return ((float)overThreshold * 100.0) / ((float)overThreshold + (float)belowThreshold);
170+
return (overThreshold * 100.0) / ((double)overThreshold + (double)belowThreshold);
170171
}
171172
else {
172173
return 0;
@@ -184,7 +185,7 @@ private void publishBigFunctionMetrics(InputFile inputFile, SourceFile squidFile
184185
context.<Integer>newMeasure()
185186
.forMetric(FunctionSizeMetrics.BIG_FUNCTIONS)
186187
.on(inputFile)
187-
.withValue((int)c.countOverThreshold)
188+
.withValue(c.countOverThreshold)
188189
.save();
189190

190191
context.<Double>newMeasure()

cxx-squid/src/main/java/org/sonar/cxx/CxxAstScanner.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.sonar.cxx.visitors.CxxCharsetAwareVisitor;
3737
import org.sonar.cxx.visitors.CxxCognitiveComplexityVisitor;
3838
import org.sonar.cxx.visitors.CxxFileVisitor;
39+
import org.sonar.cxx.visitors.CxxLinesOfCodeInFunctionBodyVisitor;
3940
import org.sonar.cxx.visitors.CxxLinesOfCodeVisitor;
4041
import org.sonar.cxx.visitors.CxxParseErrorLoggerVisitor;
4142
import org.sonar.cxx.visitors.CxxPublicApiVisitor;
@@ -199,6 +200,7 @@ public SourceCode createSourceCode(SourceCode parentSourceCode, AstNode astNode)
199200
/* Metrics */
200201
builder.withSquidAstVisitor(new LinesVisitor<>(CxxMetric.LINES));
201202
builder.withSquidAstVisitor(new CxxLinesOfCodeVisitor<>(CxxMetric.LINES_OF_CODE));
203+
builder.withSquidAstVisitor(new CxxLinesOfCodeInFunctionBodyVisitor<>());
202204
builder.withSquidAstVisitor(new CxxPublicApiVisitor<>(CxxMetric.PUBLIC_API,
203205
CxxMetric.PUBLIC_UNDOCUMENTED_API)
204206
.withHeaderFileSuffixes(conf.getHeaderFileSuffixes()));

cxx-squid/src/main/java/org/sonar/cxx/api/CxxMetric.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public enum CxxMetric implements MetricDef {
2727
FILES,
2828
LINES,
2929
LINES_OF_CODE,
30+
LINES_OF_CODE_IN_FUNCTION_BODY,
3031
STATEMENTS,
3132
FUNCTIONS,
3233
CLASSES,
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Sonar C++ Plugin (Community)
3+
* Copyright (C) 2010-2018 SonarOpenCommunity
4+
* http://github.com/SonarOpenCommunity/sonar-cxx
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.cxx.visitors;
21+
22+
import java.util.List;
23+
24+
import org.sonar.cxx.api.CppPunctuator;
25+
import org.sonar.cxx.api.CxxMetric;
26+
import org.sonar.cxx.parser.CxxGrammarImpl;
27+
import org.sonar.squidbridge.SquidAstVisitor;
28+
29+
import com.sonar.sslr.api.AstNode;
30+
import com.sonar.sslr.api.AstVisitor;
31+
import com.sonar.sslr.api.Grammar;
32+
33+
/**
34+
* Visitor that computes the NCLOCs in function body, leading and trailing {} do not count
35+
*
36+
* @param <GRAMMAR>
37+
*/
38+
public class CxxLinesOfCodeInFunctionBodyVisitor<GRAMMAR extends Grammar> extends SquidAstVisitor<GRAMMAR>
39+
implements AstVisitor {
40+
41+
@Override
42+
public void init() {
43+
subscribeTo(CxxGrammarImpl.functionBody);
44+
}
45+
46+
@Override
47+
public void visitNode(AstNode node) {
48+
List<AstNode> allChilds = node.getDescendants(CxxGrammarImpl.statement, CppPunctuator.CURLBR_LEFT,
49+
CppPunctuator.CURLBR_RIGHT);
50+
int lines = 1;
51+
int firstLine = node.getTokenLine();
52+
if (allChilds != null && !allChilds.isEmpty()) {
53+
int previousLine = firstLine;
54+
for (AstNode child : allChilds) {
55+
int currentLine = child.getTokenLine();
56+
if (currentLine != previousLine) {
57+
lines++;
58+
previousLine = currentLine;
59+
}
60+
}
61+
}
62+
getContext().peekSourceCode().add(CxxMetric.LINES_OF_CODE_IN_FUNCTION_BODY, lines);
63+
}
64+
65+
}

cxx-squid/src/test/java/org/sonar/cxx/api/CxxMetricTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class CxxMetricTest {
2727
@Test
2828
public void test() {
2929
SoftAssertions softly = new SoftAssertions();
30-
softly.assertThat(CxxMetric.values()).hasSize(11);
30+
softly.assertThat(CxxMetric.values()).hasSize(12);
3131

3232
for (CxxMetric metric : CxxMetric.values()) {
3333
softly.assertThat(metric.getName()).isEqualTo(metric.name());

0 commit comments

Comments
 (0)