Skip to content

Refactor node factory API, use node factory in parser #35282

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Jun 16, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move UnparsedSource nodes to factory
  • Loading branch information
rbuckton committed Dec 9, 2019
commit 13a8962b72cb096568dc0a2b7b8f4d2ecde513aa
69 changes: 57 additions & 12 deletions src/compat/factory.ts → src/compat/deprecations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,20 @@
namespace ts {
// #region Node Factory compat (deprecated since 3.8)
// The following are deprecations for the public API. Deprecated exports are removed from the compiler itself
// and compatible implementations are added here, along with an appropriate deprecation warning using
// the `@deprecated` JSDoc tag as well as the `Debug.deprecateExport` API.
//
// Deprecations fall into one of three categories:
//
// * "soft" - Soft deprecations are indicated with the `@deprecated` JSDoc Tag.
// * "warn" - Warning deprecations are indicated with the `@deprecated` JSDoc Tag and a diagnostic message (assuming a compatible host)
// * "error" - Error deprecations are indicated with the `@deprecated` JSDoc tag and will throw a `TypeError` when invoked.

// DEPRECATION: Node factory top-level exports
// DEPRECATION PLAN:
// - soft: 3.8
// - warn: 3.9
// - error: TBD
// #region Node factory top-level exports

// #region export const { ... } = factory;
// NOTE: These exports are deprecated in favor of using a `NodeFactory` instance and exist here purely for backwards compatibility reasons.
Expand Down Expand Up @@ -1380,7 +1395,7 @@ namespace ts {
initializer?: Expression
): PropertySignature {
const node = factory.createPropertySignature(modifiers, name, questionToken, type);
node.initializer = initializer;
factory.trackExtraneousChildNode(node, node.initializer = initializer);
return node;
}

Expand All @@ -1395,13 +1410,14 @@ namespace ts {
type: TypeNode | undefined,
initializer: Expression | undefined
) {
return node.modifiers !== modifiers
|| node.name !== name
|| node.questionToken !== questionToken
|| node.type !== type
|| node.initializer !== initializer
? updateNode(createPropertySignature(modifiers, name, questionToken, type, initializer), node)
: node;
let updated = factory.updatePropertySignature(node, modifiers, name, questionToken, type);
if (node.initializer !== initializer) {
if (updated === node) {
updated = factory.cloneNode(node);
}
factory.trackExtraneousChildNode(updated, updated.initializer = initializer);
}
return updated;
}

/**
Expand Down Expand Up @@ -1905,9 +1921,38 @@ namespace ts {
warnAfter: "3.9"
});

// #endregion NodeFactory compat (deprecated in 3.8)
Debug.deprecateExport(ts, "createNode", {
message: "Use an appropriate `factory` method instead.",
since: "3.8",
warnAfter: "3.9"
});

/**
* Creates a shallow, memberwise clone of a node for mutation.
* @deprecated Use `factory.cloneNode` instead and set `pos`, `end`, and `parent` as needed.
*/
export function getMutableClone<T extends Node>(node: T): T {
const clone = factory.cloneNode(node);
clone.pos = node.pos;
clone.end = node.end;
clone.parent = node.parent;
return clone;
}

Debug.deprecateExport(ts, "getMutableClone", {
message: "Use `factory.cloneNode` instead and set `pos`, `end`, and `parent` as needed.",
since: "3.8",
warnAfter: "3.9"
});

// #endregion Node Factory top-level exports

// #region Node Test compat (deprecated since 3.8)
// DEPRECATION: Renamed node tests
// DEPRECATION PLAN:
// - soft: 3.8
// - warn: 3.9
// - error: TBD
// #region Renamed node Tests
/**
* @deprecated Use `isTypeAssertionExpression` instead.
*/
Expand All @@ -1921,5 +1966,5 @@ namespace ts {
warnAfter: "3.9"
});

// #endregion NodeTest compat (deprecated since 3.8)
// #endregion Renamed node Tests
}
2 changes: 1 addition & 1 deletion src/compat/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@
{ "path": "../compiler" }
],
"files": [
"factory.ts"
"deprecations.ts"
]
}
27 changes: 12 additions & 15 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4450,12 +4450,12 @@ namespace ts {
}
const parameterTypeNode = typeToTypeNodeHelper(parameterType, context);

