@ttsc/factory 0.19.2 → 0.20.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 +2 -0
- package/lib/TsPrinter.d.ts +124 -17
- package/lib/TsPrinter.js +414 -106
- package/lib/TsPrinter.js.map +1 -1
- package/lib/TsPrinter.mjs +413 -107
- package/lib/TsPrinter.mjs.map +1 -1
- package/lib/ast/expressions/Expression.d.ts +5 -1
- package/lib/ast/imports/ImportClause.d.ts +10 -2
- package/lib/ast/jsdoc/JSDocImportTag.d.ts +3 -0
- package/lib/ast/types/ImportTypeNode.d.ts +3 -0
- package/lib/factory/expressions/createComma.d.ts +3 -3
- package/lib/factory/expressions/createComma.js +3 -3
- package/lib/factory/expressions/createComma.mjs +3 -3
- package/lib/factory/imports/createImportClause.d.ts +9 -3
- package/lib/factory/imports/createImportClause.js +8 -3
- package/lib/factory/imports/createImportClause.js.map +1 -1
- package/lib/factory/imports/createImportClause.mjs +8 -3
- package/lib/factory/imports/createImportClause.mjs.map +1 -1
- package/lib/factory/jsdoc/createJSDocImportTag.d.ts +3 -2
- package/lib/factory/jsdoc/createJSDocImportTag.js +3 -1
- package/lib/factory/jsdoc/createJSDocImportTag.js.map +1 -1
- package/lib/factory/jsdoc/createJSDocImportTag.mjs +3 -1
- package/lib/factory/jsdoc/createJSDocImportTag.mjs.map +1 -1
- package/lib/factory/types/createImportTypeNode.d.ts +8 -2
- package/lib/factory/types/createImportTypeNode.js +13 -1
- package/lib/factory/types/createImportTypeNode.js.map +1 -1
- package/lib/factory/types/createImportTypeNode.mjs +13 -1
- package/lib/factory/types/createImportTypeNode.mjs.map +1 -1
- package/lib/internal/doc.d.ts +13 -0
- package/lib/internal/doc.js +31 -4
- package/lib/internal/doc.js.map +1 -1
- package/lib/internal/doc.mjs +30 -4
- package/lib/internal/doc.mjs.map +1 -1
- package/lib/syntax/NodeFlags.d.ts +6 -4
- package/lib/syntax/NodeFlags.js +6 -4
- package/lib/syntax/NodeFlags.js.map +1 -1
- package/lib/syntax/NodeFlags.mjs +6 -4
- package/lib/syntax/NodeFlags.mjs.map +1 -1
- package/lib/syntax/SyntaxKind.d.ts +2 -0
- package/lib/syntax/SyntaxKind.js +6 -0
- package/lib/syntax/SyntaxKind.js.map +1 -1
- package/lib/syntax/SyntaxKind.mjs +6 -0
- package/lib/syntax/SyntaxKind.mjs.map +1 -1
- package/package.json +1 -1
- package/src/TsPrinter.ts +489 -121
- package/src/ast/expressions/Expression.ts +8 -0
- package/src/ast/imports/ImportClause.ts +10 -2
- package/src/ast/jsdoc/JSDocImportTag.ts +4 -0
- package/src/ast/types/ImportTypeNode.ts +4 -0
- package/src/factory/expressions/createComma.ts +3 -3
- package/src/factory/imports/createImportClause.ts +12 -6
- package/src/factory/jsdoc/createJSDocImportTag.ts +5 -1
- package/src/factory/types/createImportTypeNode.ts +21 -3
- package/src/internal/doc.ts +30 -3
- package/src/syntax/NodeFlags.ts +6 -4
- package/src/syntax/SyntaxKind.ts +7 -0
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import type { JsxElement } from "../jsx/JsxElement";
|
|
2
|
+
import type { JsxFragment } from "../jsx/JsxFragment";
|
|
3
|
+
import type { JsxSelfClosingElement } from "../jsx/JsxSelfClosingElement";
|
|
1
4
|
import type { Identifier } from "../names/Identifier";
|
|
2
5
|
import type { Token } from "../names/Token";
|
|
3
6
|
import type { ArrayLiteralExpression } from "./ArrayLiteralExpression";
|
|
@@ -24,6 +27,7 @@ import type { NumericLiteral } from "./NumericLiteral";
|
|
|
24
27
|
import type { ObjectLiteralExpression } from "./ObjectLiteralExpression";
|
|
25
28
|
import type { OmittedExpression } from "./OmittedExpression";
|
|
26
29
|
import type { ParenthesizedExpression } from "./ParenthesizedExpression";
|
|
30
|
+
import type { PartiallyEmittedExpression } from "./PartiallyEmittedExpression";
|
|
27
31
|
import type { PostfixUnaryExpression } from "./PostfixUnaryExpression";
|
|
28
32
|
import type { PrefixUnaryExpression } from "./PrefixUnaryExpression";
|
|
29
33
|
import type { PropertyAccessChain } from "./PropertyAccessChain";
|
|
@@ -61,6 +65,9 @@ export type Expression =
|
|
|
61
65
|
| ElementAccessExpression
|
|
62
66
|
| FunctionExpression
|
|
63
67
|
| Identifier
|
|
68
|
+
| JsxElement
|
|
69
|
+
| JsxFragment
|
|
70
|
+
| JsxSelfClosingElement
|
|
64
71
|
| MetaProperty
|
|
65
72
|
| NewExpression
|
|
66
73
|
| NoSubstitutionTemplateLiteral
|
|
@@ -70,6 +77,7 @@ export type Expression =
|
|
|
70
77
|
| ObjectLiteralExpression
|
|
71
78
|
| OmittedExpression
|
|
72
79
|
| ParenthesizedExpression
|
|
80
|
+
| PartiallyEmittedExpression
|
|
73
81
|
| PostfixUnaryExpression
|
|
74
82
|
| PrefixUnaryExpression
|
|
75
83
|
| PropertyAccessChain
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { SyntaxKind } from "../../syntax";
|
|
1
2
|
import type { Identifier } from "../names/Identifier";
|
|
2
3
|
import type { NamedImports } from "./NamedImports";
|
|
3
4
|
import type { NamespaceImport } from "./NamespaceImport";
|
|
@@ -13,8 +14,15 @@ export interface ImportClause {
|
|
|
13
14
|
/** Discriminant tag; always `"ImportClause"`. */
|
|
14
15
|
kind: "ImportClause";
|
|
15
16
|
|
|
16
|
-
/**
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* The keyword between `import` and the bindings, when there is one.
|
|
19
|
+
*
|
|
20
|
+
* `TypeKeyword` is the type-only import; `DeferKeyword` is `import defer`.
|
|
21
|
+
* Upstream calls the pair `ImportPhaseModifierSyntaxKind`, and this field
|
|
22
|
+
* replaced a `isTypeOnly: boolean` that could not express the second phase at
|
|
23
|
+
* all.
|
|
24
|
+
*/
|
|
25
|
+
phaseModifier?: SyntaxKind.TypeKeyword | SyntaxKind.DeferKeyword;
|
|
18
26
|
|
|
19
27
|
/** The name. */
|
|
20
28
|
name?: Identifier;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Expression } from "../expressions/Expression";
|
|
2
|
+
import type { ImportAttributes } from "../imports/ImportAttributes";
|
|
2
3
|
import type { ImportClause } from "../imports/ImportClause";
|
|
3
4
|
import type { Identifier } from "../names/Identifier";
|
|
4
5
|
import type { JSDocComment } from "./JSDocComment";
|
|
@@ -23,6 +24,9 @@ export interface JSDocImportTag {
|
|
|
23
24
|
/** The module specifier. */
|
|
24
25
|
moduleSpecifier: Expression;
|
|
25
26
|
|
|
27
|
+
/** The `with { … }` import attributes, if any. */
|
|
28
|
+
attributes?: ImportAttributes;
|
|
29
|
+
|
|
26
30
|
/** The trailing comment, if any. */
|
|
27
31
|
comment?: string | readonly JSDocComment[];
|
|
28
32
|
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ImportAttributes } from "../imports/ImportAttributes";
|
|
1
2
|
import type { EntityName } from "../names/EntityName";
|
|
2
3
|
import type { TypeNode } from "./TypeNode";
|
|
3
4
|
|
|
@@ -15,6 +16,9 @@ export interface ImportTypeNode {
|
|
|
15
16
|
/** Argument. */
|
|
16
17
|
argument: TypeNode;
|
|
17
18
|
|
|
19
|
+
/** The `with { … }` import attributes, if any. */
|
|
20
|
+
attributes?: ImportAttributes;
|
|
21
|
+
|
|
18
22
|
/** Qualifier. */
|
|
19
23
|
qualifier?: EntityName;
|
|
20
24
|
|
|
@@ -7,9 +7,9 @@ import { createBinaryExpression } from "./createBinaryExpression";
|
|
|
7
7
|
* which evaluates both operands and yields the right one.
|
|
8
8
|
*
|
|
9
9
|
* Shorthand for {@link createBinaryExpression} with the `CommaToken` operator.
|
|
10
|
-
* The
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* The comma attaches to the operand before it, the way every other producer
|
|
11
|
+
* writes it — {@link createCommaListExpression}, the legacy printer, and
|
|
12
|
+
* Prettier all emit `a, b`.
|
|
13
13
|
*
|
|
14
14
|
* Given operands `a` and `b`, the printer emits:
|
|
15
15
|
*
|
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
NamedImports,
|
|
5
5
|
NamespaceImport,
|
|
6
6
|
} from "../../ast";
|
|
7
|
+
import { SyntaxKind } from "../../syntax";
|
|
7
8
|
import { make } from "../internal/make";
|
|
8
9
|
|
|
9
10
|
/**
|
|
@@ -13,7 +14,12 @@ import { make } from "../internal/make";
|
|
|
13
14
|
* The `name` is the default-import binding, if any. The `namedBindings` slot
|
|
14
15
|
* holds either a {@link NamedImports} brace group or a {@link NamespaceImport}. A
|
|
15
16
|
* default binding and named bindings can appear together, joined by a comma.
|
|
16
|
-
*
|
|
17
|
+
*
|
|
18
|
+
* The `phaseModifier` is the keyword between `import` and the bindings:
|
|
19
|
+
* `SyntaxKind.TypeKeyword` for a type-only import, `SyntaxKind.DeferKeyword`
|
|
20
|
+
* for `import defer`. Upstream calls the pair `ImportPhaseModifierSyntaxKind`
|
|
21
|
+
* and takes it in this position; this factory took a boolean here, which read a
|
|
22
|
+
* modern first argument as `isTypeOnly` and could not express `defer` at all.
|
|
17
23
|
*
|
|
18
24
|
* Given a default binding `Def` plus named import `a`, this prints:
|
|
19
25
|
*
|
|
@@ -22,13 +28,13 @@ import { make } from "../internal/make";
|
|
|
22
28
|
* ```
|
|
23
29
|
*
|
|
24
30
|
* @author Jeongho Nam - https://github.com/samchon
|
|
25
|
-
* @param
|
|
31
|
+
* @param phaseModifier The `type` or `defer` keyword, if any.
|
|
26
32
|
* @param name The name.
|
|
27
33
|
* @param namedBindings The named or namespace bindings, if any.
|
|
28
34
|
* @returns The created {@link ImportClause}.
|
|
29
35
|
*/
|
|
30
36
|
export const createImportClause = (
|
|
31
|
-
|
|
32
|
-
name
|
|
33
|
-
namedBindings
|
|
34
|
-
): ImportClause => make("ImportClause", {
|
|
37
|
+
phaseModifier?: SyntaxKind.TypeKeyword | SyntaxKind.DeferKeyword,
|
|
38
|
+
name?: Identifier,
|
|
39
|
+
namedBindings?: NamedImports | NamespaceImport,
|
|
40
|
+
): ImportClause => make("ImportClause", { phaseModifier, name, namedBindings });
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type {
|
|
2
2
|
Expression,
|
|
3
3
|
Identifier,
|
|
4
|
+
ImportAttributes,
|
|
4
5
|
ImportClause,
|
|
5
6
|
JSDocComment,
|
|
6
7
|
JSDocImportTag,
|
|
@@ -27,6 +28,7 @@ import { createIdentifier } from "../names/createIdentifier";
|
|
|
27
28
|
* @param tagName The tag name; defaults to `import`.
|
|
28
29
|
* @param importClause The import clause, if any.
|
|
29
30
|
* @param moduleSpecifier The module specifier.
|
|
31
|
+
* @param attributes The `with { … }` import attributes, if any.
|
|
30
32
|
* @param comment The trailing comment, if any.
|
|
31
33
|
* @returns The created {@link JSDocImportTag}.
|
|
32
34
|
*/
|
|
@@ -34,11 +36,13 @@ export const createJSDocImportTag = (
|
|
|
34
36
|
tagName: Identifier | undefined,
|
|
35
37
|
importClause: ImportClause | undefined,
|
|
36
38
|
moduleSpecifier: Expression,
|
|
37
|
-
|
|
39
|
+
attributes?: ImportAttributes,
|
|
40
|
+
comment?: readonly JSDocComment[],
|
|
38
41
|
): JSDocImportTag =>
|
|
39
42
|
make("JSDocImportTag", {
|
|
40
43
|
tagName: tagName ?? createIdentifier("import"),
|
|
41
44
|
importClause,
|
|
42
45
|
moduleSpecifier,
|
|
46
|
+
attributes,
|
|
43
47
|
comment,
|
|
44
48
|
});
|
|
@@ -1,9 +1,20 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
EntityName,
|
|
3
|
+
ImportAttributes,
|
|
4
|
+
ImportTypeNode,
|
|
5
|
+
TypeNode,
|
|
6
|
+
} from "../../ast";
|
|
2
7
|
import { make } from "../internal/make";
|
|
3
8
|
|
|
4
9
|
/**
|
|
5
10
|
* Create an {@link ImportTypeNode}: an `import("module").Qualifier<Args>` type.
|
|
6
11
|
*
|
|
12
|
+
* The parameter order is upstream's: `isTypeOf` first, then the module
|
|
13
|
+
* specifier, then the `with { … }` attributes, then the qualifier and type
|
|
14
|
+
* arguments. This factory used to put `isTypeOf` last and omit `attributes`
|
|
15
|
+
* entirely, so a caller ported from `ts.factory` bound every argument to the
|
|
16
|
+
* wrong slot.
|
|
17
|
+
*
|
|
7
18
|
* The `argument` is the module specifier inside `import(...)`. A `qualifier`
|
|
8
19
|
* adds a `.Member` access, and type arguments add `<...>`. When `isTypeOf` is
|
|
9
20
|
* true the whole thing is prefixed with `typeof ` to query a value's type.
|
|
@@ -23,9 +34,16 @@ import { make } from "../internal/make";
|
|
|
23
34
|
* @returns The created {@link ImportTypeNode}.
|
|
24
35
|
*/
|
|
25
36
|
export const createImportTypeNode = (
|
|
37
|
+
isTypeOf: boolean | undefined,
|
|
26
38
|
argument: TypeNode,
|
|
39
|
+
attributes?: ImportAttributes,
|
|
27
40
|
qualifier?: EntityName,
|
|
28
41
|
typeArguments?: readonly TypeNode[],
|
|
29
|
-
isTypeOf: boolean = false,
|
|
30
42
|
): ImportTypeNode =>
|
|
31
|
-
make("ImportTypeNode", {
|
|
43
|
+
make("ImportTypeNode", {
|
|
44
|
+
argument,
|
|
45
|
+
attributes,
|
|
46
|
+
qualifier,
|
|
47
|
+
typeArguments,
|
|
48
|
+
isTypeOf: isTypeOf === true,
|
|
49
|
+
});
|
package/src/internal/doc.ts
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
export type Doc =
|
|
14
14
|
| string
|
|
15
|
+
| { type: "raw"; text: string }
|
|
15
16
|
| { type: "concat"; parts: Doc[] }
|
|
16
17
|
| { type: "line" }
|
|
17
18
|
| { type: "softline" }
|
|
@@ -22,6 +23,16 @@ export type Doc =
|
|
|
22
23
|
|
|
23
24
|
/** Concatenate documents. */
|
|
24
25
|
export const concat = (parts: Doc[]): Doc => ({ type: "concat", parts });
|
|
26
|
+
/**
|
|
27
|
+
* Literal text whose trailing whitespace is content, not layout.
|
|
28
|
+
*
|
|
29
|
+
* {@link printDocToString} strips spaces and tabs from the end of a line before
|
|
30
|
+
* writing a newline, which is right for generated code and wrong for the one
|
|
31
|
+
* node emitted as unquoted source text, `JsxText`: a trimmed trailing space
|
|
32
|
+
* there deletes a JSX separator and changes what the component renders. Text
|
|
33
|
+
* emitted through this node is never trimmed.
|
|
34
|
+
*/
|
|
35
|
+
export const raw = (text: string): Doc => ({ type: "raw", text });
|
|
25
36
|
/** A group: printed flat when it fits, broken otherwise. */
|
|
26
37
|
export const group = (doc: Doc, shouldBreak: boolean = false): Doc => ({
|
|
27
38
|
type: "group",
|
|
@@ -100,6 +111,9 @@ const fits = (next: Cmd, rest: readonly Cmd[], remaining: number): boolean => {
|
|
|
100
111
|
continue;
|
|
101
112
|
}
|
|
102
113
|
switch (doc.type) {
|
|
114
|
+
case "raw":
|
|
115
|
+
width -= doc.text.length;
|
|
116
|
+
break;
|
|
103
117
|
case "concat":
|
|
104
118
|
for (let i = doc.parts.length - 1; i >= 0; i--)
|
|
105
119
|
cmds.push([ind, mode, doc.parts[i]!]);
|
|
@@ -143,21 +157,34 @@ export const printDocToString = (
|
|
|
143
157
|
const { printWidth, newLine, indent: tab } = options;
|
|
144
158
|
const out: string[] = [];
|
|
145
159
|
let pos = 0;
|
|
160
|
+
// whether the tail of `out` is raw text, whose trailing whitespace is content
|
|
161
|
+
let rawTail = false;
|
|
146
162
|
const cmds: Cmd[] = [[0, MODE_BREAK, doc]];
|
|
147
163
|
const newlineTo = (ind: number): void => {
|
|
148
|
-
if (out.length)
|
|
164
|
+
if (out.length && !rawTail)
|
|
149
165
|
out[out.length - 1] = out[out.length - 1]!.replace(/[ \t]+$/, "");
|
|
150
166
|
out.push(newLine + tab.repeat(ind));
|
|
151
167
|
pos = tab.length * ind;
|
|
168
|
+
rawTail = false;
|
|
152
169
|
};
|
|
153
170
|
while (cmds.length) {
|
|
154
171
|
const [ind, mode, d] = cmds.pop()!;
|
|
155
172
|
if (typeof d === "string") {
|
|
156
|
-
|
|
157
|
-
|
|
173
|
+
// an empty string contributes nothing but would become the tail that
|
|
174
|
+
// `newlineTo` trims, hiding the real end of the line behind it
|
|
175
|
+
if (d.length !== 0) {
|
|
176
|
+
out.push(d);
|
|
177
|
+
pos += d.length;
|
|
178
|
+
rawTail = false;
|
|
179
|
+
}
|
|
158
180
|
continue;
|
|
159
181
|
}
|
|
160
182
|
switch (d.type) {
|
|
183
|
+
case "raw":
|
|
184
|
+
out.push(d.text);
|
|
185
|
+
pos += d.text.length;
|
|
186
|
+
rawTail = true;
|
|
187
|
+
break;
|
|
161
188
|
case "concat":
|
|
162
189
|
for (let i = d.parts.length - 1; i >= 0; i--)
|
|
163
190
|
cmds.push([ind, mode, d.parts[i]!]);
|
package/src/syntax/NodeFlags.ts
CHANGED
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
*
|
|
5
5
|
* An outline of the relevant subset of the legacy `ts.NodeFlags`. Each member's
|
|
6
6
|
* value is the keyword it implies (`Let = "let"`, `Const = "const"`), so the
|
|
7
|
-
* printer reads it directly. `Namespace`
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
7
|
+
* printer reads it directly. `Namespace` selects the keyword a module
|
|
8
|
+
* declaration with an identifier name prints: with the flag it is `namespace
|
|
9
|
+
* A`, without it `module A`. A string-literal name is always `module "…"`, so
|
|
10
|
+
* the flag says nothing there. A string-valued enum (deliberately not `const
|
|
11
|
+
* enum`, so consumers compiled with `isolatedModules` can still reference its
|
|
12
|
+
* members).
|
|
11
13
|
*
|
|
12
14
|
* @author Jeongho Nam - https://github.com/samchon
|
|
13
15
|
*/
|
package/src/syntax/SyntaxKind.ts
CHANGED
|
@@ -28,6 +28,13 @@ export enum SyntaxKind {
|
|
|
28
28
|
FalseKeyword = "false",
|
|
29
29
|
ThisKeyword = "this",
|
|
30
30
|
|
|
31
|
+
// import phase modifiers — the two keywords that may precede an import
|
|
32
|
+
// clause's bindings. Upstream types them as
|
|
33
|
+
// `ImportPhaseModifierSyntaxKind = TypeKeyword | DeferKeyword`, and
|
|
34
|
+
// `createImportClause` takes one where this factory used to take a boolean.
|
|
35
|
+
TypeKeyword = "type",
|
|
36
|
+
DeferKeyword = "defer",
|
|
37
|
+
|
|
31
38
|
// modifiers
|
|
32
39
|
ExportKeyword = "export",
|
|
33
40
|
DefaultKeyword = "default",
|