@iris-code/core 0.1.2 → 0.3.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/config.d.ts +14 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +48 -5
- package/dist/config.js.map +1 -1
- package/dist/fileNaming.d.ts +1 -0
- package/dist/fileNaming.d.ts.map +1 -1
- package/dist/fileNaming.js +29 -0
- package/dist/fileNaming.js.map +1 -1
- package/dist/guards.d.ts.map +1 -1
- package/dist/guards.js +44 -2
- package/dist/guards.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +45 -9
- package/dist/index.js.map +1 -1
- package/dist/java/analyser.d.ts +4 -0
- package/dist/java/analyser.d.ts.map +1 -0
- package/dist/java/analyser.js +394 -0
- package/dist/java/analyser.js.map +1 -0
- package/dist/java/lexer.d.ts +46 -0
- package/dist/java/lexer.d.ts.map +1 -0
- package/dist/java/lexer.js +198 -0
- package/dist/java/lexer.js.map +1 -0
- package/dist/languages.d.ts +2 -10
- package/dist/languages.d.ts.map +1 -1
- package/dist/languages.js +18 -35
- package/dist/languages.js.map +1 -1
- package/dist/registry.d.ts +39 -0
- package/dist/registry.d.ts.map +1 -0
- package/dist/registry.js +74 -0
- package/dist/registry.js.map +1 -0
- package/dist/rust/analyser.d.ts +26 -0
- package/dist/rust/analyser.d.ts.map +1 -0
- package/dist/rust/analyser.js +506 -0
- package/dist/rust/analyser.js.map +1 -0
- package/dist/rust/lexer.d.ts +39 -0
- package/dist/rust/lexer.d.ts.map +1 -0
- package/dist/rust/lexer.js +192 -0
- package/dist/rust/lexer.js.map +1 -0
- package/dist/secrets.d.ts.map +1 -1
- package/dist/secrets.js +357 -1
- package/dist/secrets.js.map +1 -1
- package/dist/sfc.d.ts.map +1 -1
- package/dist/sfc.js +4 -18
- package/dist/sfc.js.map +1 -1
- package/dist/types.d.ts +4 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.analyseJava = analyseJava;
|
|
4
|
+
const lines_1 = require("../lines");
|
|
5
|
+
const scoring_1 = require("../scoring");
|
|
6
|
+
const secrets_1 = require("../secrets");
|
|
7
|
+
const guards_1 = require("../guards");
|
|
8
|
+
const lexer_1 = require("./lexer");
|
|
9
|
+
const ZEROED_TS_METRICS = {
|
|
10
|
+
anyUsages: [], tsIgnoreCount: 0, tsExpectErrorCount: 0,
|
|
11
|
+
nonNullAssertions: 0, typeAssertions: 0, missingReturnTypes: 0,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* `.properties` and Spring's application.yml are MANIFESTS, not source.
|
|
15
|
+
*
|
|
16
|
+
* The C# port learned this the hard way: analysing a .csproj as code reported
|
|
17
|
+
* every `<LangVersion>12</LangVersion>` as a magic number on every .NET project.
|
|
18
|
+
* A properties file is key/value pairs, so the same would happen here - but a
|
|
19
|
+
* `spring.datasource.password` is the single most commonly committed Java
|
|
20
|
+
* credential, so these files are scanned for secrets and nothing else.
|
|
21
|
+
*/
|
|
22
|
+
function isManifest(filePath) {
|
|
23
|
+
return /\.properties$/i.test(filePath);
|
|
24
|
+
}
|
|
25
|
+
function emptyJavaSmells() {
|
|
26
|
+
return {
|
|
27
|
+
consoleLogs: [], todos: [], deepNesting: 0, longParameterLists: [],
|
|
28
|
+
magicNumbers: [], unusedVars: [], unusedFunctions: [], bareSuppressions: [],
|
|
29
|
+
duplicateBlocks: [], fileNamingViolations: [], evalUsage: [],
|
|
30
|
+
sqlConcatenation: [], insecureRandom: [], unsafeRegex: [],
|
|
31
|
+
hardcodedLocalhost: [], disabledTlsVerification: [], debugFlagsEnabled: [],
|
|
32
|
+
weakHashing: [], openRedirect: [],
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Lines that legitimately carry a literal number in Java: a `static final`
|
|
37
|
+
* constant, an annotation argument (`@Size(max = 200)`), or an enum member with
|
|
38
|
+
* an explicit value. Each of those IS the name for its number, which is exactly
|
|
39
|
+
* what the magic-number rule asks for.
|
|
40
|
+
*
|
|
41
|
+
* The C# analyser has had this since it shipped. Java went without it until the
|
|
42
|
+
* benchmark's negative fixture reported `SURCHARGE_MINOR_UNITS = 4750` - a
|
|
43
|
+
* named constant - as a magic number.
|
|
44
|
+
*/
|
|
45
|
+
const JAVA_MAGIC_NUMBER_EXEMPT_RE = /^\s*@|^\s*(?:(?:public|private|protected|static|final)\s+)*(?:static\s+)?final\s|^\s*[A-Z][A-Z0-9_]*\s*\(\s*[\d_,\s.]+\s*\)\s*,?\s*$|^\s*[A-Z][A-Z0-9_]*\s*=\s*[\d_.]+\s*,?\s*$/;
|
|
46
|
+
/**
|
|
47
|
+
* Method and constructor detection.
|
|
48
|
+
*
|
|
49
|
+
* Anchored to start-of-line OR a `{`/`}`/`;` on the same line, for the reason
|
|
50
|
+
* the C# port documented: a type collapsed onto one line reports no methods at
|
|
51
|
+
* all under a `^`-only anchor, and is then silently exempt from every
|
|
52
|
+
* length, parameter and nesting rule. All three boundary characters are needed
|
|
53
|
+
* because the match consumes its boundary.
|
|
54
|
+
*
|
|
55
|
+
* Requires a return type token, a name, a parameter list AND a body opener,
|
|
56
|
+
* which is what excludes `if`, `while`, `catch`, `switch` and object
|
|
57
|
+
* initialisers. `new Foo() {` is excluded by requiring the name not to follow
|
|
58
|
+
* `new`.
|
|
59
|
+
*/
|
|
60
|
+
const JAVA_METHOD_LINE_RE = /(?:(?:public|private|protected|static|final|abstract|synchronized|native|default|strictfp)\s+)*(?:<[^>]+>\s*)?(?:[\w$.<>,\[\]?\s]+\s+)?([A-Za-z_$][\w$]*)\s*\(([^)]*)\)\s*(?:throws\s+[\w$.,\s]+)?$/;
|
|
61
|
+
const JAVA_KEYWORDS = new Set([
|
|
62
|
+
'if', 'for', 'while', 'switch', 'catch', 'synchronized', 'try', 'do', 'else',
|
|
63
|
+
'return', 'new', 'record', 'enum', 'class', 'interface',
|
|
64
|
+
]);
|
|
65
|
+
function countParams(raw) {
|
|
66
|
+
const trimmed = raw.trim();
|
|
67
|
+
if (trimmed === '')
|
|
68
|
+
return 0;
|
|
69
|
+
// Generic arguments contain commas that are not parameter separators.
|
|
70
|
+
let depth = 0;
|
|
71
|
+
let count = 1;
|
|
72
|
+
for (const ch of trimmed) {
|
|
73
|
+
if (ch === '<' || ch === '(' || ch === '[')
|
|
74
|
+
depth++;
|
|
75
|
+
else if (ch === '>' || ch === ')' || ch === ']')
|
|
76
|
+
depth--;
|
|
77
|
+
else if (ch === ',' && depth === 0)
|
|
78
|
+
count++;
|
|
79
|
+
}
|
|
80
|
+
return count;
|
|
81
|
+
}
|
|
82
|
+
function detectJavaMethods(source, code = (0, lexer_1.javaCodeOnly)(source)) {
|
|
83
|
+
const methods = [];
|
|
84
|
+
let offset = 0;
|
|
85
|
+
let line = 1;
|
|
86
|
+
for (const rawLine of code.split('\n')) {
|
|
87
|
+
let segmentStart = 0;
|
|
88
|
+
let brace = rawLine.indexOf('{');
|
|
89
|
+
while (brace !== -1) {
|
|
90
|
+
const segment = rawLine.slice(segmentStart, brace);
|
|
91
|
+
const paren = segment.indexOf('(');
|
|
92
|
+
const prefix = segment.trimStart();
|
|
93
|
+
if (paren !== -1 &&
|
|
94
|
+
!prefix.startsWith('@') &&
|
|
95
|
+
!/^(?:if|for|while|switch|catch|try|else|do|new|class|interface|enum|record)\b/.test(prefix)) {
|
|
96
|
+
const match = JAVA_METHOD_LINE_RE.exec(prefix);
|
|
97
|
+
if (match) {
|
|
98
|
+
const name = match[1];
|
|
99
|
+
if (!JAVA_KEYWORDS.has(name)) {
|
|
100
|
+
const nameInSegment = segment.indexOf(name);
|
|
101
|
+
const start = offset + segmentStart + (nameInSegment >= 0 ? nameInSegment : 0);
|
|
102
|
+
const openIndex = offset + brace;
|
|
103
|
+
methods.push({
|
|
104
|
+
name,
|
|
105
|
+
line,
|
|
106
|
+
paramCount: countParams(match[2]),
|
|
107
|
+
start,
|
|
108
|
+
end: findBlockEnd(code, openIndex),
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
segmentStart = brace + 1;
|
|
114
|
+
brace = rawLine.indexOf('{', segmentStart);
|
|
115
|
+
}
|
|
116
|
+
offset += rawLine.length + 1;
|
|
117
|
+
line++;
|
|
118
|
+
}
|
|
119
|
+
return methods;
|
|
120
|
+
}
|
|
121
|
+
/** Index of the `}` closing the block whose `{` sits at `openIndex`. */
|
|
122
|
+
function findBlockEnd(code, openIndex) {
|
|
123
|
+
let depth = 0;
|
|
124
|
+
for (let i = openIndex; i < code.length; i++) {
|
|
125
|
+
if (code[i] === '{')
|
|
126
|
+
depth++;
|
|
127
|
+
else if (code[i] === '}') {
|
|
128
|
+
depth--;
|
|
129
|
+
if (depth === 0)
|
|
130
|
+
return i;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return code.length;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Third-party imports: everything outside the JDK.
|
|
137
|
+
*
|
|
138
|
+
* `java.*` and `javax.*` are the platform and present in nearly every file, so
|
|
139
|
+
* counting them would make the import count meaningless - the same reasoning
|
|
140
|
+
* that excludes `System.*` in C# while keeping `Microsoft.*`.
|
|
141
|
+
*/
|
|
142
|
+
function extractJavaImports(source, code = (0, lexer_1.stripJavaComments)(source)) {
|
|
143
|
+
const out = [];
|
|
144
|
+
// `[ \t]*`, NOT `\s*`. This is the exact defect SECURITY.md 1.4 records against
|
|
145
|
+
// `METHOD_RE` on 2026-08-04, reintroduced here: `\s` matches NEWLINES, so under
|
|
146
|
+
// /m the engine anchors at every line start, lets `\s*` swallow every following
|
|
147
|
+
// blank line to EOF, fails to find `import`, then backtracks one character at a
|
|
148
|
+
// time. O(n^2).
|
|
149
|
+
//
|
|
150
|
+
// Comment-blanked source is the worst input for it, because a blanked comment is
|
|
151
|
+
// a solid run of spaces and newlines - exactly what `\s*` devours. Measured
|
|
152
|
+
// 2026-08-16: a 0.71 MB file of javadoc took 9,974 ms, and 9,595 ms of that was
|
|
153
|
+
// inside this one regex. It quadrupled per doubling of input.
|
|
154
|
+
const re = /^[ \t]*import[ \t]+(static[ \t]+)?([\w$.]+(?:\.\*)?)[ \t]*;/gm;
|
|
155
|
+
let match;
|
|
156
|
+
while ((match = re.exec(code)) !== null) {
|
|
157
|
+
out.push({
|
|
158
|
+
name: match[2],
|
|
159
|
+
line: (0, lines_1.lineOf)(code, match.index),
|
|
160
|
+
isStatic: Boolean(match[1]),
|
|
161
|
+
isWildcard: match[2].endsWith('.*'),
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
return out;
|
|
165
|
+
}
|
|
166
|
+
function thirdPartyImports(imports) {
|
|
167
|
+
return imports
|
|
168
|
+
.filter(entry => !/^javax?\./.test(entry.name))
|
|
169
|
+
.map(entry => entry.name);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Unused imports. IN SCOPE for Java, unlike Ruby and C#.
|
|
173
|
+
*
|
|
174
|
+
* An import is a compile-time alias for a type name, Java has no extension
|
|
175
|
+
* methods, and javac itself warns on unused ones - so an unreferenced import
|
|
176
|
+
* genuinely does nothing. Three cases are excluded DELIBERATELY rather than
|
|
177
|
+
* guessed at:
|
|
178
|
+
*
|
|
179
|
+
* - WILDCARD imports cannot be judged at all and are skipped, never guessed.
|
|
180
|
+
* - STATIC imports bring in a bare method or constant name, so the search
|
|
181
|
+
* target is the final segment rather than a type.
|
|
182
|
+
* - JAVADOC references are real usage. `{@link Foo}` lives in a comment, so
|
|
183
|
+
* this is the ONE check here that must see comments. Running it on
|
|
184
|
+
* comment-stripped source would report a false positive on every documented
|
|
185
|
+
* codebase, and deleting the import would then break `javadoc`.
|
|
186
|
+
*/
|
|
187
|
+
function detectUnusedJavaImports(source, imports = extractJavaImports(source), code = (0, lexer_1.javaCodeOnly)(source)) {
|
|
188
|
+
if (imports.length === 0)
|
|
189
|
+
return [];
|
|
190
|
+
// Usage search runs on comment-stripped-but-string-blanked code PLUS the
|
|
191
|
+
// Javadoc comments, for the reason above.
|
|
192
|
+
const javadoc = (source.match(/\/\*\*[\s\S]*?\*\//g) ?? []).join('\n');
|
|
193
|
+
const body = code.replace(/^[ \t]*import[ \t]+[^;]+;/gm, '') + '\n' + javadoc;
|
|
194
|
+
const unused = [];
|
|
195
|
+
for (const entry of imports) {
|
|
196
|
+
if (entry.isWildcard)
|
|
197
|
+
continue;
|
|
198
|
+
const simpleName = entry.name.split('.').pop() ?? entry.name;
|
|
199
|
+
if (simpleName === '')
|
|
200
|
+
continue;
|
|
201
|
+
const used = new RegExp(`\\b${simpleName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\b`).test(body);
|
|
202
|
+
if (!used)
|
|
203
|
+
unused.push({ name: entry.name, line: entry.line });
|
|
204
|
+
}
|
|
205
|
+
return unused;
|
|
206
|
+
}
|
|
207
|
+
function detectJavaWarnings(source, methods, imports, config, code = (0, lexer_1.javaCodeOnly)(source)) {
|
|
208
|
+
const warnings = [];
|
|
209
|
+
const lines = source.split(String.fromCharCode(10));
|
|
210
|
+
// Severity is overridable per rule, the same as every other language.
|
|
211
|
+
const severity = (type, fallback) => config.severityOverrides[type] ?? fallback;
|
|
212
|
+
const warningThreshold = Math.round(config.fileLengthThreshold * 2 / 3);
|
|
213
|
+
if (lines.length > config.fileLengthThreshold) {
|
|
214
|
+
warnings.push({ type: 'file-too-long', message: `File is ${lines.length} lines (>${config.fileLengthThreshold})`, severity: severity('file-too-long', 'error'), line: 1 });
|
|
215
|
+
}
|
|
216
|
+
else if (lines.length > warningThreshold) {
|
|
217
|
+
warnings.push({ type: 'file-too-long', message: `File is ${lines.length} lines (>${warningThreshold})`, severity: severity('file-too-long', 'warning'), line: 1 });
|
|
218
|
+
}
|
|
219
|
+
for (const item of methods) {
|
|
220
|
+
const span = (0, lines_1.lineOf)(code, item.end) - item.line + 1;
|
|
221
|
+
const errorThreshold = config.functionLengthThreshold * 2;
|
|
222
|
+
if (span > errorThreshold) {
|
|
223
|
+
warnings.push({ type: 'function-too-long', message: `${item.name} is ~${span} lines (>${errorThreshold})`, severity: severity('function-too-long', 'error'), line: item.line });
|
|
224
|
+
}
|
|
225
|
+
else if (span > config.functionLengthThreshold) {
|
|
226
|
+
warnings.push({ type: 'function-too-long', message: `${item.name} is ~${span} lines (>${config.functionLengthThreshold})`, severity: severity('function-too-long', 'warning'), line: item.line });
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
if (methods.length > config.maxFunctionsPerFile) {
|
|
230
|
+
warnings.push({ type: 'too-many-functions', message: `${methods.length} methods in one file (>${config.maxFunctionsPerFile})`, severity: severity('too-many-functions', 'warning') });
|
|
231
|
+
}
|
|
232
|
+
if (imports.length > config.maxImportsPerFile) {
|
|
233
|
+
warnings.push({ type: 'too-many-imports', message: `${imports.length} third-party imports (>${config.maxImportsPerFile})`, severity: severity('too-many-imports', 'warning') });
|
|
234
|
+
}
|
|
235
|
+
return warnings;
|
|
236
|
+
}
|
|
237
|
+
function detectJavaSmells(source, methods, config, inTestFile, code = (0, lexer_1.javaCodeOnly)(source), withStrings = (0, lexer_1.stripJavaComments)(source)) {
|
|
238
|
+
const smells = emptyJavaSmells();
|
|
239
|
+
// Structural checks read string-blanked code so a construct quoted in a
|
|
240
|
+
// message is not a finding; content checks read comment-stripped source where
|
|
241
|
+
// string bodies survive. Getting these backwards is a false positive one way
|
|
242
|
+
// and a miss the other.
|
|
243
|
+
const pushLines = (re, target, haystack) => {
|
|
244
|
+
re.lastIndex = 0;
|
|
245
|
+
let match;
|
|
246
|
+
while ((match = re.exec(haystack)) !== null)
|
|
247
|
+
target.push({ line: (0, lines_1.lineOf)(haystack, match.index) });
|
|
248
|
+
};
|
|
249
|
+
// Debug output. System.out/err println is Java's console.log.
|
|
250
|
+
pushLines(/\bSystem\s*\.\s*(?:out|err)\s*\.\s*print(?:ln|f)?\s*\(/g, smells.consoleLogs, code);
|
|
251
|
+
// TODO/FIXME live in comments, so this reads the raw source.
|
|
252
|
+
const todoRe = /(?:\/\/|\*)\s*(TODO|FIXME|HACK|XXX)\b[:\s]*(.*)/gi;
|
|
253
|
+
let todo;
|
|
254
|
+
while ((todo = todoRe.exec(source)) !== null) {
|
|
255
|
+
smells.todos.push({ text: `${todo[1]}: ${todo[2].trim()}`.trim(), line: (0, lines_1.lineOf)(source, todo.index) });
|
|
256
|
+
}
|
|
257
|
+
for (const method of methods) {
|
|
258
|
+
if (method.paramCount > config.maxParameterCount) {
|
|
259
|
+
smells.longParameterLists.push({ name: method.name, paramCount: method.paramCount, line: method.line });
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
// Nesting measured RELATIVE to each method's own opening brace: Java's
|
|
263
|
+
// conventional brace style puts the method brace on the signature line, but
|
|
264
|
+
// measuring absolutely would still make a class member look one level deeper
|
|
265
|
+
// than the same code at file scope. The C# port hit exactly this.
|
|
266
|
+
let deepest = 0;
|
|
267
|
+
for (const method of methods) {
|
|
268
|
+
let depth = 0;
|
|
269
|
+
let peak = 0;
|
|
270
|
+
for (let i = method.start; i <= method.end && i < code.length; i++) {
|
|
271
|
+
if (code[i] === '{') {
|
|
272
|
+
depth++;
|
|
273
|
+
peak = Math.max(peak, depth);
|
|
274
|
+
}
|
|
275
|
+
else if (code[i] === '}')
|
|
276
|
+
depth--;
|
|
277
|
+
}
|
|
278
|
+
deepest = Math.max(deepest, Math.max(0, peak - 1));
|
|
279
|
+
}
|
|
280
|
+
smells.deepNesting = deepest;
|
|
281
|
+
const magicRe = /(?<![\w.])(-?\d{2,})(?![\w.])/g;
|
|
282
|
+
const codeLines = code.split('\n');
|
|
283
|
+
let magic;
|
|
284
|
+
while ((magic = magicRe.exec(code)) !== null) {
|
|
285
|
+
const value = magic[1];
|
|
286
|
+
if (['0', '1', '-1', '100', '1000'].includes(value))
|
|
287
|
+
continue;
|
|
288
|
+
const line = (0, lines_1.lineOf)(code, magic.index);
|
|
289
|
+
// A NAMED constant is not a magic number - naming it is the fix the rule
|
|
290
|
+
// asks for, so reporting it punishes the fix. C# has exempted this since it
|
|
291
|
+
// shipped; Java and Rust were missed, and the benchmark's negative fixtures
|
|
292
|
+
// are what surfaced it.
|
|
293
|
+
if (JAVA_MAGIC_NUMBER_EXEMPT_RE.test(codeLines[line - 1] ?? ''))
|
|
294
|
+
continue;
|
|
295
|
+
smells.magicNumbers.push({ value, line });
|
|
296
|
+
}
|
|
297
|
+
if (config.enableSecuritySmells) {
|
|
298
|
+
// NOTE: the catch-all and process-execution checks are NOT here any more.
|
|
299
|
+
// They were pushed into `evalUsage`, whose user-facing label is "eval() /
|
|
300
|
+
// exec() usage - arbitrary code execution risk". Every other language puts
|
|
301
|
+
// dynamic code evaluation there and nothing else, so `catch (Exception e)`
|
|
302
|
+
// arrived describing a defect it is not. They are now `catch-all-exception`
|
|
303
|
+
// (the SAME rule id C# already uses, since it is the same defect) and
|
|
304
|
+
// `process-execution`, emitted as warnings by detectJavaStructuralRules.
|
|
305
|
+
pushLines(/\b(?:executeQuery|executeUpdate|execute|prepareStatement)\s*\(\s*"[^"]*"\s*\+|\bcreateQuery\s*\(\s*"[^"]*"\s*\+/g, smells.sqlConcatenation, withStrings);
|
|
306
|
+
pushLines(/\bnew\s+Random\s*\(|\bMath\s*\.\s*random\s*\(/g, smells.insecureRandom, code);
|
|
307
|
+
pushLines(/\bMessageDigest\s*\.\s*getInstance\s*\(\s*"(?:MD5|SHA-?1)"/gi, smells.weakHashing, withStrings);
|
|
308
|
+
if (!inTestFile) {
|
|
309
|
+
pushLines(/(?:https?:\/\/)?(?:localhost|127\.0\.0\.1)(?::\d+)?/g, smells.hardcodedLocalhost, withStrings);
|
|
310
|
+
pushLines(/\b(?:debug|devMode|isDebug)\s*=\s*true\b/gi, smells.debugFlagsEnabled, withStrings);
|
|
311
|
+
}
|
|
312
|
+
pushLines(/\bsendRedirect\s*\(\s*(?:request\s*\.\s*getParameter|\w+\s*\+)/g, smells.openRedirect, code);
|
|
313
|
+
// TLS verification switched off: a TrustManager that validates nothing, or
|
|
314
|
+
// a hostname verifier that always returns true.
|
|
315
|
+
pushLines(/\bsetHostnameVerifier\s*\(|\bALLOW_ALL_HOSTNAME_VERIFIER\b|\bTrustAllCerts\b/g, smells.disabledTlsVerification, code);
|
|
316
|
+
}
|
|
317
|
+
return smells;
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* The two Java structural rules, as first-class warnings.
|
|
321
|
+
*
|
|
322
|
+
* Both were originally pushed into `codeSmells.evalUsage`, which reaches the
|
|
323
|
+
* user as "eval() / exec() usage - arbitrary code execution risk". Neither is
|
|
324
|
+
* that: a catch-all swallows errors, and spawning a process is command
|
|
325
|
+
* execution rather than dynamic code evaluation. Real ids give them a
|
|
326
|
+
* `severityOverrides` entry, an `iris-ignore` directive, and their own group in
|
|
327
|
+
* the Problems tab.
|
|
328
|
+
*
|
|
329
|
+
* `catch-all-exception` DELIBERATELY reuses the C# rule id rather than minting a
|
|
330
|
+
* Java-specific one. It is the same defect with the same fix, so one id means
|
|
331
|
+
* one severity override, one suppression directive and one docs entry covering
|
|
332
|
+
* both languages - and a team that sets it for a polyglot repo sets it once.
|
|
333
|
+
*/
|
|
334
|
+
function detectJavaStructuralRules(source, config, code = (0, lexer_1.javaCodeOnly)(source)) {
|
|
335
|
+
if (!config.enableSecuritySmells)
|
|
336
|
+
return [];
|
|
337
|
+
const warnings = [];
|
|
338
|
+
const severity = (type, fallback) => config.severityOverrides[type] ?? fallback;
|
|
339
|
+
const scan = (re, type, message, fallback) => {
|
|
340
|
+
re.lastIndex = 0;
|
|
341
|
+
let match;
|
|
342
|
+
while ((match = re.exec(code)) !== null) {
|
|
343
|
+
warnings.push({ type, message, severity: severity(type, fallback), line: (0, lines_1.lineOf)(code, match.index) });
|
|
344
|
+
}
|
|
345
|
+
};
|
|
346
|
+
// `catch (Exception e)` and `catch (Throwable t)`, including a multi-catch
|
|
347
|
+
// that ends in one of them. A specific type is deliberate handling and is not
|
|
348
|
+
// a finding - the same line C# draws with its `when (...)` filter.
|
|
349
|
+
scan(/\bcatch\s*\(\s*(?:final\s+)?(?:[\w.]+\s*\|\s*)*(?:java\.lang\.)?(?:Exception|Throwable)\s+\w+\s*\)/g, 'catch-all-exception', 'Catch a narrower exception type or preserve explicit handling context', 'warning');
|
|
350
|
+
scan(/\b(?:Runtime\s*\.\s*getRuntime\s*\(\s*\)\s*\.\s*exec|ProcessBuilder)\s*\(/g, 'process-execution', 'Spawning a process from application code; validate every argument and prefer a library call', 'warning');
|
|
351
|
+
return warnings;
|
|
352
|
+
}
|
|
353
|
+
function scoreJavaComplexity(source, codeLineCount, methods, imports, code = (0, lexer_1.javaCodeOnly)(source)) {
|
|
354
|
+
let score = 1;
|
|
355
|
+
const branches = (code.match(/\b(?:if|for|while|case|catch|switch)\b|&&|\|\||\?\s*[^:]+:/g) ?? []).length;
|
|
356
|
+
const density = codeLineCount > 0 ? methods.length / (codeLineCount / 50) : 0;
|
|
357
|
+
score += Math.min(3, Math.floor(density));
|
|
358
|
+
score += Math.min(3, Math.floor(branches / 10));
|
|
359
|
+
score += Math.min(2, Math.floor(imports.length / 12));
|
|
360
|
+
return Math.max(1, Math.min(10, score));
|
|
361
|
+
}
|
|
362
|
+
function analyseJava(source, config, filePath = '') {
|
|
363
|
+
const lines = source.split('\n');
|
|
364
|
+
const blankLines = lines.filter(line => line.trim() === '' || /^\s*(?:\/\/|\*|\/\*)/.test(line)).length;
|
|
365
|
+
const codeLineCount = lines.length - blankLines;
|
|
366
|
+
const manifest = isManifest(filePath);
|
|
367
|
+
const code = manifest ? '' : (0, lexer_1.javaCodeOnly)(source);
|
|
368
|
+
const withStrings = manifest ? '' : (0, lexer_1.stripJavaComments)(source);
|
|
369
|
+
const allMethods = manifest ? [] : detectJavaMethods(source, code);
|
|
370
|
+
const methods = config.ignoreFunctions.length > 0
|
|
371
|
+
? allMethods.filter(method => !config.ignoreFunctions.includes(method.name))
|
|
372
|
+
: allMethods;
|
|
373
|
+
const importEntries = manifest ? [] : extractJavaImports(source, withStrings);
|
|
374
|
+
const imports = manifest ? [] : thirdPartyImports(importEntries);
|
|
375
|
+
const warnings = manifest ? [] : [
|
|
376
|
+
...detectJavaWarnings(source, methods, imports, config, code),
|
|
377
|
+
...detectJavaStructuralRules(source, config, code),
|
|
378
|
+
];
|
|
379
|
+
const baseSmells = manifest
|
|
380
|
+
? emptyJavaSmells()
|
|
381
|
+
: detectJavaSmells(source, methods, config, (0, guards_1.isTestFile)(filePath), code, withStrings);
|
|
382
|
+
const hardcodedSecrets = (0, secrets_1.detectHardcodedSecrets)(source, config, 'java', filePath);
|
|
383
|
+
const codeSmells = { ...baseSmells, hardcodedSecrets };
|
|
384
|
+
return {
|
|
385
|
+
lineCount: lines.length, blankLines, codeLines: codeLineCount,
|
|
386
|
+
functions: methods.map(({ name, line }) => ({ name, line })),
|
|
387
|
+
thirdPartyImports: imports,
|
|
388
|
+
unusedImports: manifest ? [] : detectUnusedJavaImports(source, importEntries, code),
|
|
389
|
+
complexityScore: manifest ? 1 : scoreJavaComplexity(source, codeLineCount, methods, imports, code),
|
|
390
|
+
warnings, typeScriptMetrics: ZEROED_TS_METRICS, codeSmells,
|
|
391
|
+
healthScore: (0, scoring_1.computeHealthScore)(warnings, ZEROED_TS_METRICS, codeSmells, config),
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
//# sourceMappingURL=analyser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"analyser.js","sourceRoot":"","sources":["../../src/java/analyser.ts"],"names":[],"mappings":";;AAsZA,kCAiCC;AAtbD,oCAAiC;AACjC,wCAA+C;AAC/C,wCAAmD;AACnD,sCAAsC;AAItC,mCAAyD;AAEzD,MAAM,iBAAiB,GAAsB;IAC3C,SAAS,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC;IACtD,iBAAiB,EAAE,CAAC,EAAE,cAAc,EAAE,CAAC,EAAE,kBAAkB,EAAE,CAAC;CAC/D,CAAA;AAED;;;;;;;;GAQG;AACH,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,gBAAgB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AACxC,CAAC;AAED,SAAS,eAAe;IACtB,OAAO;QACL,WAAW,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,WAAW,EAAE,CAAC,EAAE,kBAAkB,EAAE,EAAE;QAClE,YAAY,EAAE,EAAE,EAAE,UAAU,EAAE,EAAE,EAAE,eAAe,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE;QAC3E,eAAe,EAAE,EAAE,EAAE,oBAAoB,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE;QAC5D,gBAAgB,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;QACzD,kBAAkB,EAAE,EAAE,EAAE,uBAAuB,EAAE,EAAE,EAAE,iBAAiB,EAAE,EAAE;QAC1E,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,EAAE;KAClC,CAAA;AACH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,2BAA2B,GAC/B,iLAAiL,CAAA;AAInL;;;;;;;;;;;;;GAaG;AACH,MAAM,mBAAmB,GACvB,qMAAqM,CAAA;AAEvM,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM;IAC5E,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW;CACxD,CAAC,CAAA;AAEF,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;IAC1B,IAAI,OAAO,KAAK,EAAE;QAAE,OAAO,CAAC,CAAA;IAC5B,sEAAsE;IACtE,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,MAAM,EAAE,IAAI,OAAO,EAAE,CAAC;QACzB,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,KAAK,EAAE,CAAA;aAC9C,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,GAAG;YAAE,KAAK,EAAE,CAAA;aACnD,IAAI,EAAE,KAAK,GAAG,IAAI,KAAK,KAAK,CAAC;YAAE,KAAK,EAAE,CAAA;IAC7C,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED,SAAS,iBAAiB,CAAC,MAAc,EAAE,IAAI,GAAG,IAAA,oBAAY,EAAC,MAAM,CAAC;IACpE,MAAM,OAAO,GAAiB,EAAE,CAAA;IAChC,IAAI,MAAM,GAAG,CAAC,CAAA;IACd,IAAI,IAAI,GAAG,CAAC,CAAA;IACZ,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,IAAI,YAAY,GAAG,CAAC,CAAA;QACpB,IAAI,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAChC,OAAO,KAAK,KAAK,CAAC,CAAC,EAAE,CAAC;YACpB,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;YAClD,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAClC,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAA;YAClC,IACE,KAAK,KAAK,CAAC,CAAC;gBACZ,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC;gBACvB,CAAC,8EAA8E,CAAC,IAAI,CAAC,MAAM,CAAC,EAC5F,CAAC;gBACD,MAAM,KAAK,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;gBAC9C,IAAI,KAAK,EAAE,CAAC;oBACV,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;oBACrB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;wBAC7B,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;wBAC3C,MAAM,KAAK,GAAG,MAAM,GAAG,YAAY,GAAG,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;wBAC9E,MAAM,SAAS,GAAG,MAAM,GAAG,KAAK,CAAA;wBAChC,OAAO,CAAC,IAAI,CAAC;4BACX,IAAI;4BACJ,IAAI;4BACJ,UAAU,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;4BACjC,KAAK;4BACL,GAAG,EAAE,YAAY,CAAC,IAAI,EAAE,SAAS,CAAC;yBACnC,CAAC,CAAA;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;YACD,YAAY,GAAG,KAAK,GAAG,CAAC,CAAA;YACxB,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;QAC5C,CAAC;QACD,MAAM,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,CAAA;QAC5B,IAAI,EAAE,CAAA;IACR,CAAC;IACD,OAAO,OAAO,CAAA;AAChB,CAAC;AAED,wEAAwE;AACxE,SAAS,YAAY,CAAC,IAAY,EAAE,SAAiB;IACnD,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,KAAK,IAAI,CAAC,GAAG,SAAS,EAAE,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;YAAE,KAAK,EAAE,CAAA;aACvB,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;YACzB,KAAK,EAAE,CAAA;YACP,IAAI,KAAK,KAAK,CAAC;gBAAE,OAAO,CAAC,CAAA;QAC3B,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,MAAM,CAAA;AACpB,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kBAAkB,CAAC,MAAc,EAAE,IAAI,GAAG,IAAA,yBAAiB,EAAC,MAAM,CAAC;IAC1E,MAAM,GAAG,GAA6E,EAAE,CAAA;IACxF,gFAAgF;IAChF,gFAAgF;IAChF,gFAAgF;IAChF,gFAAgF;IAChF,gBAAgB;IAChB,EAAE;IACF,iFAAiF;IACjF,4EAA4E;IAC5E,gFAAgF;IAChF,8DAA8D;IAC9D,MAAM,EAAE,GAAG,+DAA+D,CAAA;IAC1E,IAAI,KAA6B,CAAA;IACjC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QACxC,GAAG,CAAC,IAAI,CAAC;YACP,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC;YACd,IAAI,EAAE,IAAA,cAAM,EAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC;YAC/B,QAAQ,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;SACpC,CAAC,CAAA;IACJ,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,SAAS,iBAAiB,CAAC,OAA2B;IACpD,OAAO,OAAO;SACX,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;SAC9C,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;AAC7B,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,SAAS,uBAAuB,CAC9B,MAAc,EACd,OAAO,GAAG,kBAAkB,CAAC,MAAM,CAAC,EACpC,IAAI,GAAG,IAAA,oBAAY,EAAC,MAAM,CAAC;IAE3B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAA;IACnC,yEAAyE;IACzE,0CAA0C;IAC1C,MAAM,OAAO,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACtE,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC,GAAG,IAAI,GAAG,OAAO,CAAA;IAC7E,MAAM,MAAM,GAAmB,EAAE,CAAA;IACjC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,KAAK,CAAC,UAAU;YAAE,SAAQ;QAC9B,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC,IAAI,CAAA;QAC5D,IAAI,UAAU,KAAK,EAAE;YAAE,SAAQ;QAC/B,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,MAAM,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QAChG,IAAI,CAAC,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;IAChE,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC;AAED,SAAS,kBAAkB,CACzB,MAAc,EACd,OAAqB,EACrB,OAAiB,EACjB,MAAkB,EAClB,IAAI,GAAG,IAAA,oBAAY,EAAC,MAAM,CAAC;IAE3B,MAAM,QAAQ,GAAc,EAAE,CAAA;IAC9B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAA;IACnD,sEAAsE;IACtE,MAAM,QAAQ,GAAG,CAAC,IAAqB,EAAE,QAA6B,EAAuB,EAAE,CAC7F,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAA;IAC5C,MAAM,gBAAgB,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,mBAAmB,GAAG,CAAC,GAAG,CAAC,CAAC,CAAA;IAEvE,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,KAAK,CAAC,MAAM,YAAY,MAAM,CAAC,mBAAmB,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IAC5K,CAAC;SAAM,IAAI,KAAK,CAAC,MAAM,GAAG,gBAAgB,EAAE,CAAC;QAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,OAAO,EAAE,WAAW,KAAK,CAAC,MAAM,YAAY,gBAAgB,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;IACpK,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAA,cAAM,EAAC,IAAI,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,IAAI,GAAG,CAAC,CAAA;QACnD,MAAM,cAAc,GAAG,MAAM,CAAC,uBAAuB,GAAG,CAAC,CAAA;QACzD,IAAI,IAAI,GAAG,cAAc,EAAE,CAAC;YAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,QAAQ,IAAI,YAAY,cAAc,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,mBAAmB,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;QACjL,CAAC;aAAM,IAAI,IAAI,GAAG,MAAM,CAAC,uBAAuB,EAAE,CAAC;YACjD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,IAAI,QAAQ,IAAI,YAAY,MAAM,CAAC,uBAAuB,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,mBAAmB,EAAE,SAAS,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;QACnM,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,oBAAoB,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,0BAA0B,MAAM,CAAC,mBAAmB,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,EAAE,SAAS,CAAC,EAAE,CAAC,CAAA;IACvL,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;QAC9C,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,kBAAkB,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC,MAAM,0BAA0B,MAAM,CAAC,iBAAiB,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,kBAAkB,EAAE,SAAS,CAAC,EAAE,CAAC,CAAA;IACjL,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,gBAAgB,CACvB,MAAc,EACd,OAAqB,EACrB,MAAkB,EAClB,UAAmB,EACnB,IAAI,GAAG,IAAA,oBAAY,EAAC,MAAM,CAAC,EAC3B,WAAW,GAAG,IAAA,yBAAiB,EAAC,MAAM,CAAC;IAEvC,MAAM,MAAM,GAAG,eAAe,EAAE,CAAA;IAChC,wEAAwE;IACxE,8EAA8E;IAC9E,6EAA6E;IAC7E,wBAAwB;IACxB,MAAM,SAAS,GAAG,CAAC,EAAU,EAAE,MAA0B,EAAE,QAAgB,EAAQ,EAAE;QACnF,EAAE,CAAC,SAAS,GAAG,CAAC,CAAA;QAChB,IAAI,KAA6B,CAAA;QACjC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI;YAAE,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAA,cAAM,EAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACnG,CAAC,CAAA;IAED,8DAA8D;IAC9D,SAAS,CAAC,yDAAyD,EAAE,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;IAE9F,6DAA6D;IAC7D,MAAM,MAAM,GAAG,mDAAmD,CAAA;IAClE,IAAI,IAA4B,CAAA;IAChC,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,IAAA,cAAM,EAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;IACvG,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,iBAAiB,EAAE,CAAC;YACjD,MAAM,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;QACzG,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,4EAA4E;IAC5E,6EAA6E;IAC7E,kEAAkE;IAClE,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,KAAK,GAAG,CAAC,CAAA;QACb,IAAI,IAAI,GAAG,CAAC,CAAA;QACZ,KAAK,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,CAAC,IAAI,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACnE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAAC,KAAK,EAAE,CAAC;gBAAC,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAA;YAAC,CAAC;iBACzD,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,GAAG;gBAAE,KAAK,EAAE,CAAA;QACnC,CAAC;QACD,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,CAAC,WAAW,GAAG,OAAO,CAAA;IAE5B,MAAM,OAAO,GAAG,gCAAgC,CAAA;IAChD,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAClC,IAAI,KAA6B,CAAA;IACjC,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,CAAA;QACtB,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;YAAE,SAAQ;QAC7D,MAAM,IAAI,GAAG,IAAA,cAAM,EAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAA;QACtC,yEAAyE;QACzE,4EAA4E;QAC5E,4EAA4E;QAC5E,wBAAwB;QACxB,IAAI,2BAA2B,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;YAAE,SAAQ;QACzE,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,CAAC;IAED,IAAI,MAAM,CAAC,oBAAoB,EAAE,CAAC;QAChC,0EAA0E;QAC1E,0EAA0E;QAC1E,2EAA2E;QAC3E,2EAA2E;QAC3E,4EAA4E;QAC5E,sEAAsE;QACtE,yEAAyE;QACzE,SAAS,CAAC,kHAAkH,EAAE,MAAM,CAAC,gBAAgB,EAAE,WAAW,CAAC,CAAA;QACnK,SAAS,CAAC,gDAAgD,EAAE,MAAM,CAAC,cAAc,EAAE,IAAI,CAAC,CAAA;QACxF,SAAS,CAAC,8DAA8D,EAAE,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA;QAC1G,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,SAAS,CAAC,sDAAsD,EAAE,MAAM,CAAC,kBAAkB,EAAE,WAAW,CAAC,CAAA;YACzG,SAAS,CAAC,4CAA4C,EAAE,MAAM,CAAC,iBAAiB,EAAE,WAAW,CAAC,CAAA;QAChG,CAAC;QACD,SAAS,CAAC,iEAAiE,EAAE,MAAM,CAAC,YAAY,EAAE,IAAI,CAAC,CAAA;QACvG,2EAA2E;QAC3E,gDAAgD;QAChD,SAAS,CAAC,+EAA+E,EAAE,MAAM,CAAC,uBAAuB,EAAE,IAAI,CAAC,CAAA;IAClI,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,yBAAyB,CAAC,MAAc,EAAE,MAAkB,EAAE,IAAI,GAAG,IAAA,oBAAY,EAAC,MAAM,CAAC;IAChG,IAAI,CAAC,MAAM,CAAC,oBAAoB;QAAE,OAAO,EAAE,CAAA;IAC3C,MAAM,QAAQ,GAAc,EAAE,CAAA;IAC9B,MAAM,QAAQ,GAAG,CAAC,IAAqB,EAAE,QAA6B,EAAuB,EAAE,CAC7F,MAAM,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,QAAQ,CAAA;IAE5C,MAAM,IAAI,GAAG,CAAC,EAAU,EAAE,IAAqB,EAAE,OAAe,EAAE,QAA6B,EAAQ,EAAE;QACvG,EAAE,CAAC,SAAS,GAAG,CAAC,CAAA;QAChB,IAAI,KAA6B,CAAA;QACjC,OAAO,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACxC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,IAAA,cAAM,EAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;QACvG,CAAC;IACH,CAAC,CAAA;IAED,2EAA2E;IAC3E,8EAA8E;IAC9E,mEAAmE;IACnE,IAAI,CACF,qGAAqG,EACrG,qBAAqB,EACrB,uEAAuE,EACvE,SAAS,CACV,CAAA;IAED,IAAI,CACF,4EAA4E,EAC5E,mBAAmB,EACnB,6FAA6F,EAC7F,SAAS,CACV,CAAA;IAED,OAAO,QAAQ,CAAA;AACjB,CAAC;AAED,SAAS,mBAAmB,CAAC,MAAc,EAAE,aAAqB,EAAE,OAAqB,EAAE,OAAiB,EAAE,IAAI,GAAG,IAAA,oBAAY,EAAC,MAAM,CAAC;IACvI,IAAI,KAAK,GAAG,CAAC,CAAA;IACb,MAAM,QAAQ,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,6DAA6D,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAA;IACzG,MAAM,OAAO,GAAG,aAAa,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,aAAa,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IAC7E,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAA;IACzC,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,CAAA;IAC/C,KAAK,IAAI,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAA;IACrD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC,CAAA;AACzC,CAAC;AAED,SAAgB,WAAW,CAAC,MAAc,EAAE,MAAkB,EAAE,QAAQ,GAAG,EAAE;IAC3E,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,sBAAsB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAA;IACvG,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,GAAG,UAAU,CAAA;IAC/C,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,oBAAY,EAAC,MAAM,CAAC,CAAA;IACjD,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAA,yBAAiB,EAAC,MAAM,CAAC,CAAA;IAE7D,MAAM,UAAU,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;IAClE,MAAM,OAAO,GAAG,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC;QAC/C,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC5E,CAAC,CAAC,UAAU,CAAA;IACd,MAAM,aAAa,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAC7E,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAA;IAChE,MAAM,QAAQ,GAAG,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC/B,GAAG,kBAAkB,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC;QAC7D,GAAG,yBAAyB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC;KACnD,CAAA;IACD,MAAM,UAAU,GAAG,QAAQ;QACzB,CAAC,CAAC,eAAe,EAAE;QACnB,CAAC,CAAC,gBAAgB,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAA,mBAAU,EAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;IACtF,MAAM,gBAAgB,GAAG,IAAA,gCAAsB,EAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;IACjF,MAAM,UAAU,GAAe,EAAE,GAAG,UAAU,EAAE,gBAAgB,EAAE,CAAA;IAElE,OAAO;QACL,SAAS,EAAE,KAAK,CAAC,MAAM,EAAE,UAAU,EAAE,SAAS,EAAE,aAAa;QAC7D,SAAS,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5D,iBAAiB,EAAE,OAAO;QAC1B,aAAa,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,uBAAuB,CAAC,MAAM,EAAE,aAAa,EAAE,IAAI,CAAC;QACnF,eAAe,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,mBAAmB,CAAC,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;QAClG,QAAQ,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,UAAU;QAC1D,WAAW,EAAE,IAAA,4BAAkB,EAAC,QAAQ,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,CAAC;KACjF,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Java lexical layer, in its own module because TWO callers need it: the
|
|
3
|
+
* Java analyser (every structural rule) and `detectParseErrorReason` in
|
|
4
|
+
* guards.ts (the delimiter balance check that decides whether a file is
|
|
5
|
+
* analysed at all).
|
|
6
|
+
*
|
|
7
|
+
* That second caller is why this exists before any rule. C# shipped a defect
|
|
8
|
+
* where the everyday verbatim string `@"C:\logs\"` read as unterminated, every
|
|
9
|
+
* brace after it landed at the wrong depth, and the file came back a parse
|
|
10
|
+
* error with every finding zeroed - and a zeroed file is indistinguishable from
|
|
11
|
+
* a clean one. Java has two constructs with that same shape.
|
|
12
|
+
*
|
|
13
|
+
* Both modes are LENGTH- and LINE-PRESERVING, so a finding's offset still maps
|
|
14
|
+
* to its native line with no remapping layer that could drift.
|
|
15
|
+
*
|
|
16
|
+
* Handled: line and block comments (NOT nested - Java, unlike Rust, does not
|
|
17
|
+
* allow that), text blocks, regular strings, char literals, and unicode escapes.
|
|
18
|
+
*
|
|
19
|
+
* THE UNICODE ESCAPE IS THE JAVA-SPECIFIC TRAP. javac translates `\uXXXX`
|
|
20
|
+
* BEFORE tokenising, so `\u0022` is a real double quote everywhere in the file -
|
|
21
|
+
* including inside what looks like a comment. `// text \u000A code()` is a
|
|
22
|
+
* comment followed by live code, because the escape decodes to a line
|
|
23
|
+
* terminator. Nothing in the other eight languages behaves this way.
|
|
24
|
+
*
|
|
25
|
+
* NOT handled here, deliberately: generics. `Map<String, List<Integer>>` needs
|
|
26
|
+
* care in the analyser's signature patterns, but angle brackets are not counted
|
|
27
|
+
* by the delimiter balance check and do not open or close a literal, so they are
|
|
28
|
+
* not a lexical concern.
|
|
29
|
+
*/
|
|
30
|
+
/**
|
|
31
|
+
* Decodes `\uXXXX` the way javac does, before anything else runs.
|
|
32
|
+
*
|
|
33
|
+
* Length and line count are preserved rather than truly decoded: the escape is
|
|
34
|
+
* six or more characters and its value is one, so the value is emitted followed
|
|
35
|
+
* by padding spaces. An escape that decodes to a line terminator is blanked
|
|
36
|
+
* entirely instead - honouring it would ADD a line and break the guarantee that
|
|
37
|
+
* findings report native line numbers, which is worth more than being exactly
|
|
38
|
+
* right about a construct that appears almost exclusively in puzzles.
|
|
39
|
+
*/
|
|
40
|
+
export declare function decodeJavaUnicodeEscapes(source: string): string;
|
|
41
|
+
export declare function transformJava(source: string, blankStrings: boolean): string;
|
|
42
|
+
/** Comments blanked, string contents intact. */
|
|
43
|
+
export declare function stripJavaComments(source: string): string;
|
|
44
|
+
/** Comments AND string contents blanked: the input for anything structural. */
|
|
45
|
+
export declare function javaCodeOnly(source: string): string;
|
|
46
|
+
//# sourceMappingURL=lexer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lexer.d.ts","sourceRoot":"","sources":["../../src/java/lexer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAaH;;;;;;;;;GASG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAwB/D;AAED,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,OAAO,GAAG,MAAM,CA+F3E;AAED,gDAAgD;AAChD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,+EAA+E;AAC/E,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEnD"}
|