@rigour-labs/core 3.0.2 → 3.0.4
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/gates/deprecated-apis.d.ts +55 -0
- package/dist/gates/deprecated-apis.js +724 -0
- package/dist/gates/deprecated-apis.test.d.ts +1 -0
- package/dist/gates/deprecated-apis.test.js +288 -0
- package/dist/gates/hallucinated-imports.d.ts +79 -13
- package/dist/gates/hallucinated-imports.js +434 -50
- package/dist/gates/hallucinated-imports.test.js +707 -31
- package/dist/gates/phantom-apis.d.ts +77 -0
- package/dist/gates/phantom-apis.js +675 -0
- package/dist/gates/phantom-apis.test.d.ts +1 -0
- package/dist/gates/phantom-apis.test.js +320 -0
- package/dist/gates/runner.js +37 -15
- package/dist/gates/test-quality.d.ts +67 -0
- package/dist/gates/test-quality.js +512 -0
- package/dist/gates/test-quality.test.d.ts +1 -0
- package/dist/gates/test-quality.test.js +312 -0
- package/dist/templates/index.js +31 -1
- package/dist/types/index.d.ts +348 -0
- package/dist/types/index.js +33 -0
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
const mockFindFiles = vi.hoisted(() => vi.fn());
|
|
3
|
+
const mockReadFile = vi.hoisted(() => vi.fn());
|
|
4
|
+
vi.mock('../utils/scanner.js', () => ({
|
|
5
|
+
FileScanner: { findFiles: mockFindFiles },
|
|
6
|
+
}));
|
|
7
|
+
vi.mock('fs-extra', () => ({
|
|
8
|
+
default: {
|
|
9
|
+
readFile: mockReadFile,
|
|
10
|
+
pathExists: vi.fn().mockResolvedValue(false),
|
|
11
|
+
pathExistsSync: vi.fn().mockReturnValue(false),
|
|
12
|
+
readFileSync: vi.fn().mockReturnValue(''),
|
|
13
|
+
readJson: vi.fn().mockResolvedValue(null),
|
|
14
|
+
readdirSync: vi.fn().mockReturnValue([]),
|
|
15
|
+
},
|
|
16
|
+
}));
|
|
17
|
+
import { DeprecatedApisGate } from './deprecated-apis.js';
|
|
18
|
+
describe('DeprecatedApisGate — Node.js Security', () => {
|
|
19
|
+
let gate;
|
|
20
|
+
beforeEach(() => {
|
|
21
|
+
gate = new DeprecatedApisGate();
|
|
22
|
+
vi.clearAllMocks();
|
|
23
|
+
});
|
|
24
|
+
it('should flag new Buffer() as security-critical', async () => {
|
|
25
|
+
mockFindFiles.mockResolvedValue(['src/handler.js']);
|
|
26
|
+
mockReadFile.mockResolvedValue(`
|
|
27
|
+
const buf = new Buffer(100);
|
|
28
|
+
const buf2 = new Buffer('hello');
|
|
29
|
+
`);
|
|
30
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
31
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
32
|
+
const secFail = failures.find(f => f.title === 'Security-Deprecated APIs');
|
|
33
|
+
expect(secFail).toBeDefined();
|
|
34
|
+
expect(secFail.severity).toBe('critical');
|
|
35
|
+
expect(secFail.details).toContain('Buffer');
|
|
36
|
+
});
|
|
37
|
+
it('should flag crypto.createCipher as security-critical', async () => {
|
|
38
|
+
mockFindFiles.mockResolvedValue(['src/encrypt.ts']);
|
|
39
|
+
mockReadFile.mockResolvedValue(`
|
|
40
|
+
import crypto from 'crypto';
|
|
41
|
+
const cipher = crypto.createCipher('aes-256-cbc', 'password');
|
|
42
|
+
`);
|
|
43
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
44
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
45
|
+
expect(failures[0].details).toContain('createCipher');
|
|
46
|
+
});
|
|
47
|
+
it('should flag document.write() as security risk', async () => {
|
|
48
|
+
mockFindFiles.mockResolvedValue(['src/page.tsx']);
|
|
49
|
+
mockReadFile.mockResolvedValue(`
|
|
50
|
+
document.write('<script>alert("xss")</script>');
|
|
51
|
+
`);
|
|
52
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
53
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
54
|
+
expect(failures[0].details).toContain('document.write');
|
|
55
|
+
});
|
|
56
|
+
it('should flag eval() as security risk', async () => {
|
|
57
|
+
mockFindFiles.mockResolvedValue(['src/dynamic.js']);
|
|
58
|
+
mockReadFile.mockResolvedValue(`
|
|
59
|
+
const result = eval(userInput);
|
|
60
|
+
`);
|
|
61
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
62
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
63
|
+
expect(failures[0].details).toContain('eval');
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
describe('DeprecatedApisGate — Node.js Superseded', () => {
|
|
67
|
+
let gate;
|
|
68
|
+
beforeEach(() => {
|
|
69
|
+
gate = new DeprecatedApisGate();
|
|
70
|
+
vi.clearAllMocks();
|
|
71
|
+
});
|
|
72
|
+
it('should flag url.parse() as superseded', async () => {
|
|
73
|
+
mockFindFiles.mockResolvedValue(['src/router.ts']);
|
|
74
|
+
mockReadFile.mockResolvedValue(`
|
|
75
|
+
import url from 'url';
|
|
76
|
+
const parsed = url.parse(req.url);
|
|
77
|
+
`);
|
|
78
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
79
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
80
|
+
expect(failures[0].details).toContain('url.parse');
|
|
81
|
+
});
|
|
82
|
+
it('should flag fs.exists() as superseded', async () => {
|
|
83
|
+
mockFindFiles.mockResolvedValue(['src/checker.ts']);
|
|
84
|
+
mockReadFile.mockResolvedValue(`
|
|
85
|
+
const fs = require('fs');
|
|
86
|
+
fs.exists('/tmp/test', (exists) => {});
|
|
87
|
+
`);
|
|
88
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
89
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
90
|
+
expect(failures[0].details).toContain('fs.exists');
|
|
91
|
+
});
|
|
92
|
+
it('should flag require("domain") as removed', async () => {
|
|
93
|
+
mockFindFiles.mockResolvedValue(['src/app.js']);
|
|
94
|
+
mockReadFile.mockResolvedValue(`
|
|
95
|
+
const domain = require('domain');
|
|
96
|
+
`);
|
|
97
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
98
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
99
|
+
expect(failures[0].details).toContain('domain');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
describe('DeprecatedApisGate — Python', () => {
|
|
103
|
+
let gate;
|
|
104
|
+
beforeEach(() => {
|
|
105
|
+
gate = new DeprecatedApisGate();
|
|
106
|
+
vi.clearAllMocks();
|
|
107
|
+
});
|
|
108
|
+
it('should flag pickle.loads() as security risk', async () => {
|
|
109
|
+
mockFindFiles.mockResolvedValue(['handler.py']);
|
|
110
|
+
mockReadFile.mockResolvedValue(`
|
|
111
|
+
import pickle
|
|
112
|
+
data = pickle.loads(untrusted_input)
|
|
113
|
+
`);
|
|
114
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
115
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
116
|
+
expect(failures[0].details).toContain('pickle');
|
|
117
|
+
});
|
|
118
|
+
it('should flag os.system() as security risk', async () => {
|
|
119
|
+
mockFindFiles.mockResolvedValue(['runner.py']);
|
|
120
|
+
mockReadFile.mockResolvedValue(`
|
|
121
|
+
import os
|
|
122
|
+
os.system(user_command)
|
|
123
|
+
`);
|
|
124
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
125
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
126
|
+
expect(failures[0].details).toContain('os.system');
|
|
127
|
+
});
|
|
128
|
+
it('should flag subprocess with shell=True', async () => {
|
|
129
|
+
mockFindFiles.mockResolvedValue(['runner.py']);
|
|
130
|
+
mockReadFile.mockResolvedValue(`
|
|
131
|
+
import subprocess
|
|
132
|
+
subprocess.run(cmd, shell=True)
|
|
133
|
+
`);
|
|
134
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
135
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
136
|
+
expect(failures[0].details).toContain('shell=True');
|
|
137
|
+
});
|
|
138
|
+
it('should flag import imp as removed', async () => {
|
|
139
|
+
mockFindFiles.mockResolvedValue(['loader.py']);
|
|
140
|
+
mockReadFile.mockResolvedValue(`
|
|
141
|
+
import imp
|
|
142
|
+
module = imp.load_source('name', 'path')
|
|
143
|
+
`);
|
|
144
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
145
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
146
|
+
expect(failures[0].details).toContain('imp');
|
|
147
|
+
});
|
|
148
|
+
it('should flag from distutils as removed', async () => {
|
|
149
|
+
mockFindFiles.mockResolvedValue(['setup.py']);
|
|
150
|
+
mockReadFile.mockResolvedValue(`
|
|
151
|
+
from distutils.core import setup
|
|
152
|
+
`);
|
|
153
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
154
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
155
|
+
expect(failures[0].details).toContain('distutils');
|
|
156
|
+
});
|
|
157
|
+
it('should flag typing.Dict as superseded', async () => {
|
|
158
|
+
mockFindFiles.mockResolvedValue(['models.py']);
|
|
159
|
+
mockReadFile.mockResolvedValue(`
|
|
160
|
+
from typing import Dict, List, Optional
|
|
161
|
+
`);
|
|
162
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
163
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
164
|
+
});
|
|
165
|
+
it('should not flag when disabled', async () => {
|
|
166
|
+
const disabled = new DeprecatedApisGate({ enabled: false });
|
|
167
|
+
const failures = await disabled.run({ cwd: '/project' });
|
|
168
|
+
expect(failures).toHaveLength(0);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
describe('DeprecatedApisGate — Go', () => {
|
|
172
|
+
let gate;
|
|
173
|
+
beforeEach(() => {
|
|
174
|
+
gate = new DeprecatedApisGate();
|
|
175
|
+
vi.clearAllMocks();
|
|
176
|
+
});
|
|
177
|
+
it('should flag ioutil usage as deprecated', async () => {
|
|
178
|
+
mockFindFiles.mockResolvedValue(['main.go']);
|
|
179
|
+
mockReadFile.mockResolvedValue(`
|
|
180
|
+
package main
|
|
181
|
+
import "io/ioutil"
|
|
182
|
+
func main() {
|
|
183
|
+
data, _ := ioutil.ReadFile("test.txt")
|
|
184
|
+
ioutil.WriteFile("out.txt", data, 0644)
|
|
185
|
+
}
|
|
186
|
+
`);
|
|
187
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
188
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
189
|
+
expect(failures[0].details).toContain('ioutil');
|
|
190
|
+
});
|
|
191
|
+
it('should flag strings.Title as deprecated', async () => {
|
|
192
|
+
mockFindFiles.mockResolvedValue(['util.go']);
|
|
193
|
+
mockReadFile.mockResolvedValue(`
|
|
194
|
+
package util
|
|
195
|
+
import "strings"
|
|
196
|
+
func Title(s string) string {
|
|
197
|
+
return strings.Title(s)
|
|
198
|
+
}
|
|
199
|
+
`);
|
|
200
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
201
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
202
|
+
expect(failures[0].details).toContain('strings.Title');
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
describe('DeprecatedApisGate — C#', () => {
|
|
206
|
+
let gate;
|
|
207
|
+
beforeEach(() => {
|
|
208
|
+
gate = new DeprecatedApisGate();
|
|
209
|
+
vi.clearAllMocks();
|
|
210
|
+
});
|
|
211
|
+
it('should flag BinaryFormatter as security-deprecated', async () => {
|
|
212
|
+
mockFindFiles.mockResolvedValue(['Serializer.cs']);
|
|
213
|
+
mockReadFile.mockResolvedValue(`
|
|
214
|
+
using System.Runtime.Serialization.Formatters.Binary;
|
|
215
|
+
var formatter = new BinaryFormatter();
|
|
216
|
+
`);
|
|
217
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
218
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
219
|
+
expect(failures[0].details).toContain('BinaryFormatter');
|
|
220
|
+
});
|
|
221
|
+
it('should flag WebClient as deprecated', async () => {
|
|
222
|
+
mockFindFiles.mockResolvedValue(['HttpHelper.cs']);
|
|
223
|
+
mockReadFile.mockResolvedValue(`
|
|
224
|
+
using System.Net;
|
|
225
|
+
var client = new WebClient();
|
|
226
|
+
`);
|
|
227
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
228
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
229
|
+
expect(failures[0].details).toContain('WebClient');
|
|
230
|
+
});
|
|
231
|
+
it('should flag Thread.Abort as removed', async () => {
|
|
232
|
+
mockFindFiles.mockResolvedValue(['Worker.cs']);
|
|
233
|
+
mockReadFile.mockResolvedValue(`
|
|
234
|
+
using System.Threading;
|
|
235
|
+
Thread.Abort();
|
|
236
|
+
`);
|
|
237
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
238
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
describe('DeprecatedApisGate — Java', () => {
|
|
242
|
+
let gate;
|
|
243
|
+
beforeEach(() => {
|
|
244
|
+
gate = new DeprecatedApisGate();
|
|
245
|
+
vi.clearAllMocks();
|
|
246
|
+
});
|
|
247
|
+
it('should flag Vector and Hashtable as deprecated', async () => {
|
|
248
|
+
mockFindFiles.mockResolvedValue(['Legacy.java']);
|
|
249
|
+
mockReadFile.mockResolvedValue(`
|
|
250
|
+
import java.util.*;
|
|
251
|
+
Vector<String> v = new Vector<String>();
|
|
252
|
+
Hashtable<String, Integer> ht = new Hashtable<String, Integer>();
|
|
253
|
+
`);
|
|
254
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
255
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
256
|
+
});
|
|
257
|
+
it('should flag new Integer() as deprecated', async () => {
|
|
258
|
+
mockFindFiles.mockResolvedValue(['Boxing.java']);
|
|
259
|
+
mockReadFile.mockResolvedValue(`
|
|
260
|
+
Integer x = new Integer(42);
|
|
261
|
+
Long y = new Long(100L);
|
|
262
|
+
`);
|
|
263
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
264
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
265
|
+
expect(failures[0].details).toMatch(/Integer|Long/);
|
|
266
|
+
});
|
|
267
|
+
it('should flag Thread.stop as security-deprecated', async () => {
|
|
268
|
+
mockFindFiles.mockResolvedValue(['ThreadManager.java']);
|
|
269
|
+
mockReadFile.mockResolvedValue(`
|
|
270
|
+
thread.stop();
|
|
271
|
+
`);
|
|
272
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
273
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
274
|
+
});
|
|
275
|
+
it('should flag finalize() as deprecated', async () => {
|
|
276
|
+
mockFindFiles.mockResolvedValue(['Resource.java']);
|
|
277
|
+
mockReadFile.mockResolvedValue(`
|
|
278
|
+
class Resource {
|
|
279
|
+
protected void finalize() throws Throwable {
|
|
280
|
+
super.finalize();
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
`);
|
|
284
|
+
const failures = await gate.run({ cwd: '/project' });
|
|
285
|
+
expect(failures.length).toBeGreaterThanOrEqual(1);
|
|
286
|
+
expect(failures[0].details).toContain('finalize');
|
|
287
|
+
});
|
|
288
|
+
});
|
|
@@ -6,17 +6,18 @@
|
|
|
6
6
|
* statements for packages, files, or modules that were never installed
|
|
7
7
|
* or created.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
9
|
+
* Supported languages (v3.0.1):
|
|
10
|
+
* JS/TS — package.json deps, node_modules fallback, Node.js builtins (22.x)
|
|
11
|
+
* Python — stdlib whitelist (3.12+), relative imports, local module resolution
|
|
12
|
+
* Go — stdlib whitelist (1.22+), go.mod module path, aliased imports
|
|
13
|
+
* Ruby — stdlib whitelist (3.3+), Gemfile parsing, require + require_relative
|
|
14
|
+
* C# — .NET 8 framework namespaces, .csproj NuGet parsing, using directives
|
|
15
|
+
* Rust — std/core/alloc crates, Cargo.toml deps, use/extern crate statements
|
|
16
|
+
* Java — java/javax/jakarta stdlib, build.gradle + pom.xml deps, import statements
|
|
17
|
+
* Kotlin — kotlin/kotlinx stdlib, Gradle deps, import statements
|
|
18
18
|
*
|
|
19
19
|
* @since v2.16.0
|
|
20
|
+
* @since v3.0.1 — Go stdlib fix, Ruby/C# strengthened, Rust/Java/Kotlin added
|
|
20
21
|
*/
|
|
21
22
|
import { Gate, GateContext } from './base.js';
|
|
22
23
|
import { Failure, Provenance } from '../types/index.js';
|
|
@@ -24,7 +25,7 @@ export interface HallucinatedImport {
|
|
|
24
25
|
file: string;
|
|
25
26
|
line: number;
|
|
26
27
|
importPath: string;
|
|
27
|
-
type: 'relative' | 'package' | 'python' | 'go' | 'ruby' | 'csharp';
|
|
28
|
+
type: 'relative' | 'package' | 'python' | 'go' | 'ruby' | 'csharp' | 'rust' | 'java' | 'kotlin';
|
|
28
29
|
reason: string;
|
|
29
30
|
}
|
|
30
31
|
export interface HallucinatedImportsConfig {
|
|
@@ -43,6 +44,10 @@ export declare class HallucinatedImportsGate extends Gate {
|
|
|
43
44
|
private resolveRelativeImport;
|
|
44
45
|
private extractPackageName;
|
|
45
46
|
private shouldIgnore;
|
|
47
|
+
/**
|
|
48
|
+
* Node.js built-in modules — covers Node.js 18/20/22 LTS
|
|
49
|
+
* No third-party packages in this list (removed fs-extra hack).
|
|
50
|
+
*/
|
|
46
51
|
private isNodeBuiltin;
|
|
47
52
|
private isPythonStdlib;
|
|
48
53
|
/**
|
|
@@ -67,13 +72,74 @@ export declare class HallucinatedImportsGate extends Gate {
|
|
|
67
72
|
*/
|
|
68
73
|
private isGoStdlib;
|
|
69
74
|
/**
|
|
70
|
-
* Check Ruby imports —
|
|
75
|
+
* Check Ruby imports — require, require_relative, Gemfile verification
|
|
76
|
+
*
|
|
77
|
+
* Strategy:
|
|
78
|
+
* 1. require_relative: verify target .rb file exists in project
|
|
79
|
+
* 2. require: skip stdlib, skip gems from Gemfile/gemspec, flag unknown local requires
|
|
80
|
+
*
|
|
81
|
+
* @since v3.0.1 — strengthened with stdlib whitelist and Gemfile parsing
|
|
71
82
|
*/
|
|
72
83
|
private checkRubyImports;
|
|
84
|
+
/** Load gem names from Gemfile */
|
|
85
|
+
private loadRubyGems;
|
|
73
86
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
87
|
+
* Ruby standard library — covers Ruby 3.3+ (MRI)
|
|
88
|
+
* Includes both the default gems and bundled gems that ship with Ruby.
|
|
89
|
+
*/
|
|
90
|
+
private isRubyStdlib;
|
|
91
|
+
/**
|
|
92
|
+
* Check C# imports — using directives against .NET framework, NuGet, and project
|
|
93
|
+
*
|
|
94
|
+
* Strategy:
|
|
95
|
+
* 1. Skip .NET framework namespaces (System.*, Microsoft.*, etc.)
|
|
96
|
+
* 2. Skip NuGet packages from .csproj PackageReference
|
|
97
|
+
* 3. Flag project-relative namespaces that don't resolve
|
|
98
|
+
*
|
|
99
|
+
* @since v3.0.1 — .csproj NuGet parsing, comprehensive framework namespace list
|
|
76
100
|
*/
|
|
77
101
|
private checkCSharpImports;
|
|
102
|
+
/** Check if any .csproj file exists in the project root */
|
|
103
|
+
private hasCsprojFile;
|
|
104
|
+
/** Parse .csproj files for PackageReference names */
|
|
105
|
+
private loadNuGetPackages;
|
|
106
|
+
/**
|
|
107
|
+
* .NET 8 framework and common ecosystem namespaces
|
|
108
|
+
* Covers BCL, ASP.NET, EF Core, and major ecosystem packages
|
|
109
|
+
*/
|
|
110
|
+
private isDotNetFramework;
|
|
111
|
+
/**
|
|
112
|
+
* Check Rust imports — use/extern crate against std/core/alloc and Cargo.toml
|
|
113
|
+
*
|
|
114
|
+
* Strategy:
|
|
115
|
+
* 1. Skip Rust std, core, alloc crates
|
|
116
|
+
* 2. Skip crates listed in Cargo.toml [dependencies]
|
|
117
|
+
* 3. Flag unknown extern crate and use statements for project modules that don't exist
|
|
118
|
+
*
|
|
119
|
+
* @since v3.0.1
|
|
120
|
+
*/
|
|
121
|
+
private checkRustImports;
|
|
122
|
+
/** Load dependency names from Cargo.toml */
|
|
123
|
+
private loadCargoDeps;
|
|
124
|
+
/** Rust standard crates — std, core, alloc, proc_macro, and common test crates */
|
|
125
|
+
private isRustStdCrate;
|
|
126
|
+
/**
|
|
127
|
+
* Check Java/Kotlin imports — against stdlib and build dependencies
|
|
128
|
+
*
|
|
129
|
+
* Strategy:
|
|
130
|
+
* 1. Skip java.*, javax.*, jakarta.* (Java stdlib/EE)
|
|
131
|
+
* 2. Skip kotlin.*, kotlinx.* (Kotlin stdlib)
|
|
132
|
+
* 3. Skip deps from build.gradle or pom.xml
|
|
133
|
+
* 4. Flag project-relative imports that don't resolve
|
|
134
|
+
*
|
|
135
|
+
* @since v3.0.1
|
|
136
|
+
*/
|
|
137
|
+
private checkJavaKotlinImports;
|
|
138
|
+
/** Load dependency group IDs from build.gradle or pom.xml */
|
|
139
|
+
private loadJavaDeps;
|
|
140
|
+
/** Java standard library and Jakarta EE namespaces */
|
|
141
|
+
private isJavaStdlib;
|
|
142
|
+
/** Kotlin standard library namespaces */
|
|
143
|
+
private isKotlinStdlib;
|
|
78
144
|
private loadPackageJson;
|
|
79
145
|
}
|