Skip to content

Commit 33a37ab

Browse files
add description to patterns (#5)
* add description to patterns * add md files * update category * update description * update parameters description * add multiple tests * update test * update * update * update * update * update docker image * try another approach * update test * update * final
1 parent deeeea7 commit 33a37ab

17 files changed

+334
-20
lines changed

.codacyrc

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,15 +20,25 @@
2020
"value": 8
2121
}
2222
]
23+
},
24+
{
25+
"patternId": "ccn-minor",
26+
"parameters": [
27+
{
28+
"name": "threshold",
29+
"value": 0
30+
}
31+
]
2332
}
2433
]
2534
}
2635
],
2736
"files": [
28-
"/src/dist/src/configCreator.js",
29-
"/src/dist/src/engineImpl.js",
30-
"/src/dist/src/lizard.js",
31-
"/src/dist/src/lizardIssuesEngine.js",
32-
"/src/dist/src/logging.js"
37+
"/dist/src/configCreator.js",
38+
"/dist/src/engineImpl.js",
39+
"/dist/src/lizard.js",
40+
"/dist/src/lizardIssuesEngine.js",
41+
"/dist/src/lizardMetricsEngine.js",
42+
"/dist/src/logging.js"
3343
]
3444
}

Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
FROM node:lts-alpine3.20 as builder
1+
FROM node:lts-alpine3.21 as builder
22

33
COPY package.json package-lock.json ./
44
COPY src src
@@ -9,7 +9,7 @@ COPY tsconfig.json ./
99
RUN npm install &&\
1010
npm run build
1111

12-
FROM python:3.9-alpine3.20
12+
FROM python:3.9-alpine3.21
1313

1414
RUN pip install lizard &&\
1515
apk add --no-cache nodejs &&\

docs/description/ccn-critical.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Critical Cyclomatic Complexity control
2+
3+
Check the Cyclomatic Complexity value of a function or logic block. If the threshold is not met, raise a Critical issue. The default threshold is 10.

docs/description/ccn-medium.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Medium Cyclomatic Complexity control
2+
3+
Check the Cyclomatic Complexity value of a function or logic block. If the threshold is not met, raise a Medium issue. The default threshold is 7.

docs/description/ccn-minor.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Minor Cyclomatic Complexity control
2+
3+
Check the Cyclomatic Complexity value of a function or logic block. If the threshold is not met, raise a Minor issue. The default threshold is 4.

