@codegraft/rules 0.1.0-beta.0 → 0.1.0-beta.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.
|
@@ -2,9 +2,11 @@ import type { GrammarId } from '@codegraft/core';
|
|
|
2
2
|
/**
|
|
3
3
|
* Remove imports with no reference, and rewrite a value import used only in type positions into a
|
|
4
4
|
* type import — the analogue of `eslint-plugin-unused-imports` plus the import half of
|
|
5
|
-
* `@typescript-eslint/consistent-type-imports`. Syntactic and single-file
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* `@typescript-eslint/consistent-type-imports`. Syntactic and single-file, confident-or-abstain: an
|
|
6
|
+
* import whose use isn't decidable is kept. The scope resolver's rename-safety abstentions (a TS
|
|
7
|
+
* namespace, `declare module`) don't block pruning — a syntactic use-scan covers them; only `with`
|
|
8
|
+
* and `eval`, which can reach a name invisibly, force a no-op. Runs on every JS-family grammar and,
|
|
9
|
+
* through a `ZoneSplitter`, the `<script>` of a Vue SFC.
|
|
8
10
|
*/
|
|
9
11
|
export declare const removeUnusedImports: import("@codegraft/codemod").Codemod<Record<string, unknown>, GrammarId>;
|
|
10
12
|
export default removeUnusedImports;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove-unused-imports.d.ts","sourceRoot":"","sources":["../src/remove-unused-imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,
|
|
1
|
+
{"version":3,"file":"remove-unused-imports.d.ts","sourceRoot":"","sources":["../src/remove-unused-imports.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,SAAS,EAAY,MAAM,iBAAiB,CAAA;AAGtE;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,0EA4G9B,CAAA;AAEF,eAAe,mBAAmB,CAAA;AAIlC,eAAO,MAAM,OAAO,EAAE,SAAS,EAAwC,CAAA"}
|
|
@@ -2,9 +2,11 @@ import { defineCodemod } from '@codegraft/codemod';
|
|
|
2
2
|
/**
|
|
3
3
|
* Remove imports with no reference, and rewrite a value import used only in type positions into a
|
|
4
4
|
* type import — the analogue of `eslint-plugin-unused-imports` plus the import half of
|
|
5
|
-
* `@typescript-eslint/consistent-type-imports`. Syntactic and single-file
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* `@typescript-eslint/consistent-type-imports`. Syntactic and single-file, confident-or-abstain: an
|
|
6
|
+
* import whose use isn't decidable is kept. The scope resolver's rename-safety abstentions (a TS
|
|
7
|
+
* namespace, `declare module`) don't block pruning — a syntactic use-scan covers them; only `with`
|
|
8
|
+
* and `eval`, which can reach a name invisibly, force a no-op. Runs on every JS-family grammar and,
|
|
9
|
+
* through a `ZoneSplitter`, the `<script>` of a Vue SFC.
|
|
8
10
|
*/
|
|
9
11
|
export const removeUnusedImports = defineCodemod((root) => {
|
|
10
12
|
// The resolver reports only value (`identifier`) references, so type-position uses are gathered
|
|
@@ -16,6 +18,35 @@ export const removeUnusedImports = defineCodemod((root) => {
|
|
|
16
18
|
if (head.type === 'identifier')
|
|
17
19
|
typeRefs.add(head.text);
|
|
18
20
|
});
|
|
21
|
+
// The resolver abstains on the whole file at a construct it can't rename through — a TS namespace,
|
|
22
|
+
// `declare module`/`declare global`. Use-detection still holds (an import is used iff its name
|
|
23
|
+
// appears as a value identifier), so scan — unless `with`/`eval` can reach a name invisibly (null).
|
|
24
|
+
let fallback;
|
|
25
|
+
const syntacticRefs = (name) => {
|
|
26
|
+
if (!fallback) {
|
|
27
|
+
const dynamic = root.find('with_statement').size() > 0 || root.find('call_expression', { function: 'eval' }).size() > 0;
|
|
28
|
+
const refs = new Map();
|
|
29
|
+
if (!dynamic) {
|
|
30
|
+
// Value uses lex as `identifier` (call, `typeof x`, JSX tag, `member_expression` head) or
|
|
31
|
+
// `shorthand_property_identifier` (`{ x }`); a `.member`/key is a `property_identifier`. The
|
|
32
|
+
// import's own specifiers are `identifier`s too, so skip anything inside an import statement.
|
|
33
|
+
const add = (node) => {
|
|
34
|
+
for (let a = node.parent; a; a = a.parent)
|
|
35
|
+
if (a.type === 'import_statement')
|
|
36
|
+
return;
|
|
37
|
+
const list = refs.get(node.text);
|
|
38
|
+
if (list)
|
|
39
|
+
list.push(node);
|
|
40
|
+
else
|
|
41
|
+
refs.set(node.text, [node]);
|
|
42
|
+
};
|
|
43
|
+
root.find('identifier').nodes().forEach(add);
|
|
44
|
+
root.find('shorthand_property_identifier').nodes().forEach(add);
|
|
45
|
+
}
|
|
46
|
+
fallback = { dynamic, refs };
|
|
47
|
+
}
|
|
48
|
+
return fallback.dynamic ? null : (fallback.refs.get(name) ?? []);
|
|
49
|
+
};
|
|
19
50
|
root.find('import_statement').forEach((stmt) => {
|
|
20
51
|
const clause = stmt.children().filter((child) => child.type === 'import_clause').first();
|
|
21
52
|
if (clause.size() === 0)
|
|
@@ -42,12 +73,13 @@ export const removeUnusedImports = defineCodemod((root) => {
|
|
|
42
73
|
// Keep each referenced binding, recording whether its only references are type-position ones.
|
|
43
74
|
const kept = [];
|
|
44
75
|
for (const binding of bindings) {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
76
|
+
const resolved = binding.local.references();
|
|
77
|
+
const refNodes = resolved ? resolved.nodes() : syntacticRefs(binding.local.text);
|
|
78
|
+
if (!refNodes)
|
|
79
|
+
return; // resolver abstained and `with`/`eval` make use-detection unsound — skip
|
|
48
80
|
const declaration = binding.local.node;
|
|
49
81
|
const valueUsed = !binding.isType &&
|
|
50
|
-
|
|
82
|
+
refNodes.some((ref) => {
|
|
51
83
|
// A qualified-type head (`NS.Thing`) lexes as a value identifier but is a type use.
|
|
52
84
|
const parent = ref.parent;
|
|
53
85
|
return ref !== declaration && !(parent?.type === 'nested_type_identifier' && parent.child('module') === ref);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"remove-unused-imports.js","sourceRoot":"","sources":["../src/remove-unused-imports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD
|
|
1
|
+
{"version":3,"file":"remove-unused-imports.js","sourceRoot":"","sources":["../src/remove-unused-imports.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codegraft/rules",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.1",
|
|
4
4
|
"description": "Ready-made Codegraft codemods — ESLint-rule-style transforms (e.g. removeUnusedImports), one rule per module, tree-shakeable.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"node": ">=22.13"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@codegraft/codemod": "0.1.0-beta.
|
|
33
|
-
"@codegraft/core": "0.1.0-beta.
|
|
32
|
+
"@codegraft/codemod": "0.1.0-beta.1",
|
|
33
|
+
"@codegraft/core": "0.1.0-beta.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
|
-
"@codegraft/vue": "0.1.0-beta.
|
|
36
|
+
"@codegraft/vue": "0.1.0-beta.1"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
39
|
"build": "tsc -b"
|