Skip to content
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

Use discriminated unions for node categories #18285

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
8 changes: 4 additions & 4 deletions src/compiler/binder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2149,7 +2149,7 @@ namespace ts {
return updateStrictModeStatementList((<Block | ModuleBlock>node).statements);

case SyntaxKind.JSDocParameterTag:
if (node.parent.kind !== SyntaxKind.JSDocTypeLiteral) {
if ((node as Node).parent.kind !== SyntaxKind.JSDocTypeLiteral) {
break;
}
// falls through
Expand Down Expand Up @@ -2563,11 +2563,11 @@ namespace ts {
// report error on all statements except empty ones
(isStatementButNotDeclaration(node) && node.kind !== SyntaxKind.EmptyStatement) ||
// report error on class declarations
node.kind === SyntaxKind.ClassDeclaration ||
(node as Declaration).kind === SyntaxKind.ClassDeclaration ||
// report error on instantiated modules or const-enums only modules if preserveConstEnums is set
(node.kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(<ModuleDeclaration>node)) ||
((node as Declaration).kind === SyntaxKind.ModuleDeclaration && shouldReportErrorOnModuleDeclaration(<ModuleDeclaration>(node as Declaration))) ||
// report error on regular enums and const enums if preserveConstEnums is set
(node.kind === SyntaxKind.EnumDeclaration && (!isConstEnumDeclaration(node) || options.preserveConstEnums));
((node as Declaration).kind === SyntaxKind.EnumDeclaration && (!isConstEnumDeclaration(node) || options.preserveConstEnums));

if (reportError) {
currentFlow = reportedUnreachableFlow;
Expand Down
171 changes: 91 additions & 80 deletions src/compiler/checker.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/compiler/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2379,7 +2379,7 @@ namespace ts {

export interface ObjectAllocator {
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getTokenConstructor(): new <TKind extends SyntaxKind>(kind: TKind, pos?: number, end?: number) => Token<TKind>;
getTokenConstructor(): new <TKind extends SyntaxKind>(kind: TKind, pos?: number, end?: number) => Node; // Token<TKind> is incompatible with the union-based Node, as its union is not lifted out of the kind field
getIdentifierConstructor(): new (kind: SyntaxKind.Identifier, pos?: number, end?: number) => Identifier;
getSourceFileConstructor(): new (kind: SyntaxKind.SourceFile, pos?: number, end?: number) => SourceFile;
getSymbolConstructor(): new (flags: SymbolFlags, name: __String) => Symbol;
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/declarationEmitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace ts {
interface SymbolAccessibilityDiagnostic {
errorNode: Node;
diagnosticMessage: DiagnosticMessage;
typeName?: DeclarationName;
typeName?: DeclarationName | QualifiedName;
}

export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, targetSourceFile: SourceFile): Diagnostic[] {
Expand Down Expand Up @@ -64,7 +64,7 @@ namespace ts {
let currentIdentifiers: Map<string>;
let isCurrentFileExternalModule: boolean;
let reportedDeclarationError = false;
let errorNameNode: DeclarationName;
let errorNameNode: DeclarationName | QualifiedName;
const emitJsDocComments = compilerOptions.removeComments ? noop : writeJsDocComments;
const emit = compilerOptions.stripInternal ? stripInternal : emitNode;
let needsDeclare = true;
Expand Down Expand Up @@ -1351,7 +1351,7 @@ namespace ts {
}
}

function emitTypeOfVariableDeclarationFromTypeLiteral(node: VariableLikeDeclaration) {
function emitTypeOfVariableDeclarationFromTypeLiteral(node: VariableLikeDeclarationBase) {
// if this is property of type literal,
// or is parameter of method/call/construct/index signature of type literal
// emit only if type is specified
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1138,7 +1138,7 @@ namespace ts {

export function createBinary(left: Expression, operator: BinaryOperator | BinaryOperatorToken, right: Expression) {
const node = <BinaryExpression>createSynthesizedNode(SyntaxKind.BinaryExpression);
const operatorToken = asToken(operator);
const operatorToken = asToken(operator) as BinaryOperatorToken;
const operatorKind = operatorToken.kind;
node.left = parenthesizeBinaryOperand(operatorKind, left, /*isLeftSideOfBinary*/ true, /*leftOperand*/ undefined);
node.operatorToken = operatorToken;
Expand Down
53 changes: 27 additions & 26 deletions src/compiler/parser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ namespace ts {
return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, pos, end);
}
else if (!isNodeKind(kind)) {
return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, pos, end);
return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind as SyntaxKind, pos, end);
}
else {
return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end);
Expand Down Expand Up @@ -93,12 +93,13 @@ namespace ts {
case SyntaxKind.BindingElement:
return visitNodes(cbNode, cbNodes, node.decorators) ||
visitNodes(cbNode, cbNodes, node.modifiers) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).propertyName) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).dotDotDotToken) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).name) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).questionToken) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).type) ||
visitNode(cbNode, (<VariableLikeDeclaration>node).initializer);
// TODO: Specialize, remove casts to VariableLikeDeclarationBase
visitNode(cbNode, (<VariableLikeDeclarationBase>node).propertyName) ||
visitNode(cbNode, (<VariableLikeDeclarationBase>node).dotDotDotToken) ||
visitNode(cbNode, (<VariableLikeDeclarationBase>node).name) ||
visitNode(cbNode, (<VariableLikeDeclarationBase>node).questionToken) ||
visitNode(cbNode, (<VariableLikeDeclarationBase>node).type) ||
visitNode(cbNode, (<VariableLikeDeclarationBase>node).initializer);
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
case SyntaxKind.CallSignature:
Expand Down Expand Up @@ -298,9 +299,9 @@ namespace ts {
case SyntaxKind.InterfaceDeclaration:
return visitNodes(cbNode, cbNodes, node.decorators) ||
visitNodes(cbNode, cbNodes, node.modifiers) ||
visitNode(cbNode, (<InterfaceDeclaration>node).name) ||
visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).typeParameters) ||
visitNodes(cbNode, cbNodes, (<ClassDeclaration>node).heritageClauses) ||
visitNode(cbNode, node.name) ||
visitNodes(cbNode, cbNodes, node.typeParameters) ||
visitNodes(cbNode, cbNodes, node.heritageClauses) ||
visitNodes(cbNode, cbNodes, (<InterfaceDeclaration>node).members);
case SyntaxKind.TypeAliasDeclaration:
return visitNodes(cbNode, cbNodes, node.decorators) ||
Expand Down Expand Up @@ -1087,7 +1088,7 @@ namespace ts {

function parseExpectedToken<TKind extends SyntaxKind>(t: TKind, reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): Token<TKind>;
function parseExpectedToken(t: SyntaxKind, reportAtCurrentPosition: boolean, diagnosticMessage: DiagnosticMessage, arg0?: any): Node {
return parseOptionalToken(t) ||
return parseOptionalToken(t) as Node ||
createMissingNode(t, reportAtCurrentPosition, diagnosticMessage, arg0);
}

Expand Down Expand Up @@ -1179,7 +1180,7 @@ namespace ts {
(result as LiteralLikeNode).text = "";
}

return finishNode(result) as T;
return finishNode(result as Node) as T;
}