docs/description/description.json

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
[
2+
{
3+
"parameters": [
4+
{
5+
"name": "threshold",
6+
"description": "The minimum value upon the issue is being triggered."
7+
}
8+
],
9+
"patternId": "nloc-minor",
10+
"title": "Minor NLOC control - Number of Lines of Code (without comments)",
11+
"description": "Check the number of lines of code (without comments) in a function. If the threshold is not met, raise a Minor issue. The default threshold is 20.",
12+
"timeToFix": 5
13+
},
14+
{
15+
"parameters": [
16+
{
17+
"name": "threshold",
18+
"description": "The minimum value upon the issue is being triggered."
19+
}
20+
],
21+
"patternId": "nloc-medium",
22+
"title": "Medium NLOC control - Number of Lines of Code (without comments)",
23+
"description": "Check the number of lines of code (without comments) in a function. If the threshold is not met, raise a Medium issue. The default threshold is 50.",
24+
"timeToFix": 5
25+
},
26+
{
27+
"parameters": [
28+
{
29+
"name": "threshold",
30+
"description": "The minimum value upon the issue is being triggered."
31+
}
32+
],
33+
"patternId": "nloc-critical",
34+
"title": "Critical NLOC control - Number of Lines of Code (without comments)",
35+
"description": "Check the number of lines of code (without comments) in a function or logic block. If the threshold is not met, raise a Critical issue. The default threshold is 100.",
36+
"timeToFix": 5
37+
},
38+
{
39+
"parameters": [
40+
{
41+
"name": "threshold",
42+
"description": "The minimum value upon the issue is being triggered."
43+
}
44+
],
45+
"patternId": "ccn-minor",
46+
"title": "Minor Cyclomatic Complexity control",
47+
"description": "Check the Cyclomatic Complexity value of a function or logic block. If the threshold is not met, raise a Minor issue. The default threshold is 4.",
48+
"timeToFix": 5
49+
},
50+
{
51+
"parameters": [
52+
{
53+
"name": "threshold",
54+
"description": "The minimum value upon the issue is being triggered."
55+
}
56+
],
57+
"patternId": "ccn-medium",
58+
"title": "Medium Cyclomatic Complexity control",
59+
"description": "Check the Cyclomatic Complexity value of a function or logic block. If the threshold is not met, raise a Medium issue. The default threshold is 7.",
60+
"timeToFix": 5
61+
},
62+
{
63+
"parameters": [
64+
{
65+
"name": "threshold",
66+
"description": "The minimum value upon the issue is being triggered."
67+
}
68+
],
69+
"patternId": "ccn-critical",
70+
"title": "Critical Cyclomatic Complexity control",
71+
"description": "Check the Cyclomatic Complexity value of a function or logic block. If the threshold is not met, raise a Critical issue. The default threshold is 10.",
72+
"timeToFix": 5
73+
},
74+
{
75+
"parameters": [
76+
{
77+
"name": "threshold",
78+
"description": "The minimum value upon the issue is being triggered."
79+
}
80+
],
81+
"patternId": "parameter-count-minor",
82+
"title": "Minor Parameter count control",
83+
"description": "Check the number of parameters sent to a function. If the threshold is not met, raise a Minor issue. The default threshold is 3.",
84+
"timeToFix": 5
85+
},
86+
{
87+
"parameters": [
88+
{
89+
"name": "threshold",
90+
"description": "The minimum value upon the issue is being triggered."
91+
}
92+
],
93+
"patternId": "parameter-count-medium",
94+
"title": "Medium Parameter count control",
95+
"description": "Check the number of parameters sent to a function. If the threshold is not met, raise a Medium issue. The default threshold is 5.",
96+
"timeToFix": 5
97+
},
98+
{
99+
"parameters": [
100+
{
101+
"name": "threshold",
102+
"description": "The minimum value upon the issue is being triggered."
103+
}
104+
],
105+
"patternId": "parameter-count-critical",
106+
"title": "Critical Parameter count control",
107+
"description": "Check the number of parameters sent to a function. If the threshold is not met, raise a Critical issue. The default threshold is 9.",
108+
"timeToFix": 5
109+
}
110+
]

docs/description/nloc-critical.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Critical NLOC control - Number of Lines of Code (without comments)
2+
3+
Check the number of lines of code (without comments) in a function or logic block. If the threshold is not met, raise a Critical issue. The default threshold is 100.

docs/description/nloc-medium.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Medium NLOC control - Number of Lines of Code (without comments)
2+
3+
Check the number of lines of code (without comments) in a function. If the threshold is not met, raise a Medium issue. The default threshold is 50.

