npm-groovy-lint 9.4.1 → 10.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +39 -2
- package/README.md +54 -28
- package/lib/.groovylintrc-all.json +393 -394
- package/lib/.groovylintrc-format.json +2 -0
- package/lib/codenarc-caller.js +7 -3
- package/lib/codenarc-factory.js +77 -14
- package/lib/example/RuleSet-All.groovy +413 -417
- package/lib/example/SampleFileSmall.groovy +3 -3
- package/lib/example/SampleFileSmallFixed.txt +4 -4
- package/lib/example/SampleFileSmallFormatted.txt +4 -4
- package/lib/groovy-lint-rules.js +2 -0
- package/lib/groovy-lint.js +5 -3
- package/lib/index.js +5 -1
- package/lib/java/CodeNarc-3.1.0.jar +0 -0
- package/lib/java/CodeNarcServer.jar +0 -0
- package/lib/java/GMetrics-2.1.0.jar +0 -0
- package/lib/java/{log4j-api-2.17.1.jar → log4j-api-2.18.0.jar} +0 -0
- package/lib/java/{log4j-core-2.17.1.jar → log4j-core-2.18.0.jar} +0 -0
- package/lib/java/{log4j-slf4j-impl-2.17.1.jar → log4j-slf4j-impl-2.18.0.jar} +0 -0
- package/lib/options.js +30 -15
- package/lib/output.js +1 -3
- package/lib/rules/DuplicateNumberLiteral.js +21 -0
- package/lib/rules/DuplicateStringLiteral.js +21 -0
- package/lib/rules/MethodParameterTypeRequired.js +21 -0
- package/lib/rules/MisorderedStaticImports.js +2 -2
- package/lib/rules/NoDef.js +14 -0
- package/lib/rules/SimpleDateFormatMissingLocale.js +14 -0
- package/lib/rules/SpaceAfterMethodCallName.js +30 -0
- package/lib/rules/SpaceInsideParentheses.js +73 -0
- package/lib/rules/UnnecessaryPublicModifier.js +13 -0
- package/lib/rules/VariableTypeRequired.js +36 -0
- package/lib/utils.js +2 -2
- package/package.json +4 -8
- package/lib/java/CodeNarc-2.2.0.jar +0 -0
- package/lib/java/gmetrics-1.1.jar +0 -0
|
@@ -29,6 +29,7 @@
|
|
|
29
29
|
"formatting.SpaceAfterComma": {},
|
|
30
30
|
"formatting.SpaceAfterFor": {},
|
|
31
31
|
"formatting.SpaceAfterIf": {},
|
|
32
|
+
"formatting.SpaceAfterMethodCallName": {},
|
|
32
33
|
"formatting.SpaceAfterOpeningBrace": {},
|
|
33
34
|
"formatting.SpaceAfterSemicolon": {},
|
|
34
35
|
"formatting.SpaceAfterSwitch": {},
|
|
@@ -38,6 +39,7 @@
|
|
|
38
39
|
"formatting.SpaceAroundOperator": {},
|
|
39
40
|
"formatting.SpaceBeforeClosingBrace": {},
|
|
40
41
|
"formatting.SpaceBeforeOpeningBrace": {},
|
|
42
|
+
"formatting.SpaceInsideParentheses": {},
|
|
41
43
|
"formatting.TrailingWhitespace": {},
|
|
42
44
|
"unnecessary.UnnecessaryGString": {},
|
|
43
45
|
"unnecessary.UnnecessarySemicolon": {}
|
package/lib/codenarc-caller.js
CHANGED
|
@@ -39,7 +39,7 @@ class CodeNarcCaller {
|
|
|
39
39
|
rootPath: __dirname,
|
|
40
40
|
mainClass: "org.codenarc.CodeNarc",
|
|
41
41
|
classPath:
|
|
42
|
-
"java/CodeNarc-
|
|
42
|
+
"java/CodeNarc-3.1.0.jar:java/groovy/lib/groovy-3.0.9.jar:java/groovy/lib/groovy-templates-3.0.9.jar:java/groovy/lib/groovy-xml-3.0.9.jar:java/groovy/lib/groovy-json-3.0.9.jar:java/groovy/lib/groovy-ant-3.0.9.jar:java/groovy/lib/ant-1.10.11.jar:java/groovy/lib/ant-launcher-1.10.11.jar:java/slf4j-api-1.7.9.jar:java/log4j-slf4j-impl-2.18.0.jar:java/log4j-api-2.18.0.jar:java/log4j-core-2.18.0.jar:java/GMetrics-2.1.0.jar:java/*"
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
45
|
|
|
@@ -60,7 +60,10 @@ class CodeNarcCaller {
|
|
|
60
60
|
// Remove "" around values because they won't get thru system command line parser
|
|
61
61
|
const codeNarcArgsForServer = this.codenarcArgs.map(codeNarcArg => {
|
|
62
62
|
if (codeNarcArg.includes('="') || codeNarcArg.includes(':"')) {
|
|
63
|
-
codeNarcArg = codeNarcArg
|
|
63
|
+
codeNarcArg = codeNarcArg
|
|
64
|
+
.replace('="', "=")
|
|
65
|
+
.replace(':"', ":")
|
|
66
|
+
.replace(/ /g, "%20");
|
|
64
67
|
codeNarcArg = codeNarcArg.substring(0, codeNarcArg.length - 1);
|
|
65
68
|
}
|
|
66
69
|
return codeNarcArg;
|
|
@@ -76,7 +79,8 @@ class CodeNarcCaller {
|
|
|
76
79
|
codeNarcIncludes: this.execOpts.codeNarcIncludes,
|
|
77
80
|
codeNarcExcludes: this.execOpts.codeNarcExcludes,
|
|
78
81
|
parse: this.options.parse !== false && this.execOpts.onlyCodeNarc === false ? true : false,
|
|
79
|
-
file: this.execOpts.groovyFileName
|
|
82
|
+
file: this.execOpts.groovyFileName || null,
|
|
83
|
+
fileList: this.execOpts.inputFileList || null,
|
|
80
84
|
requestKey: this.execOpts.requestKey || null
|
|
81
85
|
},
|
|
82
86
|
timeout: 600000
|
package/lib/codenarc-factory.js
CHANGED
|
@@ -18,6 +18,8 @@ const npmGroovyLintRules = getNpmGroovyLintRules();
|
|
|
18
18
|
const CODENARC_TMP_FILENAME_BASE = "codeNarcTmpDir_";
|
|
19
19
|
const CODENARC_WWW_BASE = "https://codenarc.github.io/CodeNarc";
|
|
20
20
|
|
|
21
|
+
const defaultFilesPattern = ["*.groovy", "*.gvy", "Jenkinsfile", "*.gradle", "*.nf"];
|
|
22
|
+
|
|
21
23
|
// Convert NPM-groovy-lint into codeNarc arguments
|
|
22
24
|
// Create temporary files if necessary
|
|
23
25
|
async function prepareCodeNarcCall(options) {
|
|
@@ -25,6 +27,7 @@ async function prepareCodeNarcCall(options) {
|
|
|
25
27
|
|
|
26
28
|
let cnPath = options.path;
|
|
27
29
|
let cnFiles = options.files;
|
|
30
|
+
const positionalArgs = options._ || [];
|
|
28
31
|
|
|
29
32
|
// If source option, create a temporary Groovy file
|
|
30
33
|
if (options.source) {
|
|
@@ -59,9 +62,6 @@ async function prepareCodeNarcCall(options) {
|
|
|
59
62
|
// Create ruleSet groovy file if necessary
|
|
60
63
|
options.rulesets = await buildRuleSets(options);
|
|
61
64
|
|
|
62
|
-
// Build ruleSet & file CodeNarc arguments
|
|
63
|
-
let defaultFilesPattern = "**/*.groovy,**/*.gvy,**/Jenkinsfile,**/*.gradle,**/*.nf";
|
|
64
|
-
|
|
65
65
|
// RuleSets codeNarc args
|
|
66
66
|
if (options.rulesets && options.rulesets.startsWith("{")) {
|
|
67
67
|
// JSON format
|
|
@@ -72,32 +72,76 @@ async function prepareCodeNarcCall(options) {
|
|
|
72
72
|
result.codenarcArgs.push(`-rulesetfiles=${rulesetFileArgs}`);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
// Default file patterns
|
|
76
|
+
let filePatterns = defaultFilesPattern.map(filePattern => `**/${filePattern}`).join(",");
|
|
77
|
+
|
|
78
|
+
// Build codenarc arguments from eslint-like formatted positional arguments
|
|
79
|
+
if (positionalArgs.length > 0) {
|
|
80
|
+
if (options.ext && options.ext.length > 0) {
|
|
81
|
+
filePatterns = `/**/*.{` + options.extensions.map(ext => ext.replace(/^\./u, "")) + "}";
|
|
82
|
+
}
|
|
83
|
+
const fileList = [];
|
|
84
|
+
const patternsFinal = positionalArgs
|
|
85
|
+
.filter(Boolean)
|
|
86
|
+
.map(pathname => {
|
|
87
|
+
let finalPattern = path.normalize(pathname).replace(/\\/gu, "/");
|
|
88
|
+
// Directory: convert into ant pattern
|
|
89
|
+
const resolvedPath = path.resolve(cnPath, pathname);
|
|
90
|
+
if (directoryExists(resolvedPath)) {
|
|
91
|
+
finalPattern = "**/" + path.normalize(pathname.replace(/[/\\]$/u, "")).replace(/\\/gu, "/") + filePatterns;
|
|
92
|
+
}
|
|
93
|
+
// Absolute or cwd - relative path file
|
|
94
|
+
if (fs.existsSync(finalPattern)) {
|
|
95
|
+
const absolutePath = path.resolve(finalPattern).replace(/\\/gu, "/");
|
|
96
|
+
const relativePath = path.relative(process.cwd(), path.resolve(finalPattern)).replace(/\\/gu, "/");
|
|
97
|
+
fileList.push(absolutePath);
|
|
98
|
+
finalPattern = "**/" + path.normalize(relativePath.replace(/[/\\]$/u, "")).replace(/\\/gu, "/");
|
|
99
|
+
}
|
|
100
|
+
// Relative with codeNardBaseDir
|
|
101
|
+
else if (fs.existsSync(path.join(result.codeNarcBaseDir, finalPattern))) {
|
|
102
|
+
const relativePath = path.relative(process.cwd(), path.join(result.codeNarcBaseDir, finalPattern)).replace(/\\/gu, "/");
|
|
103
|
+
fileList.push(relativePath);
|
|
104
|
+
finalPattern = "**/" + path.normalize(relativePath.replace(/[/\\]$/u, "")).replace(/\\/gu, "/");
|
|
105
|
+
}
|
|
106
|
+
// Directory or ant pattern
|
|
107
|
+
return finalPattern;
|
|
108
|
+
})
|
|
109
|
+
.join(",");
|
|
110
|
+
result.codenarcArgs.push(`-includes="${patternsFinal}"`);
|
|
111
|
+
result.codeNarcIncludes = patternsFinal;
|
|
112
|
+
result.inputFileList = fileList;
|
|
113
|
+
}
|
|
75
114
|
// Matching files pattern(s)
|
|
76
|
-
if (cnFiles) {
|
|
115
|
+
else if (cnFiles) {
|
|
77
116
|
const normalizedCnFiles = cnFiles.replace(/^"(.*)"$/, "$1");
|
|
78
|
-
result.codenarcArgs.push(`-includes
|
|
117
|
+
result.codenarcArgs.push(`-includes="${normalizedCnFiles}"`);
|
|
79
118
|
result.codeNarcIncludes = normalizedCnFiles;
|
|
80
119
|
} else {
|
|
81
120
|
// If files not sent, use defaultFilesPattern, guessed from options.rulesets value
|
|
82
|
-
result.codenarcArgs.push(`-includes
|
|
83
|
-
result.codeNarcIncludes =
|
|
121
|
+
result.codenarcArgs.push(`-includes="${filePatterns}"`);
|
|
122
|
+
result.codeNarcIncludes = filePatterns;
|
|
84
123
|
}
|
|
85
124
|
|
|
86
125
|
// Ignore pattern
|
|
87
126
|
if (options.ignorepattern) {
|
|
88
|
-
result.codenarcArgs.push(`-excludes
|
|
127
|
+
result.codenarcArgs.push(`-excludes="${options.ignorepattern}"`);
|
|
89
128
|
result.codeNarcExcludes = options.ignorepattern;
|
|
90
129
|
}
|
|
91
130
|
|
|
92
131
|
// Output
|
|
93
132
|
result.output = options.output.replace(/^"(.*)"$/, "$1");
|
|
94
|
-
if (
|
|
133
|
+
if (
|
|
134
|
+
["txt", "json", "sarif", "none"].includes(result.output) ||
|
|
95
135
|
result.output.endsWith(".txt") ||
|
|
96
136
|
result.output.endsWith(".sarif") ||
|
|
97
|
-
result.output.endsWith(".json")
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
137
|
+
result.output.endsWith(".json")
|
|
138
|
+
) {
|
|
139
|
+
result.outputType = result.output.endsWith(".txt")
|
|
140
|
+
? "txt"
|
|
141
|
+
: result.output.endsWith(".json")
|
|
142
|
+
? "json"
|
|
143
|
+
: result.output.endsWith(".sarif")
|
|
144
|
+
? "sarif"
|
|
101
145
|
: result.output;
|
|
102
146
|
result.codenarcArgs.push(`-report=json:stdout`);
|
|
103
147
|
} else if (["html", "xml"].includes(result.output.split(".").pop())) {
|
|
@@ -253,7 +297,7 @@ async function parseCodeNarcResult(options, codeNarcBaseDir, codeNarcJsonResult,
|
|
|
253
297
|
const evaluatedVars = evaluateVariables(errRule.variables, errItem.msg, { verbose: options.verbose });
|
|
254
298
|
const errLine = allLines[errItem.line - 1];
|
|
255
299
|
const range = evaluateRange(errItem, errRule, evaluatedVars, errLine, allLines, { verbose: options.verbose });
|
|
256
|
-
if (range) {
|
|
300
|
+
if (range && range.start.character > -1) {
|
|
257
301
|
errItem.range = range;
|
|
258
302
|
}
|
|
259
303
|
}
|
|
@@ -347,6 +391,10 @@ async function buildRuleSets(options) {
|
|
|
347
391
|
? ruleOptions
|
|
348
392
|
: ruleFromConfig;
|
|
349
393
|
const ruleDef = buildCodeNarcRule(ruleName, mergedRuleConfig);
|
|
394
|
+
// If rule has been sent as argument, enable it by default
|
|
395
|
+
if (ruleDef.enabled === false) {
|
|
396
|
+
ruleDef.enabled = true;
|
|
397
|
+
}
|
|
350
398
|
return ruleDef;
|
|
351
399
|
});
|
|
352
400
|
}
|
|
@@ -385,6 +433,10 @@ async function buildRuleSets(options) {
|
|
|
385
433
|
delete rule.ruleName;
|
|
386
434
|
ruleSetJson[ruleName] = rule;
|
|
387
435
|
}
|
|
436
|
+
// Remove UnnecessarySubstring as it is no longer in CodeNarc v3
|
|
437
|
+
if (ruleSetJson["UnnecessarySubstring"] != null) {
|
|
438
|
+
delete ruleSetJson["UnnecessarySubstring"];
|
|
439
|
+
}
|
|
388
440
|
return JSON.stringify(ruleSetJson);
|
|
389
441
|
}
|
|
390
442
|
|
|
@@ -428,4 +480,15 @@ async function manageDeleteTmpFiles(tmpGroovyFileName) {
|
|
|
428
480
|
}
|
|
429
481
|
}
|
|
430
482
|
|
|
483
|
+
function directoryExists(resolvedPath) {
|
|
484
|
+
try {
|
|
485
|
+
return fs.statSync(resolvedPath).isDirectory();
|
|
486
|
+
} catch (error) {
|
|
487
|
+
if (error && (error.code === "ENOENT" || error.code === "ENOTDIR")) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
throw error;
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
431
494
|
module.exports = { prepareCodeNarcCall, parseCodeNarcResult, manageDeleteTmpFiles };
|