Skip to content

Commit 836a79d

Browse files
committed
Improve metric NCLOC to consider whitespace and comment only lines
> Lines of code (ncloc): The number of physical lines that contain at least one character which is neither a whitespace nor a tabulation nor part of a comment. https://docs.sonarsource.com/sonarqube/latest/user-guide/metric-definitions/
1 parent 98c7b44 commit 836a79d

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

src/main/java/com/premiumminds/sonar/postgres/PostgresSqlSensor.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -64,12 +64,6 @@ public void execute(SensorContext context) {
6464
LOGGER.warn("Analysis cancelled");
6565
}
6666

67-
context.<Integer>newMeasure()
68-
.on(file)
69-
.withValue(file.lines())
70-
.forMetric(CoreMetrics.NCLOC)
71-
.save();
72-
7367
try {
7468
PostgreSqlFile postgreSqlFile = new PostgreSqlFile(file);
7569
parseContents(context, postgreSqlFile);
@@ -135,6 +129,23 @@ private void scanContents(SensorContext context, PostgreSqlFile file) throws Inv
135129
RULE_IDENTIFIER_MAX_LENGTH);
136130
});
137131

132+
final var ncloc = scanResult.getTokensList()
133+
.stream()
134+
.filter(st -> !st.getToken().equals(Token.SQL_COMMENT))
135+
.filter(st -> !st.getToken().equals(Token.C_COMMENT))
136+
.map(st -> {
137+
final TextRange textRange = file.convertAbsoluteOffsetsToTextRange(st.getStart(), st.getEnd());
138+
return textRange.start().line();
139+
})
140+
.distinct()
141+
.count();
142+
143+
context.<Integer>newMeasure()
144+
.on(file.getInputFile())
145+
.withValue((int) ncloc)
146+
.forMetric(CoreMetrics.NCLOC)
147+
.save();
148+
138149
final var nclocData = scanResult.getTokensList()
139150
.stream()
140151
.map(st -> {

src/test/java/com/premiumminds/sonar/postgres/PostgresSqlSensorTest.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import static com.premiumminds.sonar.postgres.PostgresSqlRulesDefinition.RULE_SETTING_NOT_NULLABLE_FIELD;
4646
import static com.premiumminds.sonar.postgres.PostgresSqlRulesDefinition.RULE_VACUUM_FULL;
4747
import static org.junit.jupiter.api.Assertions.assertEquals;
48-
import static org.junit.jupiter.api.Assertions.assertNull;
4948
import static org.junit.jupiter.api.Assertions.assertTrue;
5049
import static org.sonar.api.measures.CoreMetrics.NCLOC;
5150
import static org.sonar.api.measures.CoreMetrics.NCLOC_DATA;
@@ -129,13 +128,33 @@ void metricsNcloc() {
129128
createFile(contextTester, "file1.sql", "SELECT 1;\r\nSELECT 2;\r\nSELECT 3;");
130129
createFile(contextTester, "file2.sql", "SELECT 'Évora 1';\nSELECT 'Évora 2';\nSELECT 'Évora 3';");
131130
createFile(contextTester, "file3.sql", "INSERT INTO foo VALUES ('éééééééééééé'), ('a');");
131+
createFile(contextTester, "file4.sql", "--comment\nSELECT 1;");
132+
createFile(contextTester, "file5.sql", "\n" +
133+
" select bar from foo;;\n" +
134+
" \n" +
135+
" select \n" +
136+
" -- some comment\n" +
137+
" bar2\n" +
138+
" ,\n" +
139+
" baz2\n" +
140+
" /* some other comment */\n" +
141+
" from foo2;\n" +
142+
"\n" +
143+
"COMMENT ON TABLE mytable IS 'This is my table.';\n" +
144+
"\n" +
145+
"create table foo (\n" +
146+
" like bar\n" +
147+
" including comments\n" +
148+
");\n");
132149

133150
PostgresSqlSensor sensor = getPostgresSqlSensor();
134151
sensor.execute(contextTester);
135152

136153
assertEquals(3, contextTester.measure(":file1.sql", NCLOC).value());
137154
assertEquals(3, contextTester.measure(":file2.sql", NCLOC).value());
138155
assertEquals(1, contextTester.measure(":file3.sql", NCLOC).value());
156+
assertEquals(1, contextTester.measure(":file4.sql", NCLOC).value());
157+
assertEquals(11, contextTester.measure(":file5.sql", NCLOC).value());
139158
}
140159

141160
@Test

0 commit comments

Comments
 (0)