docs/description/nloc-minor.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Minor NLOC control - Number of Lines of Code (without comments)
2+
3+
Check the number of lines of code (without comments) in a function. If the threshold is not met, raise a Minor issue. The default threshold is 20.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Critical Parameter count control
2+
3+
Check the number of parameters sent to a function. If the threshold is not met, raise a Critical issue. The default threshold is 9.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Medium Parameter count control
2+
3+
Check the number of parameters sent to a function. If the threshold is not met, raise a Medium issue. The default threshold is 5.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Minor Parameter count control
2+
3+
Check the number of parameters sent to a function. If the threshold is not met, raise a Minor issue. The default threshold is 3.
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<module name="root">
2+
<module name="ccn-minor">
3+
<property name="threshold" value="1" />
4+
</module>
5+
<module name="ccn-medium">
6+
<property name="threshold" value="7" />
7+
</module>
8+
<module name="ccn-critical">
9+
<property name="threshold" value="10" />
10+
</module>
11+
<module name="nloc-minor">
12+
<property name="threshold" value="20" />
13+
</module>
14+
<module name="nloc-medium">
15+
<property name="threshold" value="50" />
16+
</module>
17+
<module name="nloc-critical">
18+
<property name="threshold" value="100" />
19+
</module>
20+
<module name="parameter-count-minor">
21+
<property name="threshold" value="3" />
22+
</module>
23+
<module name="parameter-count-medium">
24+
<property name="threshold" value="5" />
25+
</module>
26+
<module name="parameter-count-critical">
27+
<property name="threshold" value="9" />
28+
</module>
29+
</module>
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<checkstyle version="4.3">
3+
<file name="all-patterns.ts">
4+
<error source="ccn-minor" line="42" message="Method (anonymous) has a cyclomatic complexity of 3 (limit is 1)" severity="info" />
5+
</file>
6+
</checkstyle>
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
import { exec } from "child_process"
2+
import fs from "fs"
3+
4+
import { LizardOptions } from "./configCreator"
5+
6+
export interface LizardMethodResult {
7+
"name": string;
8+
"fromLine": number;
9+
"toLine": number;
10+
"file": string;
11+
"nloc": number;
12+
"ccn": number;
13+
"params": number;
14+
"tokens": number;
15+
}
16+
17+
export interface LizardFileResult {
18+
"file": string;
19+
"nloc": number;
20+
"maxCcn": number;
21+
"averageNloc": number;
22+
"averageCcn": number;
23+
"averageTokens": number;
24+
"methodsCount": number;
25+
}
26+
27+
export interface LizardResults {
28+
"methods": LizardMethodResult[];
29+
"files": LizardFileResult[];
30+
}
31+
32+
export const runLizardCommand = (
33+
options: LizardOptions
34+
): Promise<LizardResults> => {
35+
// create a file with the list of files to analyze
36+
const filesList = options.files.join("\n")
37+
const filesListPath = "/codacy/filesList.txt"
38+
fs.writeFileSync(filesListPath, filesList)
39+
40+
// run lizard command
41+
return new Promise((resolve, reject) => {
42+
exec(`lizard -f ${filesListPath}`, (error, stdout, stderr) => {
43+
if (error) {
44+
reject(error)
45+
}
46+
if (stderr) {
47+
reject(stderr)
48+
}
49+
50+
resolve(parseLizardResults(stdout))
51+
})
52+
})
53+
}
54+
55+
const parseLizardResults = (output: string): LizardResults => {
56+
// NOTE: lizard supports generating the output in XML or CSV format, but both results lack some information
57+
// (files are not listed for the CSV output, and only starting line is included for the XML output); so the best
58+
// option is to parse the plain text output
59+
60+
// parse the output in an array of lines
61+
const lines = output.split("\n")
62+
63+
const results: LizardResults = {
64+
"methods": [],
65+
"files": []
66+
}
67+
68+
let isMethodSection = false
69+
let isFileSection = false
70+
71+
lines.forEach(line => {
72+
line = line.trim()
73+
74+
if (line.startsWith("===")) {
75+
isMethodSection = false
76+
isFileSection = false
77+
}
78+
if (line.startsWith("===") || line.startsWith("---") || line === "" || line.includes("file analyzed")) return
79+
80+
if (line.includes("NLOC CCN token PARAM length location")) {
81+
isMethodSection = true
82+
return
83+
}
84+
85+
if (line.includes("NLOC Avg.NLOC AvgCCN Avg.token function_cnt file")) {
86+
isFileSection = true
87+
return
88+
}
89+
90+
if (isMethodSection) {
91+
const lineSplitted = line.replaceAll(/\s+|@/g, " ")
92+
.trim()
93+
.split(" ")
94+
if (lineSplitted.length != 8) return
95+
const [nloc, ccn, tokens, params, , name, fromToLine, file] = lineSplitted
96+
const [fromLine, toLine] = fromToLine.split("-")
97+
98+
results.methods.push({
99+
"name": name,
100+
"fromLine": parseInt(fromLine),
101+
"toLine": parseInt(toLine),
102+
"file": file,
103+
"nloc": parseInt(nloc),
104+
"ccn": parseInt(ccn),
105+
"params": parseInt(params),
106+
"tokens": parseInt(tokens)
107+
})
108+
}
109+
110+
if (isFileSection) {
111+
const lineSplitted = line.replaceAll(/\s+/g, " ")
112+
.trim()
113+
.split(" ")
114+
if (lineSplitted.length != 6) return
115+
const [nloc, avgNloc, avgCcn, avgTokens, methodsCount, file] = lineSplitted
116+
117+
results.files.push({
118+
file,
119+
"nloc": parseInt(nloc),
120+
"maxCcn": results.methods
121+
.filter((m) => m.file === file)
122+
.reduce((max, m) => Math.max(m.ccn, max), 0),
123+
"averageNloc": parseFloat(avgNloc),
124+
"averageCcn": parseFloat(avgCcn),
125+
"averageTokens": parseFloat(avgTokens),
126+
"methodsCount": parseInt(methodsCount)
127+
})
128+
}
129+
})
130+
131+
return results
132+
}

0 commit comments

Comments
 (0)