• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1import {
2    ArrayBindingOrAssignmentElement, ArrayBindingOrAssignmentPattern, AssignmentPattern,
3    BindingOrAssignmentElementTarget, BindingOrAssignmentPattern, Block, cast, ConciseBody, Debug, Expression,
4    FunctionDeclaration, getStartsOnNewLine, isArrayBindingPattern, isArrayLiteralExpression, isBindingElement,
5    isBindingPattern, isBlock, isExpression, isIdentifier, isObjectBindingPattern, isObjectLiteralElementLike,
6    isObjectLiteralExpression, map, NodeConverters, NodeFactory, notImplemented, ObjectBindingOrAssignmentElement,
7    ObjectBindingOrAssignmentPattern, setOriginalNode, setStartsOnNewLine, setTextRange, SyntaxKind,
8} from "../_namespaces/ts";
9
10/** @internal */
11export function createNodeConverters(factory: NodeFactory): NodeConverters {
12    return {
13        convertToFunctionBlock,
14        convertToFunctionExpression,
15        convertToArrayAssignmentElement,
16        convertToObjectAssignmentElement,
17        convertToAssignmentPattern,
18        convertToObjectAssignmentPattern,
19        convertToArrayAssignmentPattern,
20        convertToAssignmentElementTarget,
21    };
22
23    function convertToFunctionBlock(node: ConciseBody, multiLine?: boolean): Block {
24        if (isBlock(node)) return node;
25        const returnStatement = factory.createReturnStatement(node);
26        setTextRange(returnStatement, node);
27        const body = factory.createBlock([returnStatement], multiLine);
28        setTextRange(body, node);
29        return body;
30    }
31
32    function convertToFunctionExpression(node: FunctionDeclaration) {
33        if (!node.body) return Debug.fail(`Cannot convert a FunctionDeclaration without a body`);
34        const updated = factory.createFunctionExpression(
35            node.modifiers,
36            node.asteriskToken,
37            node.name,
38            node.typeParameters,
39            node.parameters,
40            node.type,
41            node.body
42        );
43        setOriginalNode(updated, node);
44        setTextRange(updated, node);
45        if (getStartsOnNewLine(node)) {
46            setStartsOnNewLine(updated, /*newLine*/ true);
47        }
48        return updated;
49    }
50
51    function convertToArrayAssignmentElement(element: ArrayBindingOrAssignmentElement) {
52        if (isBindingElement(element)) {
53            if (element.dotDotDotToken) {
54                Debug.assertNode(element.name, isIdentifier);
55                return setOriginalNode(setTextRange(factory.createSpreadElement(element.name), element), element);
56            }
57            const expression = convertToAssignmentElementTarget(element.name);
58            return element.initializer
59                ? setOriginalNode(
60                    setTextRange(
61                        factory.createAssignment(expression, element.initializer),
62                        element
63                    ),
64                    element
65                )
66                : expression;
67        }
68        return cast(element, isExpression);
69    }
70
71    function convertToObjectAssignmentElement(element: ObjectBindingOrAssignmentElement) {
72        if (isBindingElement(element)) {
73            if (element.dotDotDotToken) {
74                Debug.assertNode(element.name, isIdentifier);
75                return setOriginalNode(setTextRange(factory.createSpreadAssignment(element.name), element), element);
76            }
77            if (element.propertyName) {
78                const expression = convertToAssignmentElementTarget(element.name);
79                return setOriginalNode(setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element);
80            }
81            Debug.assertNode(element.name, isIdentifier);
82            return setOriginalNode(setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element);
83        }
84
85        return cast(element, isObjectLiteralElementLike);
86    }
87
88    function convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern {
89        switch (node.kind) {
90            case SyntaxKind.ArrayBindingPattern:
91            case SyntaxKind.ArrayLiteralExpression:
92                return convertToArrayAssignmentPattern(node);
93
94            case SyntaxKind.ObjectBindingPattern:
95            case SyntaxKind.ObjectLiteralExpression:
96                return convertToObjectAssignmentPattern(node);
97        }
98    }
99
100    function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) {
101        if (isObjectBindingPattern(node)) {
102            return setOriginalNode(
103                setTextRange(
104                    factory.createObjectLiteralExpression(map(node.elements, convertToObjectAssignmentElement)),
105                    node
106                ),
107                node
108            );
109        }
110        return cast(node, isObjectLiteralExpression);
111    }
112
113    function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) {
114        if (isArrayBindingPattern(node)) {
115            return setOriginalNode(
116                setTextRange(
117                    factory.createArrayLiteralExpression(map(node.elements, convertToArrayAssignmentElement)),
118                    node
119                ),
120                node
121            );
122        }
123        return cast(node, isArrayLiteralExpression);
124    }
125
126    function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression {
127        if (isBindingPattern(node)) {
128            return convertToAssignmentPattern(node);
129        }
130
131        return cast(node, isExpression);
132    }
133}
134
135/** @internal */
136export const nullNodeConverters: NodeConverters = {
137    convertToFunctionBlock: notImplemented,
138    convertToFunctionExpression: notImplemented,
139    convertToArrayAssignmentElement: notImplemented,
140    convertToObjectAssignmentElement: notImplemented,
141    convertToAssignmentPattern: notImplemented,
142    convertToObjectAssignmentPattern: notImplemented,
143    convertToArrayAssignmentPattern: notImplemented,
144    convertToAssignmentElementTarget: notImplemented,
145};