Skip to content

Commit

Permalink
Move UnparsedSource nodes to factory
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuckton committed Dec 9, 2019
1 parent 922ab41 commit 13a8962
Show file tree
Hide file tree
Showing 24 changed files with 612 additions and 462 deletions.
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

0 comments on commit 13a8962

Please sign in to comment.