const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(getSynthesizedClone) : undefined;
const modifiers = !(context.flags & NodeBuilderFlags.OmitParameterModifiers) && preserveModifierFlags && parameterDeclaration && parameterDeclaration.modifiers ? parameterDeclaration.modifiers.map(factory.cloneNode) : undefined;
const isRest = parameterDeclaration && isRestParameter(parameterDeclaration) || getCheckFlags(parameterSymbol) & CheckFlags.RestParameter;
const dotDotDotToken = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined;
const name = parameterDeclaration ? parameterDeclaration.name ?
parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(getSynthesizedClone(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) :
parameterDeclaration.name.kind === SyntaxKind.Identifier ? setEmitFlags(factory.cloneNode(parameterDeclaration.name), EmitFlags.NoAsciiEscaping) :
parameterDeclaration.name.kind === SyntaxKind.QualifiedName ? setEmitFlags(factory.cloneNode(parameterDeclaration.name.right), EmitFlags.NoAsciiEscaping) :
cloneBindingName(parameterDeclaration.name) :
symbolName(parameterSymbol) :
symbolName(parameterSymbol);
Expand All @@ -4479,7 +4479,7 @@ namespace ts {
trackComputedName(node.expression, context.enclosingDeclaration, context);
}
const visited = visitEachChild(node, elideInitializerAndSetEmitFlags, nullTransformationContext, /*nodesVisitor*/ undefined, elideInitializerAndSetEmitFlags)!;
const clone = nodeIsSynthesized(visited) ? visited : getSynthesizedClone(visited);
const clone = nodeIsSynthesized(visited) ? visited : factory.cloneNode(visited);
if (clone.kind === SyntaxKind.BindingElement) {
(<BindingElement>clone).initializer = undefined;
}
Expand Down Expand Up @@ -5935,7 +5935,7 @@ namespace ts {
// try to reuse the existing annotation
const existing = getEffectiveTypeAnnotationNode(declWithExistingAnnotation)!;
const transformed = visitNode(existing, visitExistingNodeTreeSymbols);
return transformed === existing ? getMutableClone(existing) : transformed;
return transformed === existing ? setTextRange(factory.cloneNode(existing), existing) : transformed;
}
const oldFlags = context.flags;
if (type.flags & TypeFlags.UniqueESSymbol &&
Expand Down Expand Up @@ -6689,13 +6689,10 @@ namespace ts {
if (parentAccess && parentAccess.flowNode) {
const propName = getDestructuringPropertyName(node);
if (propName) {
const result = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, node.pos, node.end);
result.parent = node;
result.expression = <LeftHandSideExpression>parentAccess;
const literal = <StringLiteral>createNode(SyntaxKind.StringLiteral, node.pos, node.end);
const literal = setTextRange(parseNodeFactory.createStringLiteral(propName), node);
const result = setTextRange(parseNodeFactory.createElementAccess(parentAccess, literal), node);
literal.parent = result;
literal.text = propName;
result.argumentExpression = literal;
result.parent = node;
result.flowNode = parentAccess.flowNode;
return result;
}
Expand Down Expand Up @@ -20231,7 +20228,8 @@ namespace ts {
if (returnType && returnType.flags & TypeFlags.Union) {
const unionTypes = (<UnionTypeNode>funcTypeNode.type).types;
if (unionTypes && unionTypes[unionTypes.length - 1].kind === SyntaxKind.UndefinedKeyword) {
const parenedFuncType = getMutableClone(funcTypeNode);
// TODO(rbuckton): Does this need to be parented?
const parenedFuncType = setParent(setTextRange(factory.cloneNode(funcTypeNode), funcTypeNode), funcTypeNode.parent);
// Highlight to the end of the second to last constituent of the union
parenedFuncType.end = unionTypes[unionTypes.length - 2].end;
addRelatedInfo(diag, createDiagnosticForNode(parenedFuncType, Diagnostics.Did_you_mean_to_parenthesize_this_function_type));
Expand Down Expand Up @@ -23901,10 +23899,9 @@ namespace ts {
}

function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean) {
const result = <SyntheticExpression>createNode(SyntaxKind.SyntheticExpression, parent.pos, parent.end);
const result = parseNodeFactory.createSyntheticExpression(type, isSpread);
setTextRange(result, parent);
result.parent = parent;
result.type = type;
result.isSpread = isSpread || false;
return result;
}

Expand Down
38 changes: 21 additions & 17 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -674,30 +674,34 @@ namespace ts {
}

function createSourceFilesFromBundleBuildInfo(bundle: BundleBuildInfo, buildInfoDirectory: string, host: EmitUsingBuildInfoHost): readonly SourceFile[] {
const sourceFiles = bundle.sourceFiles.map(fileName => {
const sourceFile = createNode(SyntaxKind.SourceFile, 0, 0) as SourceFile;
const jsBundle = Debug.assertDefined(bundle.js);
const prologueMap = jsBundle.sources?.prologues && arrayToMap(jsBundle.sources.prologues, prologueInfo => "" + prologueInfo.file);
return bundle.sourceFiles.map((fileName, index) => {
const prologueInfo = prologueMap?.get("" + index);
const statements = prologueInfo?.directives.map(directive => {
const literal = setTextRange(factory.createStringLiteral(directive.expression.text), directive.expression);
const statement = setTextRange(factory.createExpressionStatement(literal), directive);
literal.parent = statement;
return statement;
});
const eofToken = factory.createToken(SyntaxKind.EndOfFileToken);
const sourceFile = factory.createSourceFile(statements ?? [], eofToken);
sourceFile.fileName = getRelativePathFromDirectory(
host.getCurrentDirectory(),
getNormalizedAbsolutePath(fileName, buildInfoDirectory),
!host.useCaseSensitiveFileNames()
);
sourceFile.text = "";
sourceFile.statements = factory.createNodeArray();
sourceFile.text = prologueInfo?.text ?? "";
sourceFile.pos = 0;
sourceFile.end = prologueInfo?.text.length ?? 0;
for (const statement of sourceFile.statements) {
statement.parent = sourceFile;
}
eofToken.pos = sourceFile.end;
eofToken.end = sourceFile.end;
eofToken.parent = sourceFile;
return sourceFile;
});
const jsBundle = Debug.assertDefined(bundle.js);
forEach(jsBundle.sources && jsBundle.sources.prologues, prologueInfo => {
const sourceFile = sourceFiles[prologueInfo.file];
sourceFile.text = prologueInfo.text;
sourceFile.end = prologueInfo.text.length;
sourceFile.statements = factory.createNodeArray(prologueInfo.directives.map(directive => {
const statement = createNode(SyntaxKind.ExpressionStatement, directive.pos, directive.end) as PrologueDirective;
statement.expression = createNode(SyntaxKind.StringLiteral, directive.expression.pos, directive.expression.end) as StringLiteral;
statement.expression.text = directive.expression.text;
return statement;
}));
});
return sourceFiles;
}

/*@internal*/
Expand Down
Loading
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy