@codacy/tools-jackson 0.3.0 → 0.5.0
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/dist/index.js +115 -37
- package/dist/metadata.d.ts +13 -0
- package/dist/metadata.js +39 -0
- package/package.json +13 -3
package/dist/index.js
CHANGED
|
@@ -38,20 +38,27 @@ var import_tooling = require("@codacy/tooling");
|
|
|
38
38
|
// src/adapter.ts
|
|
39
39
|
var import_promises = __toESM(require("fs/promises"));
|
|
40
40
|
var import_path = __toESM(require("path"));
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var
|
|
44
|
-
|
|
45
|
-
id: TOOL_ID,
|
|
41
|
+
|
|
42
|
+
// src/metadata.ts
|
|
43
|
+
var descriptor = {
|
|
44
|
+
id: "jackson",
|
|
46
45
|
displayName: "Jackson Linter",
|
|
47
46
|
preferredVersion: "1.0.0",
|
|
48
|
-
compatibleVersions: ">=1.0.0",
|
|
49
|
-
website: "https://github.com/FasterXML/jackson-core",
|
|
50
47
|
languages: ["JSON"],
|
|
51
48
|
filePatterns: ["**/*.json"],
|
|
52
49
|
supportedOS: ["linux", "darwin", "win32"],
|
|
53
50
|
supportedArch: ["x64", "arm64"],
|
|
54
|
-
supportedRunners: ["local", "container"]
|
|
51
|
+
supportedRunners: ["local", "container"]
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// src/adapter.ts
|
|
55
|
+
var TOOL_ID = "jackson";
|
|
56
|
+
var PATTERN_PARSE_ERROR = `${TOOL_ID}_parse-error`;
|
|
57
|
+
var PATTERN_DUPLICATE_KEYS = `${TOOL_ID}_duplicate-keys`;
|
|
58
|
+
var adapter = {
|
|
59
|
+
...descriptor,
|
|
60
|
+
compatibleVersions: ">=1.0.0",
|
|
61
|
+
website: "https://github.com/FasterXML/jackson-core",
|
|
55
62
|
prerequisites: [],
|
|
56
63
|
/**
|
|
57
64
|
* Always available — this adapter uses only Node's built-in JSON.parse.
|
|
@@ -104,32 +111,49 @@ var adapter = {
|
|
|
104
111
|
const startedAt = /* @__PURE__ */ new Date();
|
|
105
112
|
const issues = [];
|
|
106
113
|
const errors = [];
|
|
107
|
-
if (codacyConfig.patterns.length === 0) {
|
|
108
|
-
ctx.logger.info("Skipping analysis: no patterns enabled", { toolId: TOOL_ID });
|
|
109
|
-
const completedAt2 = /* @__PURE__ */ new Date();
|
|
110
|
-
return {
|
|
111
|
-
metadata: {
|
|
112
|
-
startedAt: startedAt.toISOString(),
|
|
113
|
-
completedAt: completedAt2.toISOString(),
|
|
114
|
-
durationMs: completedAt2.getTime() - startedAt.getTime()
|
|
115
|
-
},
|
|
116
|
-
issues,
|
|
117
|
-
errors,
|
|
118
|
-
summary: {
|
|
119
|
-
toolId: TOOL_ID,
|
|
120
|
-
status: "success",
|
|
121
|
-
issueCount: 0,
|
|
122
|
-
errorCount: 0,
|
|
123
|
-
durationMs: completedAt2.getTime() - startedAt.getTime(),
|
|
124
|
-
filesAnalyzed: ctx.targetFiles.length
|
|
125
|
-
}
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
114
|
const enabledPatterns = new Set(codacyConfig.patterns.map((p) => p.patternId));
|
|
129
115
|
const checkParseError = enabledPatterns.has(PATTERN_PARSE_ERROR);
|
|
130
116
|
const checkDuplicateKeys = enabledPatterns.has(PATTERN_DUPLICATE_KEYS);
|
|
117
|
+
let rootReal;
|
|
118
|
+
try {
|
|
119
|
+
rootReal = await import_promises.default.realpath(ctx.repositoryRoot);
|
|
120
|
+
} catch (err) {
|
|
121
|
+
errors.push({
|
|
122
|
+
toolId: TOOL_ID,
|
|
123
|
+
phase: "toolInvoke",
|
|
124
|
+
kind: "FileReadError",
|
|
125
|
+
message: `Cannot resolve repository root: ${err instanceof Error ? err.message : String(err)}`,
|
|
126
|
+
level: "error"
|
|
127
|
+
});
|
|
128
|
+
return buildResult(startedAt, /* @__PURE__ */ new Date(), issues, errors, ctx.targetFiles.length);
|
|
129
|
+
}
|
|
131
130
|
for (const relPath of ctx.targetFiles) {
|
|
132
131
|
const absPath = import_path.default.resolve(ctx.repositoryRoot, relPath);
|
|
132
|
+
const relToRoot = import_path.default.relative(ctx.repositoryRoot, absPath);
|
|
133
|
+
if (relToRoot === ".." || relToRoot.startsWith(`..${import_path.default.sep}`) || import_path.default.isAbsolute(relToRoot)) {
|
|
134
|
+
errors.push({
|
|
135
|
+
toolId: TOOL_ID,
|
|
136
|
+
phase: "toolInvoke",
|
|
137
|
+
kind: "FileReadError",
|
|
138
|
+
message: `Refusing path outside repository root: ${relPath}`,
|
|
139
|
+
level: "warning",
|
|
140
|
+
filePath: relPath
|
|
141
|
+
});
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const fileReal = await import_promises.default.realpath(absPath).catch(() => null);
|
|
145
|
+
const realRelative = fileReal ? import_path.default.relative(rootReal, fileReal) : null;
|
|
146
|
+
if (realRelative !== null && (realRelative === ".." || realRelative.startsWith(`..${import_path.default.sep}`) || import_path.default.isAbsolute(realRelative))) {
|
|
147
|
+
errors.push({
|
|
148
|
+
toolId: TOOL_ID,
|
|
149
|
+
phase: "toolInvoke",
|
|
150
|
+
kind: "FileReadError",
|
|
151
|
+
message: `Refusing path outside repository root: ${relPath}`,
|
|
152
|
+
level: "warning",
|
|
153
|
+
filePath: relPath
|
|
154
|
+
});
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
133
157
|
let content;
|
|
134
158
|
try {
|
|
135
159
|
content = await import_promises.default.readFile(absPath, "utf-8");
|
|
@@ -144,14 +168,15 @@ var adapter = {
|
|
|
144
168
|
});
|
|
145
169
|
continue;
|
|
146
170
|
}
|
|
147
|
-
|
|
148
|
-
|
|
171
|
+
const strippedContent = stripJsonComments(content);
|
|
172
|
+
let syntaxValid = true;
|
|
173
|
+
if (checkParseError || checkDuplicateKeys) {
|
|
149
174
|
try {
|
|
150
|
-
JSON.parse(
|
|
175
|
+
JSON.parse(strippedContent);
|
|
151
176
|
} catch (err) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const { line, column } = extractPosition(err.message,
|
|
177
|
+
syntaxValid = false;
|
|
178
|
+
if (checkParseError && err instanceof SyntaxError) {
|
|
179
|
+
const { line, column } = extractPosition(err.message, strippedContent);
|
|
155
180
|
const lines = content.split("\n");
|
|
156
181
|
const lineContent = lines[line - 1] ?? "";
|
|
157
182
|
issues.push({
|
|
@@ -168,8 +193,8 @@ var adapter = {
|
|
|
168
193
|
}
|
|
169
194
|
}
|
|
170
195
|
}
|
|
171
|
-
if (checkDuplicateKeys &&
|
|
172
|
-
const duplicates = findDuplicateKeys(
|
|
196
|
+
if (checkDuplicateKeys && syntaxValid) {
|
|
197
|
+
const duplicates = findDuplicateKeys(strippedContent);
|
|
173
198
|
const lines = content.split("\n");
|
|
174
199
|
for (const dup of duplicates) {
|
|
175
200
|
const lineContent = lines[dup.line - 1] ?? "";
|
|
@@ -213,6 +238,59 @@ var adapter = {
|
|
|
213
238
|
};
|
|
214
239
|
}
|
|
215
240
|
};
|
|
241
|
+
function stripJsonComments(source) {
|
|
242
|
+
const len = source.length;
|
|
243
|
+
const result = new Array(len);
|
|
244
|
+
let i = 0;
|
|
245
|
+
while (i < len) {
|
|
246
|
+
const ch = source[i];
|
|
247
|
+
if (ch === '"') {
|
|
248
|
+
result[i] = ch;
|
|
249
|
+
i++;
|
|
250
|
+
while (i < len) {
|
|
251
|
+
const sc = source[i];
|
|
252
|
+
result[i] = sc;
|
|
253
|
+
i++;
|
|
254
|
+
if (sc === "\\" && i < len) {
|
|
255
|
+
result[i] = source[i];
|
|
256
|
+
i++;
|
|
257
|
+
} else if (sc === '"') {
|
|
258
|
+
break;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
continue;
|
|
262
|
+
}
|
|
263
|
+
if (ch === "/" && i + 1 < len && source[i + 1] === "*") {
|
|
264
|
+
result[i] = " ";
|
|
265
|
+
result[i + 1] = " ";
|
|
266
|
+
i += 2;
|
|
267
|
+
while (i < len) {
|
|
268
|
+
if (source[i] === "*" && i + 1 < len && source[i + 1] === "/") {
|
|
269
|
+
result[i] = " ";
|
|
270
|
+
result[i + 1] = " ";
|
|
271
|
+
i += 2;
|
|
272
|
+
break;
|
|
273
|
+
}
|
|
274
|
+
result[i] = source[i] === "\n" ? "\n" : " ";
|
|
275
|
+
i++;
|
|
276
|
+
}
|
|
277
|
+
continue;
|
|
278
|
+
}
|
|
279
|
+
if (ch === "/" && i + 1 < len && source[i + 1] === "/") {
|
|
280
|
+
result[i] = " ";
|
|
281
|
+
result[i + 1] = " ";
|
|
282
|
+
i += 2;
|
|
283
|
+
while (i < len && source[i] !== "\n") {
|
|
284
|
+
result[i] = " ";
|
|
285
|
+
i++;
|
|
286
|
+
}
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
result[i] = ch;
|
|
290
|
+
i++;
|
|
291
|
+
}
|
|
292
|
+
return result.join("");
|
|
293
|
+
}
|
|
216
294
|
function extractPosition(message, source) {
|
|
217
295
|
const posMatch = message.match(/position (\d+)/);
|
|
218
296
|
if (posMatch) {
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { AdapterDescriptor } from '@codacy/tooling';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Lightweight adapter descriptor for lazy loading.
|
|
5
|
+
*
|
|
6
|
+
* This module contains only plain-data metadata fields and has zero heavy
|
|
7
|
+
* imports (no patterns.json, no runtime utilities). The CLI imports this
|
|
8
|
+
* at startup for adapter registration without loading the full adapter module.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
declare const descriptor: AdapterDescriptor;
|
|
12
|
+
|
|
13
|
+
export { descriptor };
|
package/dist/metadata.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/metadata.ts
|
|
21
|
+
var metadata_exports = {};
|
|
22
|
+
__export(metadata_exports, {
|
|
23
|
+
descriptor: () => descriptor
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(metadata_exports);
|
|
26
|
+
var descriptor = {
|
|
27
|
+
id: "jackson",
|
|
28
|
+
displayName: "Jackson Linter",
|
|
29
|
+
preferredVersion: "1.0.0",
|
|
30
|
+
languages: ["JSON"],
|
|
31
|
+
filePatterns: ["**/*.json"],
|
|
32
|
+
supportedOS: ["linux", "darwin", "win32"],
|
|
33
|
+
supportedArch: ["x64", "arm64"],
|
|
34
|
+
supportedRunners: ["local", "container"]
|
|
35
|
+
};
|
|
36
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
37
|
+
0 && (module.exports = {
|
|
38
|
+
descriptor
|
|
39
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codacy/tools-jackson",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Jackson Linter adapter — pure TypeScript JSON syntax validator",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"dist"
|
|
9
9
|
],
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@codacy/tooling": "0.
|
|
11
|
+
"@codacy/tooling": "0.5.0"
|
|
12
12
|
},
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"author": "Codacy <support@codacy.com> (https://www.codacy.com)",
|
|
@@ -21,8 +21,18 @@
|
|
|
21
21
|
"engines": {
|
|
22
22
|
"node": ">=20.0.0"
|
|
23
23
|
},
|
|
24
|
+
"exports": {
|
|
25
|
+
".": {
|
|
26
|
+
"types": "./dist/index.d.ts",
|
|
27
|
+
"default": "./dist/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./metadata": {
|
|
30
|
+
"types": "./dist/metadata.d.ts",
|
|
31
|
+
"default": "./dist/metadata.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
24
34
|
"scripts": {
|
|
25
|
-
"build": "tsup src/index.ts --format cjs --dts --clean",
|
|
35
|
+
"build": "tsup src/index.ts src/metadata.ts --format cjs --dts --clean",
|
|
26
36
|
"test": "vitest run",
|
|
27
37
|
"lint": "eslint src/",
|
|
28
38
|
"clean": "rm -rf dist",
|