uql-codemod 0.48.1 → 0.49.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/README.md +27 -16
- package/dist/builders.d.ts +18 -0
- package/dist/builders.js +588 -0
- package/dist/classOptions.d.ts +9 -0
- package/dist/classOptions.js +240 -0
- package/dist/columnMethods.d.ts +11 -0
- package/dist/columnMethods.js +6 -0
- package/dist/columnRefs.js +3 -10
- package/dist/context.d.ts +18 -5
- package/dist/context.js +22 -4
- package/dist/definers.d.ts +24 -0
- package/dist/definers.js +34 -0
- package/dist/edits.d.ts +43 -11
- package/dist/edits.js +105 -26
- package/dist/entitySql.d.ts +15 -16
- package/dist/entitySql.js +33 -31
- package/dist/imports.d.ts +33 -16
- package/dist/imports.js +213 -99
- package/dist/index.d.ts +3 -3
- package/dist/index.js +9 -12
- package/dist/jsonIndex.d.ts +11 -0
- package/dist/jsonIndex.js +78 -0
- package/dist/keyMaps.d.ts +3 -1
- package/dist/keyMaps.js +5 -1
- package/dist/migrationBuilders.d.ts +13 -0
- package/dist/migrationBuilders.js +182 -0
- package/dist/relationTarget.d.ts +6 -0
- package/dist/relationTarget.js +21 -0
- package/dist/schemaEntity.d.ts +12 -0
- package/dist/schemaEntity.js +518 -0
- package/dist/schemaOptions.d.ts +6 -0
- package/dist/schemaOptions.js +6 -0
- package/dist/statementSql.d.ts +2 -1
- package/dist/statementSql.js +10 -4
- package/dist/syntax.d.ts +54 -0
- package/dist/syntax.js +131 -1
- package/dist/transform.d.ts +11 -2
- package/dist/transform.js +174 -165
- package/dist/tsconfig.d.ts +3 -9
- package/dist/tsconfig.js +18 -22
- package/package.json +1 -1
- package/dist/fieldType.d.ts +0 -13
- package/dist/fieldType.js +0 -56
package/dist/edits.js
CHANGED
|
@@ -1,17 +1,84 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import { lineStartOf } from './syntax.js';
|
|
3
|
+
/** The text of `node` as written, for a replacement to keep. */
|
|
4
|
+
export function original(node) {
|
|
5
|
+
return { start: node.getStart(), end: node.getEnd() };
|
|
6
|
+
}
|
|
7
|
+
const isInsertion = (edit) => edit.start === edit.end;
|
|
8
|
+
/**
|
|
9
|
+
* Applies edits to `source`, which is spliced rather than reprinted: a codemod that reformats everything it
|
|
10
|
+
* touches buries its own change in the diff. An edit inside a range another replaces is moot, unless that
|
|
11
|
+
* replacement keeps the stretch it sits in; edits that overlap without one holding the other are a bug.
|
|
12
|
+
*/
|
|
13
|
+
export function applyEdits(source, edits) {
|
|
14
|
+
return editedText(source, edits).text;
|
|
15
|
+
}
|
|
16
|
+
/** `text` as a pass that changed nothing. */
|
|
17
|
+
export const unedited = (text) => ({ text, sourceOffset: (at) => at });
|
|
18
|
+
/** `second` run on what `first` wrote, each offset of its text mapped back to what `first` read. */
|
|
19
|
+
export function followed(first, second) {
|
|
20
|
+
return { text: second.text, sourceOffset: (at) => first.sourceOffset(second.sourceOffset(at)) };
|
|
21
|
+
}
|
|
22
|
+
/** `pass` edited again by `edits`, which read its text. */
|
|
23
|
+
function editedAgain(pass, edits) {
|
|
24
|
+
return followed(pass, editedText(pass.text, edits));
|
|
25
|
+
}
|
|
26
|
+
/** `pass` edited again by the edits `edits` reads off its text, parsed. */
|
|
27
|
+
export function reparsedAgain(fileName, pass, edits) {
|
|
28
|
+
return editedAgain(pass, edits(ts.createSourceFile(fileName, pass.text, ts.ScriptTarget.Latest, true)));
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* {@link applyEdits}, with where each offset of the result was in `source`, for a later pass reading the result to
|
|
32
|
+
* report against the file as written: an offset inside an edit's text maps to where the edit starts.
|
|
33
|
+
*/
|
|
34
|
+
export function editedText(source, edits) {
|
|
35
|
+
const moved = [];
|
|
36
|
+
const ordered = edits
|
|
37
|
+
.map((edit, index) => ({ edit, index }))
|
|
38
|
+
.sort((a, b) => a.edit.start - b.edit.start ||
|
|
39
|
+
Number(!isInsertion(a.edit)) - Number(!isInsertion(b.edit)) ||
|
|
40
|
+
(isInsertion(a.edit) ? b.index - a.index : b.edit.end - a.edit.end))
|
|
41
|
+
.map(({ edit }) => edit);
|
|
42
|
+
const text = render(source, ordered, { start: 0, end: source.length }, undefined, moved);
|
|
43
|
+
const sourceOffset = (at) => {
|
|
44
|
+
const before = moved.findLast((edit) => edit.from <= at);
|
|
45
|
+
if (!before)
|
|
46
|
+
return at;
|
|
47
|
+
return at < before.to ? before.start : before.end + at - before.to;
|
|
48
|
+
};
|
|
49
|
+
return { text, sourceOffset };
|
|
50
|
+
}
|
|
1
51
|
/**
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
*
|
|
52
|
+
* `range` of `source` with `edits` (ordered outermost first, an insertion before a replacement at its offset, a
|
|
53
|
+
* later insertion before an earlier) applied. `parent` is the edit keeping `range`: an insertion at its edges
|
|
54
|
+
* is written beside it, so it is not written again inside.
|
|
5
55
|
*/
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
56
|
+
function render(source, edits, range, parent, moved) {
|
|
57
|
+
const within = (edit) => edit !== parent &&
|
|
58
|
+
range.start <= edit.start &&
|
|
59
|
+
edit.end <= range.end &&
|
|
60
|
+
!(parent && isInsertion(edit) && (edit.start === parent.start || edit.start === parent.end));
|
|
61
|
+
const inside = edits.filter(within);
|
|
62
|
+
let written = '';
|
|
63
|
+
let at = range.start;
|
|
64
|
+
for (const edit of inside) {
|
|
65
|
+
if (edit.start < at) {
|
|
66
|
+
if (edit.end > at) {
|
|
67
|
+
throw new Error(`overlapping edits at ${edit.start}`);
|
|
68
|
+
}
|
|
69
|
+
continue;
|
|
70
|
+
}
|
|
71
|
+
const parts = typeof edit.text === 'string' ? [edit.text] : edit.text;
|
|
72
|
+
written += source.slice(at, edit.start);
|
|
73
|
+
const from = written.length;
|
|
74
|
+
written += parts.map((part) => (typeof part === 'string' ? part : render(source, inside, part, edit))).join('');
|
|
75
|
+
moved?.push({ start: edit.start, end: edit.end, from, to: written.length });
|
|
76
|
+
at = edit.end;
|
|
10
77
|
}
|
|
11
|
-
return
|
|
78
|
+
return written + source.slice(at, range.end);
|
|
12
79
|
}
|
|
13
80
|
export function replaced(node, text) {
|
|
14
|
-
return {
|
|
81
|
+
return { ...original(node), text };
|
|
15
82
|
}
|
|
16
83
|
export function inserted(node, text) {
|
|
17
84
|
return { start: node.getStart(), end: node.getStart(), text };
|
|
@@ -19,25 +86,37 @@ export function inserted(node, text) {
|
|
|
19
86
|
export function appended(node, text) {
|
|
20
87
|
return { start: node.getEnd(), end: node.getEnd(), text };
|
|
21
88
|
}
|
|
89
|
+
/** `node`'s text with each of `uses`, the nodes inside it, written as `text`. */
|
|
90
|
+
export function replacingUses(node, uses, text) {
|
|
91
|
+
return applyEdits(node.getText(), uses.map((use) => ({ start: use.getStart() - node.getStart(), end: use.getEnd() - node.getStart(), text })));
|
|
92
|
+
}
|
|
22
93
|
/**
|
|
23
|
-
* Removes
|
|
24
|
-
*
|
|
25
|
-
*
|
|
94
|
+
* Removes elements of a comma-separated list, at least one of them kept, with the separators that would dangle.
|
|
95
|
+
* Each removed element takes the text up to the next item; the removed run at the end takes the separator before
|
|
96
|
+
* it, so the ranges never overlap. `source` is passed because a tree from `ts.parseJsonText` has no `getStart()`.
|
|
26
97
|
*/
|
|
27
|
-
export function removeFromList(items,
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
98
|
+
export function removeFromList(items, removed, source) {
|
|
99
|
+
const kept = items.map((item) => !removed.includes(item));
|
|
100
|
+
const lastKept = kept.lastIndexOf(true);
|
|
101
|
+
const between = items
|
|
102
|
+
.slice(0, lastKept + 1)
|
|
103
|
+
.flatMap((item, at) => kept[at] ? [] : [{ start: item.getStart(source), end: items[at + 1].getStart(source), text: '' }]);
|
|
104
|
+
const trailing = items.slice(lastKept + 1);
|
|
105
|
+
if (!trailing.length) {
|
|
106
|
+
return between;
|
|
107
|
+
}
|
|
108
|
+
return [...between, { start: items[lastKept].getEnd(), end: items[items.length - 1].getEnd(), text: '' }];
|
|
36
109
|
}
|
|
37
|
-
/**
|
|
110
|
+
/**
|
|
111
|
+
* Removes a statement with the blanks before it on its line, the rest of its line and the blank lines after it,
|
|
112
|
+
* so nothing is left blank behind it.
|
|
113
|
+
*/
|
|
38
114
|
export function removeStatement(node) {
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
115
|
+
const text = node.getSourceFile().text;
|
|
116
|
+
const lineStart = lineStartOf(text, node.getStart());
|
|
117
|
+
const head = text.slice(lineStart, node.getStart());
|
|
118
|
+
const after = /[^\n]*\n?(?:[ \t]*\n)*/y;
|
|
119
|
+
after.lastIndex = node.getEnd();
|
|
120
|
+
after.exec(text);
|
|
121
|
+
return { start: lineStart + head.replace(/[ \t]*$/, '').length, end: after.lastIndex, text: '' };
|
|
43
122
|
}
|
package/dist/entitySql.d.ts
CHANGED
|
@@ -1,22 +1,21 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import { type Edit } from './edits.js';
|
|
3
|
-
/** `
|
|
4
|
-
type
|
|
5
|
-
export declare function
|
|
6
|
-
/** The expressions of a column list, written as one or returned by its callback: each entry or `column` that is `
|
|
7
|
-
export declare function columnExpressions(list: ts.Expression | undefined): readonly
|
|
8
|
-
/** SQL text as a
|
|
9
|
-
export declare function
|
|
10
|
-
/**
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export declare function rawWhereEdit(where: ts.Expression): Edit | undefined;
|
|
2
|
+
import { type Edit, type Part, type Span } from './edits.js';
|
|
3
|
+
/** `sql\`...\`` or `sql(...)`, or the deprecated `raw` of either. */
|
|
4
|
+
type SqlCall = ts.TaggedTemplateExpression | ts.CallExpression;
|
|
5
|
+
export declare function isSqlCall(node: ts.Node, checker: ts.TypeChecker): node is SqlCall;
|
|
6
|
+
/** The expressions of a column list, written as one or returned by its callback: each entry or `column` that is `sql`. */
|
|
7
|
+
export declare function columnExpressions(list: ts.Expression | undefined, checker: ts.TypeChecker): readonly SqlCall[];
|
|
8
|
+
/** SQL text as a template tagged by `name`, escaping what would end or interpolate it. */
|
|
9
|
+
export declare function sqlTag(name: string, sql: string): string;
|
|
10
|
+
/** `text` as a template literal binding nothing: a backslash, a backtick and a `${` in it are escaped. */
|
|
11
|
+
export declare function templateOf(text: string): string;
|
|
12
|
+
/** A template literal reading `texts`, the `values` kept from the original interpolated between them. */
|
|
13
|
+
export declare function templateWith(texts: readonly string[], values: readonly Span[]): readonly Part[];
|
|
14
|
+
/** A partial-index `where` string as `sql`, or nothing for a template that interpolates, whose values `sql` would bind. */
|
|
15
|
+
export declare function sqlWhereEdit(where: ts.Expression, name: string): Edit | undefined;
|
|
17
16
|
/**
|
|
18
17
|
* The columns SQL names by hand, which a rename does not reach: each quoted identifier, and each bare word
|
|
19
18
|
* naming one of `members`. What a string literal holds is left out, as is a word called as a function.
|
|
20
19
|
*/
|
|
21
|
-
export declare function handNamedColumns(sql: ts.Expression, members: ReadonlySet<string
|
|
20
|
+
export declare function handNamedColumns(sql: ts.Expression, members: ReadonlySet<string>, checker: ts.TypeChecker): readonly string[];
|
|
22
21
|
export {};
|
package/dist/entitySql.js
CHANGED
|
@@ -1,60 +1,62 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
2
|
import { inserted, replaced } from './edits.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import { isSqlExport, uqlExport } from './imports.js';
|
|
4
|
+
import { columnListEntries, propertyValue } from './syntax.js';
|
|
5
|
+
export function isSqlCall(node, checker) {
|
|
5
6
|
const callee = ts.isTaggedTemplateExpression(node)
|
|
6
7
|
? node.tag
|
|
7
8
|
: ts.isCallExpression(node)
|
|
8
9
|
? node.expression
|
|
9
10
|
: undefined;
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
const body = list && ts.isArrowFunction(list) ? list.body : list;
|
|
16
|
-
const entries = body && ts.isArrayLiteralExpression(body) ? body.elements : [];
|
|
17
|
-
return entries.flatMap((entry) => {
|
|
11
|
+
return isSqlExport(uqlExport(callee, checker));
|
|
12
|
+
}
|
|
13
|
+
/** The expressions of a column list, written as one or returned by its callback: each entry or `column` that is `sql`. */
|
|
14
|
+
export function columnExpressions(list, checker) {
|
|
15
|
+
return columnListEntries(list).flatMap((entry) => {
|
|
18
16
|
const sql = ts.isObjectLiteralExpression(entry) ? propertyValue(entry, 'column') : entry;
|
|
19
|
-
return sql &&
|
|
17
|
+
return sql && isSqlCall(sql, checker) ? [sql] : [];
|
|
20
18
|
});
|
|
21
19
|
}
|
|
22
|
-
/** SQL text as a
|
|
23
|
-
export function
|
|
24
|
-
return
|
|
20
|
+
/** SQL text as a template tagged by `name`, escaping what would end or interpolate it. */
|
|
21
|
+
export function sqlTag(name, sql) {
|
|
22
|
+
return `${name}${templateOf(sql)}`;
|
|
25
23
|
}
|
|
26
|
-
/**
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
/** `text` as a template literal binding nothing: a backslash, a backtick and a `${` in it are escaped. */
|
|
25
|
+
export function templateOf(text) {
|
|
26
|
+
return `\`${escapedIn(text)}\``;
|
|
27
|
+
}
|
|
28
|
+
/** A template literal reading `texts`, the `values` kept from the original interpolated between them. */
|
|
29
|
+
export function templateWith(texts, values) {
|
|
30
|
+
const [first, ...rest] = texts.map(escapedIn);
|
|
31
|
+
return ['`', first, ...rest.flatMap((text, at) => ['${', values[at], '}', text]), '`'];
|
|
32
|
+
}
|
|
33
|
+
function escapedIn(text) {
|
|
34
|
+
return text.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
|
|
33
35
|
}
|
|
34
|
-
/** A partial-index `where` string as `
|
|
35
|
-
export function
|
|
36
|
+
/** A partial-index `where` string as `sql`, or nothing for a template that interpolates, whose values `sql` would bind. */
|
|
37
|
+
export function sqlWhereEdit(where, name) {
|
|
36
38
|
if (ts.isNoSubstitutionTemplateLiteral(where)) {
|
|
37
|
-
return inserted(where,
|
|
39
|
+
return inserted(where, name);
|
|
38
40
|
}
|
|
39
|
-
return ts.isStringLiteral(where) ? replaced(where,
|
|
41
|
+
return ts.isStringLiteral(where) ? replaced(where, sqlTag(name, where.text)) : undefined;
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
44
|
* The columns SQL names by hand, which a rename does not reach: each quoted identifier, and each bare word
|
|
43
45
|
* naming one of `members`. What a string literal holds is left out, as is a word called as a function.
|
|
44
46
|
*/
|
|
45
|
-
export function handNamedColumns(sql, members) {
|
|
46
|
-
const code = sqlText(sql)?.replace(/'(?:[^']|'')*'/g, "''") ?? '';
|
|
47
|
+
export function handNamedColumns(sql, members, checker) {
|
|
48
|
+
const code = sqlText(sql, checker)?.replace(/'(?:[^']|'')*'/g, "''") ?? '';
|
|
47
49
|
const quoted = Array.from(code.matchAll(/"[^"]+"|`[^`]+`/g), ([token]) => token.slice(1, -1));
|
|
48
50
|
const bare = Array.from(code.matchAll(/\b[A-Za-z_]\w*\b(?!\s*\()/g), ([word]) => word);
|
|
49
51
|
return [...new Set([...quoted, ...bare.filter((word) => members.has(word))])];
|
|
50
52
|
}
|
|
51
|
-
/** The text of a `
|
|
52
|
-
function sqlText(sql) {
|
|
53
|
+
/** The text of a `sql` or a string, `?` standing in for each interpolation. */
|
|
54
|
+
function sqlText(sql, checker) {
|
|
53
55
|
if (!sql) {
|
|
54
56
|
return undefined;
|
|
55
57
|
}
|
|
56
|
-
if (
|
|
57
|
-
return sqlText(ts.isTaggedTemplateExpression(sql) ? sql.template : sql.arguments[0]);
|
|
58
|
+
if (isSqlCall(sql, checker)) {
|
|
59
|
+
return sqlText(ts.isTaggedTemplateExpression(sql) ? sql.template : sql.arguments[0], checker);
|
|
58
60
|
}
|
|
59
61
|
if (ts.isTemplateExpression(sql)) {
|
|
60
62
|
return [sql.head, ...sql.templateSpans.map((span) => span.literal)].map((part) => part.text).join(' ? ');
|
package/dist/imports.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import type
|
|
2
|
+
import { type Context } from './context.js';
|
|
3
|
+
import { type Edit } from './edits.js';
|
|
4
|
+
/** The name `uql-orm` gave its SQL tag, and gives it now. */
|
|
5
|
+
export declare const LEGACY_SQL_TAG = "raw";
|
|
6
|
+
export declare const SQL_TAG = "sql";
|
|
3
7
|
type UqlImport = {
|
|
4
8
|
readonly declaration: ts.ImportDeclaration;
|
|
5
9
|
readonly entry: string;
|
|
@@ -14,27 +18,40 @@ export declare function uqlImportDeclarations(source: ts.SourceFile, entries?: b
|
|
|
14
18
|
export declare function uqlImport(source: ts.SourceFile, name: string, entries?: boolean): ts.ImportSpecifier | undefined;
|
|
15
19
|
/** Every identifier in the file bound to the same symbol as `name`, besides `name` itself. */
|
|
16
20
|
export declare function usesOf(source: ts.SourceFile, name: ts.Identifier, checker: ts.TypeChecker): ts.Identifier[];
|
|
21
|
+
/** The names among `names` the file binds or reads as something other than uql-orm's export, which a rewrite would shadow. */
|
|
22
|
+
export declare function foreignNames(source: ts.SourceFile, names: ReadonlySet<string>, checker: ts.TypeChecker): ReadonlySet<string>;
|
|
17
23
|
/** Names an export that no longer exists, where it is imported from the package or one of its entries. */
|
|
18
24
|
export declare function reportRemovedExports(ctx: Context): void;
|
|
25
|
+
/** The imported names of `REWRITTEN` the codemod removes, once every use was rewritten. */
|
|
26
|
+
export declare function deadImportNames(ctx: Context): ReadonlySet<string>;
|
|
27
|
+
/** The `uql-orm` export `node` names, where its symbol is an import of it or of one of its entries. */
|
|
28
|
+
export declare function uqlExport(node: ts.Node | undefined, checker: ts.TypeChecker): string | undefined;
|
|
29
|
+
/** Whether `name` is the SQL tag, by either of its names. */
|
|
30
|
+
export declare function isSqlExport(name: string | undefined): boolean;
|
|
31
|
+
/** The name the file calls the SQL tag by once `raw` is renamed: the alias it imports it as, else `sql`. */
|
|
32
|
+
export declare function sqlName(source: ts.SourceFile): string;
|
|
19
33
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
* as is a `dead` one. Returns the rewritten imports, which nothing else may edit.
|
|
23
|
-
*/
|
|
24
|
-
export declare function renameExports(dead: ReadonlySet<string>, ctx: Context): ReadonlySet<ts.ImportDeclaration>;
|
|
25
|
-
/**
|
|
26
|
-
* The imported names the codemod removes once every use was rewritten: `Relation` unwrapped and `expr` defaults.
|
|
27
|
-
* A removed decorator keeps its import on purpose: deleting it would swap a clear error for a puzzling one.
|
|
34
|
+
* The first identifier of the file already naming something a rewrite writes: a name it imports (`sql`, `refs`,
|
|
35
|
+
* `idKey`) or a rename brings in. The write would shadow it or be shadowed, so the file is left to its owner.
|
|
28
36
|
*/
|
|
29
|
-
export declare function
|
|
37
|
+
export declare function clashingName(ctx: Context): ts.Identifier | undefined;
|
|
30
38
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
39
|
+
* Rewrites the file's imports in one pass: a name {@link RENAMED_EXPORTS} renames or a {@link MOVED_ENTRIES} entry
|
|
40
|
+
* moves is imported again where it lives now, every use renamed, and one already imported or `dead` is dropped.
|
|
41
|
+
* The names the rewrites wrote join the first `uql-orm` import, or are reported when there is none.
|
|
33
42
|
*/
|
|
34
|
-
export declare function
|
|
43
|
+
export declare function rewriteImports(dead: ReadonlySet<string>, ctx: Context): void;
|
|
44
|
+
/** An import of `names` from `from`, quoted as the file quotes its imports. */
|
|
45
|
+
export declare const importText: (keyword: string, names: readonly string[], from: string, quote?: string) => string;
|
|
35
46
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
47
|
+
* The import without `dropped` of its `elements`: the whole statement where nothing else is left of it, and the
|
|
48
|
+
* braces with them where a default import stays.
|
|
38
49
|
*/
|
|
39
|
-
export declare function
|
|
50
|
+
export declare function importRemovalEdits(declaration: ts.ImportDeclaration, elements: readonly ts.ImportSpecifier[], dropped: readonly ts.ImportSpecifier[]): readonly Edit[];
|
|
51
|
+
/** Every name the file spells outside its imports, which an import it binds is still used under if listed here. */
|
|
52
|
+
export declare function spelledNames(source: ts.SourceFile): ReadonlySet<string>;
|
|
53
|
+
/** The import names in `candidates` that the file no longer spells. */
|
|
54
|
+
export declare function deadImports(elements: readonly ts.ImportSpecifier[], candidates: ReadonlySet<string | undefined>, spelled: ReadonlySet<string>): readonly ts.ImportSpecifier[];
|
|
55
|
+
/** The edits dropping each `uql-orm` import name in `candidates` that the file no longer spells. */
|
|
56
|
+
export declare function unusedImportEdits(source: ts.SourceFile, candidates: ReadonlySet<string>): readonly Edit[];
|
|
40
57
|
export {};
|