@design.estate/wcctools 6.0.0 → 6.1.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/changelog.md +13 -0
- package/dist_shell/bundle.js +3 -3
- package/dist_shell/bundle.js.map +1 -1
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/cli.js +8 -2
- package/dist_ts/plugins.d.ts +7 -2
- package/dist_ts/plugins.js +9 -3
- package/dist_ts/standards/baselines.d.ts +27 -0
- package/dist_ts/standards/baselines.js +83 -0
- package/dist_ts/standards/checker.d.ts +21 -0
- package/dist_ts/standards/checker.js +88 -0
- package/dist_ts/standards/classes.gitrepo.d.ts +13 -0
- package/dist_ts/standards/classes.gitrepo.js +43 -0
- package/dist_ts/standards/classes.sourceedits.d.ts +15 -0
- package/dist_ts/standards/classes.sourceedits.js +54 -0
- package/dist_ts/standards/classes.standardfixer.d.ts +40 -0
- package/dist_ts/standards/classes.standardfixer.js +210 -0
- package/dist_ts/standards/classes.standardproject.d.ts +80 -0
- package/dist_ts/standards/classes.standardproject.js +195 -0
- package/dist_ts/standards/classes.standardtree.d.ts +56 -0
- package/dist_ts/standards/classes.standardtree.js +207 -0
- package/dist_ts/standards/cli.d.ts +7 -0
- package/dist_ts/standards/cli.js +89 -0
- package/dist_ts/standards/config.d.ts +33 -0
- package/dist_ts/standards/config.js +139 -0
- package/dist_ts/standards/errors.d.ts +9 -0
- package/dist_ts/standards/errors.js +17 -0
- package/dist_ts/standards/helpers.ast.d.ts +56 -0
- package/dist_ts/standards/helpers.ast.js +172 -0
- package/dist_ts/standards/helpers.paths.d.ts +36 -0
- package/dist_ts/standards/helpers.paths.js +86 -0
- package/dist_ts/standards/index.d.ts +14 -0
- package/dist_ts/standards/index.js +15 -0
- package/dist_ts/standards/output.d.ts +7 -0
- package/dist_ts/standards/output.js +57 -0
- package/dist_ts/standards/ratchet.d.ts +15 -0
- package/dist_ts/standards/ratchet.js +45 -0
- package/dist_ts/standards/rule.d.ts +50 -0
- package/dist_ts/standards/rule.js +9 -0
- package/dist_ts/standards/rules/barrel.element-index.d.ts +7 -0
- package/dist_ts/standards/rules/barrel.element-index.js +108 -0
- package/dist_ts/standards/rules/barrel.no-demo-export.d.ts +3 -0
- package/dist_ts/standards/rules/barrel.no-demo-export.js +29 -0
- package/dist_ts/standards/rules/demo.fixture-not-exported.d.ts +3 -0
- package/dist_ts/standards/rules/demo.fixture-not-exported.js +29 -0
- package/dist_ts/standards/rules/demo.groups.d.ts +6 -0
- package/dist_ts/standards/rules/demo.groups.js +72 -0
- package/dist_ts/standards/rules/demo.required.d.ts +3 -0
- package/dist_ts/standards/rules/demo.required.js +48 -0
- package/dist_ts/standards/rules/demo.separate-file.d.ts +3 -0
- package/dist_ts/standards/rules/demo.separate-file.js +38 -0
- package/dist_ts/standards/rules/demo.shape.d.ts +3 -0
- package/dist_ts/standards/rules/demo.shape.js +38 -0
- package/dist_ts/standards/rules/docs.component-index.d.ts +8 -0
- package/dist_ts/standards/rules/docs.component-index.js +84 -0
- package/dist_ts/standards/rules/element.exported.d.ts +3 -0
- package/dist_ts/standards/rules/element.exported.js +33 -0
- package/dist_ts/standards/rules/element.literal-tag.d.ts +3 -0
- package/dist_ts/standards/rules/element.literal-tag.js +30 -0
- package/dist_ts/standards/rules/element.reachable.d.ts +3 -0
- package/dist_ts/standards/rules/element.reachable.js +48 -0
- package/dist_ts/standards/rules/element.tag-map.d.ts +3 -0
- package/dist_ts/standards/rules/element.tag-map.js +83 -0
- package/dist_ts/standards/rules/i18n.literals.d.ts +3 -0
- package/dist_ts/standards/rules/i18n.literals.js +52 -0
- package/dist_ts/standards/rules/index.d.ts +12 -0
- package/dist_ts/standards/rules/index.js +83 -0
- package/dist_ts/standards/rules/layout.element-folder.d.ts +3 -0
- package/dist_ts/standards/rules/layout.element-folder.js +47 -0
- package/dist_ts/standards/rules/layout.entry-file-name.d.ts +3 -0
- package/dist_ts/standards/rules/layout.entry-file-name.js +71 -0
- package/dist_ts/standards/rules/layout.entry.d.ts +3 -0
- package/dist_ts/standards/rules/layout.entry.js +38 -0
- package/dist_ts/standards/rules/layout.group-folder.d.ts +3 -0
- package/dist_ts/standards/rules/layout.group-folder.js +22 -0
- package/dist_ts/standards/rules/layout.shared-00.d.ts +3 -0
- package/dist_ts/standards/rules/layout.shared-00.js +36 -0
- package/dist_ts/standards/rules/naming.class-matches-tag.d.ts +3 -0
- package/dist_ts/standards/rules/naming.class-matches-tag.js +26 -0
- package/dist_ts/standards/rules/naming.lowercase-files.d.ts +3 -0
- package/dist_ts/standards/rules/naming.lowercase-files.js +26 -0
- package/dist_ts/standards/rules/naming.tag-prefix.d.ts +3 -0
- package/dist_ts/standards/rules/naming.tag-prefix.js +23 -0
- package/dist_ts/standards/rules/props.accessor.d.ts +3 -0
- package/dist_ts/standards/rules/props.accessor.js +35 -0
- package/dist_ts/standards/rules/props.object-no-attribute.d.ts +3 -0
- package/dist_ts/standards/rules/props.object-no-attribute.js +42 -0
- package/dist_ts/standards/rules/props.reflect-primitive.d.ts +5 -0
- package/dist_ts/standards/rules/props.reflect-primitive.js +41 -0
- package/dist_ts/standards/rules/props.typed.d.ts +6 -0
- package/dist_ts/standards/rules/props.typed.js +64 -0
- package/dist_ts/standards/rules/shared.d.ts +38 -0
- package/dist_ts/standards/rules/shared.js +103 -0
- package/dist_ts/standards/rules/style.bdtheme.d.ts +5 -0
- package/dist_ts/standards/rules/style.bdtheme.js +28 -0
- package/dist_ts_interfaces/index.d.ts +1 -0
- package/dist_ts_interfaces/index.js +2 -1
- package/dist_ts_interfaces/standard.d.ts +93 -0
- package/dist_ts_interfaces/standard.js +6 -0
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/package.json +4 -2
- package/readme.md +34 -1
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/cli.ts +8 -1
- package/ts/plugins.ts +10 -2
- package/ts/standards/baselines.ts +100 -0
- package/ts/standards/checker.ts +114 -0
- package/ts/standards/classes.gitrepo.ts +48 -0
- package/ts/standards/classes.sourceedits.ts +58 -0
- package/ts/standards/classes.standardfixer.ts +234 -0
- package/ts/standards/classes.standardproject.ts +250 -0
- package/ts/standards/classes.standardtree.ts +220 -0
- package/ts/standards/cli.ts +86 -0
- package/ts/standards/config.ts +160 -0
- package/ts/standards/errors.ts +18 -0
- package/ts/standards/helpers.ast.ts +208 -0
- package/ts/standards/helpers.paths.ts +119 -0
- package/ts/standards/index.ts +22 -0
- package/ts/standards/output.ts +65 -0
- package/ts/standards/ratchet.ts +63 -0
- package/ts/standards/rule.ts +58 -0
- package/ts/standards/rules/barrel.element-index.ts +112 -0
- package/ts/standards/rules/barrel.no-demo-export.ts +30 -0
- package/ts/standards/rules/demo.fixture-not-exported.ts +30 -0
- package/ts/standards/rules/demo.groups.ts +74 -0
- package/ts/standards/rules/demo.required.ts +49 -0
- package/ts/standards/rules/demo.separate-file.ts +40 -0
- package/ts/standards/rules/demo.shape.ts +42 -0
- package/ts/standards/rules/docs.component-index.ts +88 -0
- package/ts/standards/rules/element.exported.ts +35 -0
- package/ts/standards/rules/element.literal-tag.ts +30 -0
- package/ts/standards/rules/element.reachable.ts +49 -0
- package/ts/standards/rules/element.tag-map.ts +87 -0
- package/ts/standards/rules/i18n.literals.ts +58 -0
- package/ts/standards/rules/index.ts +87 -0
- package/ts/standards/rules/layout.element-folder.ts +49 -0
- package/ts/standards/rules/layout.entry-file-name.ts +73 -0
- package/ts/standards/rules/layout.entry.ts +40 -0
- package/ts/standards/rules/layout.group-folder.ts +23 -0
- package/ts/standards/rules/layout.shared-00.ts +37 -0
- package/ts/standards/rules/naming.class-matches-tag.ts +27 -0
- package/ts/standards/rules/naming.lowercase-files.ts +27 -0
- package/ts/standards/rules/naming.tag-prefix.ts +24 -0
- package/ts/standards/rules/props.accessor.ts +37 -0
- package/ts/standards/rules/props.object-no-attribute.ts +45 -0
- package/ts/standards/rules/props.reflect-primitive.ts +44 -0
- package/ts/standards/rules/props.typed.ts +70 -0
- package/ts/standards/rules/shared.ts +127 -0
- package/ts/standards/rules/style.bdtheme.ts +31 -0
- package/ts_web/00_commitinfo_data.ts +1 -1
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { rekeyStandardConfig } from './baselines.js';
|
|
3
|
+
import { checkStandard, detectFindings, rulesOfProfile } from './checker.js';
|
|
4
|
+
import { GitRepo } from './classes.gitrepo.js';
|
|
5
|
+
import { loadStandardProject, standardSideFiles } from './classes.standardproject.js';
|
|
6
|
+
import { FixBatch, StandardTree } from './classes.standardtree.js';
|
|
7
|
+
import { StandardUsageError } from './errors.js';
|
|
8
|
+
import { dirOf, isRepoPath, isTypeScriptSource } from './helpers.paths.js';
|
|
9
|
+
import { fixOrder, standardRules } from './rules/index.js';
|
|
10
|
+
/** How often one rule is re-run on the edited tree to apply edits that overlapped in an earlier run. */
|
|
11
|
+
const maxRunsPerRule = 5;
|
|
12
|
+
/**
|
|
13
|
+
* `wcctools fix`: applies the fixes of the selected rules to an in-memory copy of the repository,
|
|
14
|
+
* one rule after another on the re-parsed result, validates that every path of the resulting plan
|
|
15
|
+
* stays inside the repository root, then writes the configuration, moves files with `git mv`, writes
|
|
16
|
+
* the edited files and checks again. Refuses to run on a dirty work tree and never commits, so a
|
|
17
|
+
* failure part-way through the writes is undone with `git reset --hard` and `git clean -fd`.
|
|
18
|
+
*/
|
|
19
|
+
export class StandardFixer {
|
|
20
|
+
options;
|
|
21
|
+
constructor(optionsArg) {
|
|
22
|
+
this.options = optionsArg;
|
|
23
|
+
}
|
|
24
|
+
selectRules() {
|
|
25
|
+
const { profile } = this.options.loaded;
|
|
26
|
+
const inProfile = new Set(rulesOfProfile(profile).map((ruleArg) => ruleArg.id));
|
|
27
|
+
if (!this.options.rules || this.options.rules.length === 0) {
|
|
28
|
+
return fixOrder.filter((idArg) => inProfile.has(idArg) && standardRules.find((ruleArg) => ruleArg.id === idArg).fixMode === 'auto');
|
|
29
|
+
}
|
|
30
|
+
for (const id of this.options.rules) {
|
|
31
|
+
const rule = standardRules.find((ruleArg) => ruleArg.id === id);
|
|
32
|
+
if (!rule) {
|
|
33
|
+
throw new StandardUsageError(`Unknown rule '${id}'`);
|
|
34
|
+
}
|
|
35
|
+
if (!inProfile.has(id)) {
|
|
36
|
+
throw new StandardUsageError(`Rule '${id}' is not part of the '${profile}' profile`);
|
|
37
|
+
}
|
|
38
|
+
if (rule.fixMode === 'none') {
|
|
39
|
+
throw new StandardUsageError(`Rule '${id}' has no fix`);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return fixOrder.filter((idArg) => this.options.rules.includes(idArg));
|
|
43
|
+
}
|
|
44
|
+
async run() {
|
|
45
|
+
const { rootDir, loaded } = this.options;
|
|
46
|
+
const selected = this.selectRules();
|
|
47
|
+
const git = new GitRepo(rootDir);
|
|
48
|
+
const topLevel = await git.topLevel();
|
|
49
|
+
if (!topLevel || plugins.fsSync.realpathSync(topLevel) !== plugins.fsSync.realpathSync(rootDir)) {
|
|
50
|
+
throw new StandardUsageError(`wcctools fix runs at the root of a git repository; ${rootDir} is not one`);
|
|
51
|
+
}
|
|
52
|
+
const status = await git.statusLines();
|
|
53
|
+
if (status.length > 0) {
|
|
54
|
+
throw new StandardUsageError(`wcctools fix needs a clean work tree; git status reports ${status.length} change(s). Commit or stash them first.`);
|
|
55
|
+
}
|
|
56
|
+
const trackedFiles = await git.trackedFiles();
|
|
57
|
+
const files = new Map();
|
|
58
|
+
for (const file of trackedFiles) {
|
|
59
|
+
if (isTypeScriptSource(file) || standardSideFiles.includes(file)) {
|
|
60
|
+
files.set(file, await plugins.fs.readFile(plugins.path.join(rootDir, file), 'utf8'));
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const tree = new StandardTree(files, trackedFiles, (fileArg) => plugins.fsSync.existsSync(plugins.path.join(rootDir, fileArg)));
|
|
64
|
+
for (const ruleId of selected) {
|
|
65
|
+
const rule = standardRules.find((ruleArg) => ruleArg.id === ruleId);
|
|
66
|
+
for (let run = 0; run < maxRunsPerRule; run++) {
|
|
67
|
+
const fixable = detectFindings(tree.project(), loaded, [rule]).filter((detectedArg) => !detectedArg.allowlisted && detectedArg.finding.fix);
|
|
68
|
+
if (fixable.length === 0) {
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
const batch = new FixBatch();
|
|
72
|
+
fixable.forEach((detectedArg) => detectedArg.finding.fix(batch));
|
|
73
|
+
if (tree.apply(rule.id, batch) === 0) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
const plan = tree.plan();
|
|
79
|
+
await this.assertInsideRoot(plan);
|
|
80
|
+
const rekeyed = rekeyStandardConfig(loaded.config, plan.moves);
|
|
81
|
+
if (rekeyed.changed.length > 0 && !this.options.configWriter) {
|
|
82
|
+
throw new StandardUsageError(`wcctools fix would move files that the standard configuration names (${rekeyed.changed.join(', ')}) but has no configuration writer`);
|
|
83
|
+
}
|
|
84
|
+
const loadedAfter = { ...loaded, config: rekeyed.config };
|
|
85
|
+
if (this.options.dryRun) {
|
|
86
|
+
return { dryRun: true, plan, remaining: checkStandard(tree.project(), loadedAfter) };
|
|
87
|
+
}
|
|
88
|
+
// Every path is validated above. The configuration goes first: a refused write (the file changed
|
|
89
|
+
// since it was read) leaves the tree untouched. A failure after it leaves a partial result that the
|
|
90
|
+
// clean work tree fix started from restores (`git reset --hard`, `git clean -fd`).
|
|
91
|
+
if (rekeyed.changed.length > 0) {
|
|
92
|
+
await this.options.configWriter.writeStandardConfig(rekeyed.config);
|
|
93
|
+
}
|
|
94
|
+
await this.commitMoves(git, plan.moves);
|
|
95
|
+
for (const file of [...plan.created, ...plan.edited.map((editedArg) => editedArg.file)]) {
|
|
96
|
+
await this.ensureDir(dirOf(file));
|
|
97
|
+
await plugins.fs.writeFile(plugins.path.join(rootDir, file), tree.files.get(file), 'utf8');
|
|
98
|
+
}
|
|
99
|
+
await this.removeEmptyDirs(plan.moves.map((moveArg) => dirOf(moveArg.from)));
|
|
100
|
+
return { dryRun: false, plan, remaining: checkStandard(await loadStandardProject(rootDir), loadedAfter) };
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Refuses a plan with a path that leaves the repository root, lexically (an absolute path or a `..`
|
|
104
|
+
* segment) or physically (through a symbolic link that resolves outside the root or dangles).
|
|
105
|
+
* Runs before anything is written, so a refused plan leaves the repository and its surroundings as
|
|
106
|
+
* they were.
|
|
107
|
+
*/
|
|
108
|
+
async assertInsideRoot(planArg) {
|
|
109
|
+
const realRoot = await plugins.fs.realpath(this.options.rootDir);
|
|
110
|
+
const paths = [
|
|
111
|
+
...planArg.moves.flatMap((moveArg) => [moveArg.from, moveArg.to]),
|
|
112
|
+
...planArg.created,
|
|
113
|
+
...planArg.edited.map((editedArg) => editedArg.file),
|
|
114
|
+
];
|
|
115
|
+
const outside = [];
|
|
116
|
+
for (const file of new Set(paths)) {
|
|
117
|
+
if (!isRepoPath(file) || !(await this.resolvesInside(realRoot, file))) {
|
|
118
|
+
outside.push(file);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (outside.length > 0) {
|
|
122
|
+
throw new StandardUsageError(`wcctools fix refuses to write outside the repository root: ${outside.join(', ')}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/** True when the file, or its nearest existing ancestor, resolves to a path inside the real root. */
|
|
126
|
+
async resolvesInside(realRootArg, fileArg) {
|
|
127
|
+
let current = plugins.path.join(realRootArg, fileArg);
|
|
128
|
+
while (true) {
|
|
129
|
+
try {
|
|
130
|
+
const real = await plugins.fs.realpath(current);
|
|
131
|
+
return real === realRootArg || real.startsWith(`${realRootArg}${plugins.path.sep}`);
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
const code = error.code;
|
|
135
|
+
if (code !== 'ENOENT' && code !== 'ENOTDIR') {
|
|
136
|
+
throw error;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (await this.isSymbolicLink(current)) {
|
|
140
|
+
// A dangling link: writing through it would create its target, wherever that is.
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const parent = plugins.path.dirname(current);
|
|
144
|
+
if (parent === current) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
current = parent;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
async isSymbolicLink(pathArg) {
|
|
151
|
+
try {
|
|
152
|
+
return (await plugins.fs.lstat(pathArg)).isSymbolicLink();
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
const code = error.code;
|
|
156
|
+
if (code === 'ENOENT' || code === 'ENOTDIR') {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
/** `git mv` in an order where no move overwrites a file that has not moved away yet. */
|
|
163
|
+
async commitMoves(gitArg, movesArg) {
|
|
164
|
+
const pending = [...movesArg];
|
|
165
|
+
while (pending.length > 0) {
|
|
166
|
+
const index = pending.findIndex((moveArg) => !plugins.fsSync.existsSync(plugins.path.join(this.options.rootDir, moveArg.to)));
|
|
167
|
+
if (index === -1) {
|
|
168
|
+
throw new Error(`Cannot order the moves ${pending.map((moveArg) => `${moveArg.from} → ${moveArg.to}`).join(', ')}`);
|
|
169
|
+
}
|
|
170
|
+
const [move] = pending.splice(index, 1);
|
|
171
|
+
await this.ensureDir(dirOf(move.to));
|
|
172
|
+
await gitArg.move(move.from, move.to);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
/** Creates a directory one path component at a time. */
|
|
176
|
+
async ensureDir(dirArg) {
|
|
177
|
+
let current = this.options.rootDir;
|
|
178
|
+
for (const segment of dirArg.split('/').filter((segmentArg) => segmentArg && segmentArg !== '.')) {
|
|
179
|
+
current = plugins.path.join(current, segment);
|
|
180
|
+
try {
|
|
181
|
+
await plugins.fs.mkdir(current);
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
if (error.code !== 'EEXIST') {
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** Removes directories that moves left empty, walking up towards the repository root. */
|
|
191
|
+
async removeEmptyDirs(dirsArg) {
|
|
192
|
+
for (const start of [...new Set(dirsArg)].sort((a, b) => b.length - a.length)) {
|
|
193
|
+
let dir = start;
|
|
194
|
+
while (dir && dir !== '.') {
|
|
195
|
+
try {
|
|
196
|
+
await plugins.fs.rmdir(plugins.path.join(this.options.rootDir, dir));
|
|
197
|
+
}
|
|
198
|
+
catch (error) {
|
|
199
|
+
const code = error.code;
|
|
200
|
+
if (code === 'ENOTEMPTY' || code === 'EEXIST' || code === 'ENOENT') {
|
|
201
|
+
break;
|
|
202
|
+
}
|
|
203
|
+
throw error;
|
|
204
|
+
}
|
|
205
|
+
dir = dirOf(dir);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdGFuZGFyZGZpeGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvc3RhbmRhcmRzL2NsYXNzZXMuc3RhbmRhcmRmaXhlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNyRCxPQUFPLEVBQUUsYUFBYSxFQUFFLGNBQWMsRUFBRSxjQUFjLEVBQUUsTUFBTSxjQUFjLENBQUM7QUFDN0UsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBQy9DLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDhCQUE4QixDQUFDO0FBQ3RGLE9BQU8sRUFBRSxRQUFRLEVBQUUsWUFBWSxFQUFFLE1BQU0sMkJBQTJCLENBQUM7QUFFbkUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sYUFBYSxDQUFDO0FBQ2pELE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLGtCQUFrQixFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDM0UsT0FBTyxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQVkzRCx3R0FBd0c7QUFDeEcsTUFBTSxjQUFjLEdBQUcsQ0FBQyxDQUFDO0FBRXpCOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxhQUFhO0lBQ1AsT0FBTyxDQUFzQjtJQUU5QyxZQUFZLFVBQStCO1FBQ3pDLElBQUksQ0FBQyxPQUFPLEdBQUcsVUFBVSxDQUFDO0lBQzVCLENBQUM7SUFFTyxXQUFXO1FBQ2pCLE1BQU0sRUFBRSxPQUFPLEVBQUUsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUN4QyxNQUFNLFNBQVMsR0FBRyxJQUFJLEdBQUcsQ0FBQyxjQUFjLENBQUMsT0FBTyxDQUFDLENBQUMsR0FBRyxD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
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as ast from './helpers.ast.js';
|
|
3
|
+
/** A class decorated with `@customElement(…)`. */
|
|
4
|
+
export interface IStandardElement {
|
|
5
|
+
file: string;
|
|
6
|
+
sourceFile: ast.TSourceFile;
|
|
7
|
+
classNode: ast.TClassDeclaration;
|
|
8
|
+
className: string | null;
|
|
9
|
+
decoratorCall: ast.TCallExpression;
|
|
10
|
+
/** The literal tag, or null when the decorator argument is not a string literal. */
|
|
11
|
+
tag: string | null;
|
|
12
|
+
exported: boolean;
|
|
13
|
+
inDemoFile: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** A class member decorated with `@property(…)` or `@state(…)`. */
|
|
16
|
+
export interface IStandardProperty {
|
|
17
|
+
file: string;
|
|
18
|
+
sourceFile: ast.TSourceFile;
|
|
19
|
+
classNode: ast.TClassDeclaration;
|
|
20
|
+
member: ast.TClassElement;
|
|
21
|
+
name: string;
|
|
22
|
+
decorator: 'property' | 'state';
|
|
23
|
+
call: ast.TCallExpression;
|
|
24
|
+
/** The options object literal; null when the decorator has no argument or a non-literal one. */
|
|
25
|
+
options: ast.TObjectLiteralExpression | null;
|
|
26
|
+
/** True when the decorator has an argument that is not an object literal. */
|
|
27
|
+
dynamicOptions: boolean;
|
|
28
|
+
isPublic: boolean;
|
|
29
|
+
inDemoFile: boolean;
|
|
30
|
+
}
|
|
31
|
+
/** An `export … from '<relative>'` declaration. */
|
|
32
|
+
export interface IStandardReexport {
|
|
33
|
+
file: string;
|
|
34
|
+
statement: plugins.typescript.ExportDeclaration;
|
|
35
|
+
specifier: string;
|
|
36
|
+
/** The resolved repository path, or null when it does not resolve to a known file. */
|
|
37
|
+
target: string | null;
|
|
38
|
+
}
|
|
39
|
+
export type TParseCache = Map<string, {
|
|
40
|
+
text: string;
|
|
41
|
+
sourceFile: ast.TSourceFile;
|
|
42
|
+
}>;
|
|
43
|
+
/** The root barrel every reachability check starts from. */
|
|
44
|
+
export declare const rootBarrel = "ts_web/index.ts";
|
|
45
|
+
export declare const elementsBarrel = "ts_web/elements/index.ts";
|
|
46
|
+
/**
|
|
47
|
+
* The syntax-only model of a catalog the rules read: its files, elements, reactive properties and
|
|
48
|
+
* barrel graph. Built from a map of repository paths to file texts, so the same model serves a
|
|
49
|
+
* repository on disk and the fixer's in-memory tree.
|
|
50
|
+
*/
|
|
51
|
+
export declare class StandardProject {
|
|
52
|
+
readonly files: ReadonlyMap<string, string>;
|
|
53
|
+
private readonly existsOnDisk;
|
|
54
|
+
private readonly parseCache;
|
|
55
|
+
private elementsCache;
|
|
56
|
+
private propertiesCache;
|
|
57
|
+
private reexportsCache;
|
|
58
|
+
constructor(filesArg: ReadonlyMap<string, string>, existsOnDiskArg: (fileArg: string) => boolean, parseCacheArg?: TParseCache);
|
|
59
|
+
/** True when the file is part of the model or exists in the repository. */
|
|
60
|
+
exists(fileArg: string): boolean;
|
|
61
|
+
/** The `ts_web/**\/*.ts` sources, sorted. */
|
|
62
|
+
get webFiles(): string[];
|
|
63
|
+
sourceFile(fileArg: string): ast.TSourceFile;
|
|
64
|
+
/** `compilerOptions.experimentalDecorators` of tsconfig.json (its `extends` chain is not followed). */
|
|
65
|
+
get experimentalDecorators(): boolean;
|
|
66
|
+
get elements(): IStandardElement[];
|
|
67
|
+
get properties(): IStandardProperty[];
|
|
68
|
+
/** The `export … from` declarations of a file with relative specifiers. */
|
|
69
|
+
reexports(fileArg: string): IStandardReexport[];
|
|
70
|
+
/** Every file reached from a barrel by following `export … from` declarations. */
|
|
71
|
+
reachableFrom(fileArg: string): Set<string>;
|
|
72
|
+
lineAndColumn(fileArg: string, positionArg: number): {
|
|
73
|
+
line: number;
|
|
74
|
+
column: number;
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** The files besides `ts_web/**` a check reads. */
|
|
78
|
+
export declare const standardSideFiles: string[];
|
|
79
|
+
/** Reads the files the standard covers from a repository on disk. */
|
|
80
|
+
export declare const loadStandardProject: (rootDirArg: string) => Promise<StandardProject>;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as ast from './helpers.ast.js';
|
|
3
|
+
import { isDemoFile, isTypeScriptSource, resolveSpecifier, toPosix } from './helpers.paths.js';
|
|
4
|
+
const ts = plugins.typescript;
|
|
5
|
+
/** The root barrel every reachability check starts from. */
|
|
6
|
+
export const rootBarrel = 'ts_web/index.ts';
|
|
7
|
+
export const elementsBarrel = 'ts_web/elements/index.ts';
|
|
8
|
+
/**
|
|
9
|
+
* The syntax-only model of a catalog the rules read: its files, elements, reactive properties and
|
|
10
|
+
* barrel graph. Built from a map of repository paths to file texts, so the same model serves a
|
|
11
|
+
* repository on disk and the fixer's in-memory tree.
|
|
12
|
+
*/
|
|
13
|
+
export class StandardProject {
|
|
14
|
+
files;
|
|
15
|
+
existsOnDisk;
|
|
16
|
+
parseCache;
|
|
17
|
+
elementsCache = null;
|
|
18
|
+
propertiesCache = null;
|
|
19
|
+
reexportsCache = new Map();
|
|
20
|
+
constructor(filesArg, existsOnDiskArg, parseCacheArg = new Map()) {
|
|
21
|
+
this.files = filesArg;
|
|
22
|
+
this.existsOnDisk = existsOnDiskArg;
|
|
23
|
+
this.parseCache = parseCacheArg;
|
|
24
|
+
}
|
|
25
|
+
/** True when the file is part of the model or exists in the repository. */
|
|
26
|
+
exists(fileArg) {
|
|
27
|
+
return this.files.has(fileArg) || this.existsOnDisk(fileArg);
|
|
28
|
+
}
|
|
29
|
+
/** The `ts_web/**\/*.ts` sources, sorted. */
|
|
30
|
+
get webFiles() {
|
|
31
|
+
return [...this.files.keys()].filter((fileArg) => fileArg.startsWith('ts_web/') && fileArg.endsWith('.ts') && isTypeScriptSource(fileArg)).sort();
|
|
32
|
+
}
|
|
33
|
+
sourceFile(fileArg) {
|
|
34
|
+
const text = this.files.get(fileArg);
|
|
35
|
+
if (text === undefined) {
|
|
36
|
+
throw new Error(`Not a known file: ${fileArg}`);
|
|
37
|
+
}
|
|
38
|
+
const cached = this.parseCache.get(fileArg);
|
|
39
|
+
if (cached && cached.text === text) {
|
|
40
|
+
return cached.sourceFile;
|
|
41
|
+
}
|
|
42
|
+
const sourceFile = ast.parseSource(fileArg, text);
|
|
43
|
+
this.parseCache.set(fileArg, { text, sourceFile });
|
|
44
|
+
return sourceFile;
|
|
45
|
+
}
|
|
46
|
+
/** `compilerOptions.experimentalDecorators` of tsconfig.json (its `extends` chain is not followed). */
|
|
47
|
+
get experimentalDecorators() {
|
|
48
|
+
const text = this.files.get('tsconfig.json');
|
|
49
|
+
if (!text) {
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
const parsed = ts.parseConfigFileTextToJson('tsconfig.json', text);
|
|
53
|
+
return parsed.config?.compilerOptions?.experimentalDecorators === true;
|
|
54
|
+
}
|
|
55
|
+
get elements() {
|
|
56
|
+
if (!this.elementsCache) {
|
|
57
|
+
this.elementsCache = [];
|
|
58
|
+
for (const file of this.webFiles) {
|
|
59
|
+
const sourceFile = this.sourceFile(file);
|
|
60
|
+
const visit = (nodeArg) => {
|
|
61
|
+
if (ts.isClassDeclaration(nodeArg)) {
|
|
62
|
+
const decorator = ast.findDecoratorCall(nodeArg, ['customElement']);
|
|
63
|
+
if (decorator) {
|
|
64
|
+
const tagArgument = decorator.call.arguments[0];
|
|
65
|
+
this.elementsCache.push({
|
|
66
|
+
file,
|
|
67
|
+
sourceFile,
|
|
68
|
+
classNode: nodeArg,
|
|
69
|
+
className: nodeArg.name?.text ?? null,
|
|
70
|
+
decoratorCall: decorator.call,
|
|
71
|
+
tag: decorator.call.arguments.length === 1 && ast.isStringLiteralLike(tagArgument) ? tagArgument.text : null,
|
|
72
|
+
exported: ast.hasModifier(nodeArg, ts.SyntaxKind.ExportKeyword),
|
|
73
|
+
inDemoFile: isDemoFile(file),
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
ts.forEachChild(nodeArg, visit);
|
|
78
|
+
};
|
|
79
|
+
visit(sourceFile);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return this.elementsCache;
|
|
83
|
+
}
|
|
84
|
+
get properties() {
|
|
85
|
+
if (!this.propertiesCache) {
|
|
86
|
+
this.propertiesCache = [];
|
|
87
|
+
for (const file of this.webFiles) {
|
|
88
|
+
const sourceFile = this.sourceFile(file);
|
|
89
|
+
const visit = (nodeArg) => {
|
|
90
|
+
if (ts.isClassDeclaration(nodeArg) || ts.isClassExpression(nodeArg)) {
|
|
91
|
+
for (const member of nodeArg.members) {
|
|
92
|
+
const decorator = ast.findDecoratorCall(member, ['property', 'state']);
|
|
93
|
+
const name = ast.memberNameText(member);
|
|
94
|
+
if (!decorator || name === null) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const firstArgument = decorator.call.arguments[0];
|
|
98
|
+
const isPrivateName = !!member.name && ts.isPrivateIdentifier(member.name);
|
|
99
|
+
this.propertiesCache.push({
|
|
100
|
+
file,
|
|
101
|
+
sourceFile,
|
|
102
|
+
classNode: nodeArg,
|
|
103
|
+
member,
|
|
104
|
+
name: isPrivateName && !name.startsWith('#') ? `#${name}` : name,
|
|
105
|
+
decorator: decorator.name,
|
|
106
|
+
call: decorator.call,
|
|
107
|
+
options: firstArgument && ts.isObjectLiteralExpression(firstArgument) ? firstArgument : null,
|
|
108
|
+
dynamicOptions: !!firstArgument && !ts.isObjectLiteralExpression(firstArgument),
|
|
109
|
+
isPublic: !isPrivateName
|
|
110
|
+
&& !ast.hasModifier(member, ts.SyntaxKind.PrivateKeyword)
|
|
111
|
+
&& !ast.hasModifier(member, ts.SyntaxKind.ProtectedKeyword),
|
|
112
|
+
inDemoFile: isDemoFile(file),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
ts.forEachChild(nodeArg, visit);
|
|
117
|
+
};
|
|
118
|
+
visit(sourceFile);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return this.propertiesCache;
|
|
122
|
+
}
|
|
123
|
+
/** The `export … from` declarations of a file with relative specifiers. */
|
|
124
|
+
reexports(fileArg) {
|
|
125
|
+
let reexports = this.reexportsCache.get(fileArg);
|
|
126
|
+
if (!reexports) {
|
|
127
|
+
reexports = [];
|
|
128
|
+
if (this.files.has(fileArg)) {
|
|
129
|
+
for (const statement of this.sourceFile(fileArg).statements) {
|
|
130
|
+
if (ts.isExportDeclaration(statement) && statement.moduleSpecifier && ast.isStringLiteralLike(statement.moduleSpecifier)) {
|
|
131
|
+
const specifier = statement.moduleSpecifier.text;
|
|
132
|
+
if (!specifier.startsWith('.')) {
|
|
133
|
+
continue;
|
|
134
|
+
}
|
|
135
|
+
const resolved = resolveSpecifier(fileArg, specifier, (candidateArg) => this.files.has(candidateArg));
|
|
136
|
+
reexports.push({ file: fileArg, statement, specifier, target: resolved?.target ?? null });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
this.reexportsCache.set(fileArg, reexports);
|
|
141
|
+
}
|
|
142
|
+
return reexports;
|
|
143
|
+
}
|
|
144
|
+
/** Every file reached from a barrel by following `export … from` declarations. */
|
|
145
|
+
reachableFrom(fileArg) {
|
|
146
|
+
const reached = new Set();
|
|
147
|
+
const queue = this.files.has(fileArg) ? [fileArg] : [];
|
|
148
|
+
while (queue.length > 0) {
|
|
149
|
+
const file = queue.shift();
|
|
150
|
+
if (reached.has(file)) {
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
reached.add(file);
|
|
154
|
+
for (const reexport of this.reexports(file)) {
|
|
155
|
+
if (reexport.target && !reached.has(reexport.target)) {
|
|
156
|
+
queue.push(reexport.target);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return reached;
|
|
161
|
+
}
|
|
162
|
+
lineAndColumn(fileArg, positionArg) {
|
|
163
|
+
return ast.lineAndColumn(this.sourceFile(fileArg), positionArg);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/** The files besides `ts_web/**` a check reads. */
|
|
167
|
+
export const standardSideFiles = ['html/index.ts', 'html/index.html', 'tsconfig.json', 'readme.md'];
|
|
168
|
+
/** Reads the files the standard covers from a repository on disk. */
|
|
169
|
+
export const loadStandardProject = async (rootDirArg) => {
|
|
170
|
+
const files = new Map();
|
|
171
|
+
const webDir = plugins.path.join(rootDirArg, 'ts_web');
|
|
172
|
+
if (plugins.fsSync.existsSync(webDir)) {
|
|
173
|
+
const entries = await plugins.fs.readdir(webDir, { recursive: true, withFileTypes: true });
|
|
174
|
+
for (const entry of entries) {
|
|
175
|
+
if (!entry.isFile()) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const relative = toPosix(plugins.path.relative(rootDirArg, plugins.path.join(entry.parentPath, entry.name)));
|
|
179
|
+
if (relative.split('/').some((segmentArg) => segmentArg === 'node_modules')) {
|
|
180
|
+
continue;
|
|
181
|
+
}
|
|
182
|
+
if (relative.endsWith('.ts') && isTypeScriptSource(relative)) {
|
|
183
|
+
files.set(relative, await plugins.fs.readFile(plugins.path.join(rootDirArg, relative), 'utf8'));
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
for (const sideFile of standardSideFiles) {
|
|
188
|
+
const absolute = plugins.path.join(rootDirArg, sideFile);
|
|
189
|
+
if (plugins.fsSync.existsSync(absolute)) {
|
|
190
|
+
files.set(sideFile, await plugins.fs.readFile(absolute, 'utf8'));
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return new StandardProject(files, (fileArg) => plugins.fsSync.existsSync(plugins.path.join(rootDirArg, fileArg)));
|
|
194
|
+
};
|
|
195
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdGFuZGFyZHByb2plY3QuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9zdGFuZGFyZHMvY2xhc3Nlcy5zdGFuZGFyZHByb2plY3QudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxlQUFlLENBQUM7QUFDekMsT0FBTyxLQUFLLEdBQUcsTUFBTSxrQkFBa0IsQ0FBQztBQUN4QyxPQUFPLEVBQUUsVUFBVSxFQUFFLGtCQUFrQixFQUFFLGdCQUFnQixFQUFFLE9BQU8sRUFBRSxNQUFNLG9CQUFvQixDQUFDO0FBRS9GLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7QUEyQzlCLDREQUE0RDtBQUM1RCxNQUFNLENBQUMsTUFBTSxVQUFVLEdBQUcsaUJBQWlCLENBQUM7QUFDNUMsTUFBTSxDQUFDLE1BQU0sY0FBYyxHQUFHLDBCQUEwQixDQUFDO0FBRXpEOzs7O0dBSUc7QUFDSCxNQUFNLE9BQU8sZUFBZTtJQUNWLEtBQUssQ0FBOEI7SUFDbEMsWUFBWSxDQUErQjtJQUMzQyxVQUFVLENBQWM7SUFDakMsYUFBYSxHQUE4QixJQUFJLENBQUM7SUFDaEQsZUFBZSxHQUErQixJQUFJLENBQUM7SUFDbkQsY0FBYyxHQUFHLElBQUksR0FBRyxFQUErQixDQUFDO0lBRWhFLFlBQVksUUFBcUMsRUFBRSxlQUE2QyxFQUFFLGdCQUE2QixJQUFJLEdBQUcsRUFBRTtRQUN0SSxJQUFJLENBQUMsS0FBSyxHQUFHLFFBQVEsQ0FBQztRQUN0QixJQUFJLENBQUMsWUFBWSxHQUFHLGVBQWUsQ0FBQztRQUNwQyxJQUFJLENBQUMsVUFBVSxHQUFHLGFBQWEsQ0FBQztJQUNsQyxDQUFDO0lBRUQsMkVBQTJFO0lBQ3BFLE1BQU0sQ0FBQyxPQUFlO1FBQzNCLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUMvRCxDQUFDO0lBRUQsNkNBQTZDO0lBQzdDLElBQVcsUUFBUTtRQUNqQixPQUFPLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLElBQUksa0JBQWtCLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNwSixDQUFDO0lBRU0sVUFBVSxDQUFDLE9BQWU7UUFDL0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDckMsSUFBSSxJQUFJLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDdkIsTUFBTSxJQUFJLEtBQUssQ0FBQyxxQkFBcUIsT0FBTyxFQUFFLENBQUMsQ0FBQztRQUNsRCxDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDNUMsSUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQztZQUNuQyxPQUFPLE1BQU0sQ0FBQyxVQUFVLENBQUM7UUFDM0IsQ0FBQztRQUNELE1BQU0sVUFBVSxHQUFHLEdBQUcsQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLElBQUksQ0FBQyxDQUFDO1FBQ2xELElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ25ELE9BQU8sVUFBVSxDQUFDO0lBQ3BCLENBQUM7SUFFRCx1R0FBdUc7SUFDdkcsSUFBVyxzQkFBc0I7UUFDL0IsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDN0MsSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQ1YsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBQ0QsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDLHlCQUF5QixDQUFDLGVBQWUsRUFBRSxJQUFJLENBQUMsQ0FBQztRQUNuRSxPQUFPLE1BQU0sQ0FBQyxNQUFNLEVBQUUsZUFBZSxFQUFFLHNCQUFzQixLQUFLLElBQUksQ0FBQztJQUN6RSxDQUFDO0lBRUQsSUFBVyxRQUFRO1FBQ2pCLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLENBQUM7WUFDeEIsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFFLENBQUM7WUFDeEIsS0FBSyxNQUFNLElBQUksSUFBSSxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2pDLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3pDLE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBa0IsRUFBUSxFQUFFO29CQUN6QyxJQUFJLEVBQUUsQ0FBQyxrQkFBa0IsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUNuQyxNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsaUJBQWlCLENBQUMsT0FBTyxFQUFFLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQzt3QkFDcEUsSUFBSSxTQUFTLEVBQUUsQ0FBQzs0QkFDZCxNQUFNLFdBQVcsR0FBRyxTQUFTLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQzs0QkFDaEQsSUFBSSxDQUFDLGFBQWMsQ0FBQyxJQUFJLENBQUM7Z0NBQ3ZCLElBQUk7Z0NBQ0osVUFBVTtnQ0FDVixTQUFTLEVBQUUsT0FBTztnQ0FDbEIsU0FBUyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsSUFBSSxJQUFJLElBQUk7Z0NBQ3JDLGFBQWEsRUFBRSxTQUFTLENBQUMsSUFBSTtnQ0FDN0IsR0FBRyxFQUFFLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLElBQUksR0FBRyxDQUFDLG1CQUFtQixDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJO2dDQUM1RyxRQUFRLEVBQUUsR0FBRyxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxhQUFhLENBQUM7Z0NBQy9ELFVBQVUsRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDOzZCQUM3QixDQUFDLENBQUM7d0JBQ0wsQ0FBQztvQkFDSCxDQUFDO29CQUNELEVBQUUsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNsQyxDQUFDLENBQUM7Z0JBQ0YsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3BCLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDO0lBQzVCLENBQUM7SUFFRCxJQUFXLFVBQVU7UUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztZQUMxQixJQUFJLENBQUMsZUFBZSxHQUFHLEVBQUUsQ0FBQztZQUMxQixLQUFLLE1BQU0sSUFBSSxJQUFJLElBQUksQ0FBQyxRQUFRLEVBQUUsQ0FBQztnQkFDakMsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDekMsTUFBTSxLQUFLLEdBQUcsQ0FBQyxPQUFrQixFQUFRLEVBQUU7b0JBQ3pDLElBQUksRUFBRSxDQUFDLGtCQUFrQixDQUFDLE9BQU8sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxpQkFBaUIsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO3dCQUNwRSxLQUFLLE1BQU0sTUFBTSxJQUFJLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQzs0QkFDckMsTUFBTSxTQUFTLEdBQUcsR0FBRyxDQUFDLGlCQUFpQixDQUFDLE1BQU0sRUFBRSxDQUFDLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDOzRCQUN2RSxNQUFNLElBQUksR0FBRyxHQUFHLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxDQUFDOzRCQUN4QyxJQUFJLENBQUMsU0FBUyxJQUFJLElBQUksS0FBSyxJQUFJLEVBQUUsQ0FBQztnQ0FDaEMsU0FBUzs0QkFDWCxDQUFDOzRCQUNELE1BQU0sYUFBYSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxDQUFDOzRCQUNsRCxNQUFNLGFBQWEsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsbUJBQW1CLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDOzRCQUMzRSxJQUFJLENBQUMsZUFBZ0IsQ0FBQyxJQUFJLENBQUM7Z0NBQ3pCLElBQUk7Z0NBQ0osVUFBVTtnQ0FDVixTQUFTLEVBQUUsT0FBZ0M7Z0NBQzNDLE1BQU07Z0NBQ04sSUFBSSxFQUFFLGFBQWEsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUk7Z0NBQ2hFLFNBQVMsRUFBRSxTQUFTLENBQUMsSUFBNEI7Z0NBQ2pELElBQUksRUFBRSxTQUFTLENBQUMsSUFBSTtnQ0FDcEIsT0FBTyxFQUFFLGFBQWEsSUFBSSxFQUFFLENBQUMseUJBQXlCLENBQUMsYUFBYSxDQUFDLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsSUFBSTtnQ0FDNUYsY0FBYyxFQUFFLENBQUMsQ0FBQyxhQUFhLElBQUksQ0FBQyxFQUFFLENBQUMseUJBQXlCLENBQUMsYUFBYSxDQUFDO2dDQUMvRSxRQUFRLEVBQUUsQ0FBQyxhQUFhO3VDQUNuQixDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsY0FBYyxDQUFDO3VDQUN0RCxDQUFDLEdBQUcsQ0FBQyxXQUFXLENBQUMsTUFBTSxFQUFFLEVBQUUsQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUM7Z0NBQzdELFVBQVUsRUFBRSxVQUFVLENBQUMsSUFBSSxDQUFDOzZCQUM3QixDQUFDLENBQUM7d0JBQ0wsQ0FBQztvQkFDSCxDQUFDO29CQUNELEVBQUUsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLEtBQUssQ0FBQyxDQUFDO2dCQUNsQyxDQUFDLENBQUM7Z0JBQ0YsS0FBSyxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3BCLENBQUM7UUFDSCxDQUFDO1FBQ0QsT0FBTyxJQUFJLENBQUMsZUFBZSxDQUFDO0lBQzlCLENBQUM7SUFFRCwyRUFBMkU7SUFDcEUsU0FBUyxDQUFDLE9BQWU7UUFDOUIsSUFBSSxTQUFTLEdBQUcsSUFBSSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDakQsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1lBQ2YsU0FBUyxHQUFHLEVBQUUsQ0FBQztZQUNmLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztnQkFDNUIsS0FBSyxNQUFNLFNBQVMsSUFBSSxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDO29CQUM1RCxJQUFJLEVBQUUsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsSUFBSSxTQUFTLENBQUMsZUFBZSxJQUFJLEdBQUcsQ0FBQyxtQkFBbUIsQ0FBQyxTQUFTLENBQUMsZUFBZSxDQUFDLEVBQUUsQ0FBQzt3QkFDekgsTUFBTSxTQUFTLEdBQUcsU0FBUyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUM7d0JBQ2pELElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7NEJBQy9CLFNBQVM7d0JBQ1gsQ0FBQzt3QkFDRCxNQUFNLFFBQVEsR0FBRyxnQkFBZ0IsQ0FBQyxPQUFPLEVBQUUsU0FBUyxFQUFFLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDO3dCQUN0RyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQUUsTUFBTSxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7b0JBQzVGLENBQUM7Z0JBQ0gsQ0FBQztZQUNILENBQUM7WUFDRCxJQUFJLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDOUMsQ0FBQztRQUNELE9BQU8sU0FBUyxDQUFDO0lBQ25CLENBQUM7SUFFRCxrRkFBa0Y7SUFDM0UsYUFBYSxDQUFDLE9BQWU7UUFDbEMsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQVUsQ0FBQztRQUNsQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3ZELE9BQU8sS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUN4QixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsS0FBSyxFQUFHLENBQUM7WUFDNUIsSUFBSSxPQUFPLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7Z0JBQ3RCLFNBQVM7WUFDWCxDQUFDO1lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUNsQixLQUFLLE1BQU0sUUFBUSxJQUFJLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztnQkFDNUMsSUFBSSxRQUFRLENBQUMsTUFBTSxJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztvQkFDckQsS0FBSyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQzlCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELE9BQU8sT0FBTyxDQUFDO0lBQ2pCLENBQUM7SUFFTSxhQUFhLENBQUMsT0FBZSxFQUFFLFdBQW1CO1FBQ3ZELE9BQU8sR0FBRyxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLE9BQU8sQ0FBQyxFQUFFLFdBQVcsQ0FBQyxDQUFDO0lBQ2xFLENBQUM7Q0FDRjtBQUVELG1EQUFtRDtBQUNuRCxNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLGVBQWUsRUFBRSxpQkFBaUIsRUFBRSxlQUFlLEVBQUUsV0FBVyxDQUFDLENBQUM7QUFFcEcscUVBQXFFO0FBQ3JFLE1BQU0sQ0FBQyxNQUFNLG1CQUFtQixHQUFHLEtBQUssRUFBRSxVQUFrQixFQUE0QixFQUFFO0lBQ3hGLE1BQU0sS0FBSyxHQUFHLElBQUksR0FBRyxFQUFrQixDQUFDO0lBQ3hDLE1BQU0sTUFBTSxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQztJQUN2RCxJQUFJLE9BQU8sQ0FBQyxNQUFNLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUM7UUFDdEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxPQUFPLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxTQUFTLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDO1FBQzNGLEtBQUssTUFBTSxLQUFLLElBQUksT0FBTyxFQUFFLENBQUM7WUFDNUIsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsRUFBRSxDQUFDO2dCQUNwQixTQUFTO1lBQ1gsQ0FBQztZQUNELE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzdHLElBQUksUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLFVBQVUsS0FBSyxjQUFjLENBQUMsRUFBRSxDQUFDO2dCQUM1RSxTQUFTO1lBQ1gsQ0FBQztZQUNELElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO2dCQUM3RCxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxNQUFNLE9BQU8sQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDO1lBQ2xHLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUNELEtBQUssTUFBTSxRQUFRLElBQUksaUJBQWlCLEVBQUUsQ0FBQztRQUN6QyxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUM7UUFDekQsSUFBSSxPQUFPLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1lBQ3hDLEtBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sT0FBTyxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUM7UUFDbkUsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLElBQUksZUFBZSxDQUFDLEtBQUssRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUNwSCxDQUFDLENBQUMifQ==
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import * as ast from './helpers.ast.js';
|
|
3
|
+
import { StandardProject } from './classes.standardproject.js';
|
|
4
|
+
import type { IFixBuilder } from './rule.js';
|
|
5
|
+
/** The changes one rule run collected. */
|
|
6
|
+
export declare class FixBatch implements IFixBuilder {
|
|
7
|
+
readonly edits: Map<string, ast.ITextEdit[]>;
|
|
8
|
+
readonly creates: Map<string, string>;
|
|
9
|
+
readonly moves: Map<string, string>;
|
|
10
|
+
readonly redirects: Map<string, string>;
|
|
11
|
+
edit(fileArg: string, startArg: number, endArg: number, textArg: string): void;
|
|
12
|
+
create(fileArg: string, textArg: string): void;
|
|
13
|
+
move(fromArg: string, toArg: string): void;
|
|
14
|
+
redirectBarrelExports(targetArg: string, barrelTargetArg: string): void;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The fixer's in-memory copy of a repository: the tracked TypeScript sources and the side files the
|
|
18
|
+
* standard reads, with the moves and edits applied so far. Nothing touches the disk until the
|
|
19
|
+
* fixer commits the tree. Every path a batch names must be a repository path (see isRepoPath);
|
|
20
|
+
* a batch with any other path is rejected before it changes the tree.
|
|
21
|
+
*/
|
|
22
|
+
export declare class StandardTree {
|
|
23
|
+
readonly files: Map<string, string>;
|
|
24
|
+
private readonly originalTexts;
|
|
25
|
+
/** Current path → original path, for moved files. */
|
|
26
|
+
private readonly originOf;
|
|
27
|
+
/** Original paths that were moved away. */
|
|
28
|
+
private readonly vacated;
|
|
29
|
+
readonly created: Set<string>;
|
|
30
|
+
/** Current path → ids of the rules that changed the file. */
|
|
31
|
+
private readonly changedBy;
|
|
32
|
+
private readonly parseCache;
|
|
33
|
+
/** Every tracked file of the repository, including those the tree holds no text for (`.json`, `.css`, `.d.ts`, …). */
|
|
34
|
+
private readonly trackedFiles;
|
|
35
|
+
private readonly existsOnDisk;
|
|
36
|
+
constructor(filesArg: Map<string, string>, trackedFilesArg: Iterable<string>, existsOnDiskArg: (fileArg: string) => boolean);
|
|
37
|
+
exists(fileArg: string): boolean;
|
|
38
|
+
/** The model of the tree's current state. */
|
|
39
|
+
project(): StandardProject;
|
|
40
|
+
private markChanged;
|
|
41
|
+
/**
|
|
42
|
+
* Applies a batch: edits, then new files, then moves with import rewriting. Returns the number of
|
|
43
|
+
* applied changes. Throws without changing the tree when the batch names a path that is not a
|
|
44
|
+
* repository path.
|
|
45
|
+
*/
|
|
46
|
+
apply(ruleIdArg: string, batchArg: FixBatch): number;
|
|
47
|
+
/**
|
|
48
|
+
* Rewrites every relative module specifier whose importing file or target moves, keeping its
|
|
49
|
+
* extension style. A specifier resolves to any tracked file (sources, `.d.ts`, `.json`, `.css`, …),
|
|
50
|
+
* so a moved file's imports of files that stay keep pointing at them. Barrel re-exports of a
|
|
51
|
+
* redirected target point at the redirect instead.
|
|
52
|
+
*/
|
|
53
|
+
private rewriteSpecifiers;
|
|
54
|
+
/** The tree's changes against the repository it was read from. */
|
|
55
|
+
plan(): plugins.interfaces.IStandardFixPlan;
|
|
56
|
+
}
|