function internIdentifier(text: string): string {
Expand Down Expand Up @@ -1611,11 +1612,11 @@ namespace ts {

// Ok, we have a node that looks like it could be reused. Now verify that it is valid
// in the current list parsing context that we're currently at.
if (!canReuseNode(node, parsingContext)) {
if (!canReuseNode(node as Node, parsingContext)) {
return undefined;
}

return node;
return node as Node;
}

function consumeNode(node: Node) {
Expand Down Expand Up @@ -6975,23 +6976,23 @@ namespace ts {

function moveElementEntirelyPastChangeRange(element: IncrementalElement, isArray: boolean, delta: number, oldText: string, newText: string, aggressiveChecks: boolean) {
if (isArray) {
visitArray(<IncrementalNodeArray>element);
visitArray(<NodeArray<Node>><IncrementalNodeArray>element);
}
else {
visitNode(<IncrementalNode>element);
visitNode(<Node><IncrementalNode>element);
}
return;

function visitNode(node: IncrementalNode) {
function visitNode(node: Node) {
let text = "";
if (aggressiveChecks && shouldCheckNode(node)) {
text = oldText.substring(node.pos, node.end);
}

// Ditch any existing LS children we may have created. This way we can avoid
// moving them forward.
if (node._children) {
node._children = undefined;
if ((node as IncrementalNode)._children) {
(node as IncrementalNode)._children = undefined;
}

node.pos += delta;
Expand All @@ -7001,7 +7002,7 @@ namespace ts {
Debug.assert(text === newText.substring(node.pos, node.end));
}

forEachChild(node, visitNode, visitArray);
forEachChild(node as Node, visitNode, visitArray);
if (hasJSDocNodes(node)) {
for (const jsDocComment of node.jsDoc) {
forEachChild(jsDocComment, visitNode, visitArray);
Expand All @@ -7010,8 +7011,8 @@ namespace ts {
checkNodePositions(node, aggressiveChecks);
}

function visitArray(array: IncrementalNodeArray) {
array._children = undefined;
function visitArray(array: NodeArray<Node>) {
(array as IncrementalNodeArray)._children = undefined;
array.pos += delta;
array.end += delta;

Expand All @@ -7021,7 +7022,7 @@ namespace ts {
}
}

function shouldCheckNode(node: Node) {
function shouldCheckNode(node: BaseNode) {
switch (node.kind) {
case SyntaxKind.StringLiteral:
case SyntaxKind.NumericLiteral:
Expand Down Expand Up @@ -7150,9 +7151,9 @@ namespace ts {

// Adjust the pos or end (or both) of the intersecting element accordingly.
adjustIntersectingElement(child, changeStart, changeRangeOldEnd, changeRangeNewEnd, delta);
forEachChild(child, visitNode, visitArray);
forEachChild(child as Node, visitNode as (n: Node) => undefined, visitArray as (n: NodeArray<Node>) => undefined);

checkNodePositions(child, aggressiveChecks);
checkNodePositions(child as Node, aggressiveChecks);
return;
}

Expand Down Expand Up @@ -7341,7 +7342,7 @@ namespace ts {
_children: Node[];
}

export interface IncrementalNode extends Node, IncrementalElement {
export interface IncrementalNode extends BaseNode, IncrementalElement {
hasBeenIncrementallyParsed: boolean;
}

Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ namespace ts {
* @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
*/
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: ReadonlyArray<T>, transformers: ReadonlyArray<TransformerFactory<T>>, allowDtsFiles: boolean): TransformationResult<T> {
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count + 1);
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformers/es2015.ts
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ namespace ts {
function shouldVisitNode(node: Node): boolean {
return (node.transformFlags & TransformFlags.ContainsES2015) !== 0
|| convertedLoopState !== undefined
|| (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || (node.kind === SyntaxKind.Block)))
|| (hierarchyFacts & HierarchyFacts.ConstructorWithCapturedSuper && (isStatement(node) || ((node as Node).kind === SyntaxKind.Block)))
|| (isIterationStatement(node, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(node))
|| (getEmitFlags(node) & EmitFlags.TypeScriptClassWrapper) !== 0;
}
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/transformers/module/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1597,7 +1597,7 @@ namespace ts {
? setTextRange(
createBinary(
node.operand,
createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken),
node.operator === SyntaxKind.PlusPlusToken ? createToken(SyntaxKind.PlusEqualsToken) : createToken(SyntaxKind.MinusEqualsToken),
createLiteral(1)
),
/*location*/ node)
Expand Down
Loading