diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index fc23222eb520b..126c2532386fe 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -114,6 +114,7 @@ import { HasLocals, hasSyntacticModifier, Identifier, + identifierToKeywordKind, idText, IfStatement, ImportClause, @@ -413,7 +414,7 @@ function getModuleInstanceStateWorker(node: Node, visited: Map void { else if (containerFlags & ContainerFlags.IsInterface) { seenThisKeyword = false; bindChildren(node); + Debug.assertNotNode(node, isIdentifier); // ContainsThis cannot overlap with HasExtendedUnicodeEscape on Identifier node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis; } else { @@ -2420,13 +2422,14 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { !isIdentifierName(node)) { // strict mode identifiers + const originalKeywordKind = identifierToKeywordKind(node); if (inStrictMode && - node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord && - node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord) { + originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord && + originalKeywordKind! <= SyntaxKind.LastFutureReservedWord) { file.bindDiagnostics.push(createDiagnosticForNode(node, getStrictModeIdentifierMessage(node), declarationNameToString(node))); } - else if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) { + else if (originalKeywordKind === SyntaxKind.AwaitKeyword) { if (isExternalModule(file) && isInTopLevelContext(node)) { file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_at_the_top_level_of_a_module, @@ -2438,7 +2441,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { declarationNameToString(node))); } } - else if (node.originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) { + else if (originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) { file.bindDiagnostics.push(createDiagnosticForNode(node, Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here, declarationNameToString(node))); @@ -2731,7 +2734,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void { // for typedef type names with namespaces, bind the new jsdoc type symbol here // because it requires all containing namespaces to be in effect, namely the // current "blockScopeContainer" needs to be set to its immediate namespace parent. - if ((node as Identifier).isInJSDocNamespace) { + if (node.flags & NodeFlags.IdentifierIsInJSDocNamespace) { let parentNode = node.parent; while (parentNode && !isJSDocTypeAlias(parentNode)) { parentNode = parentNode.parent; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 8f1bf66fa63da..11675a5b90edc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -272,6 +272,8 @@ import { getFirstIdentifier, getFunctionFlags, getHostSignatureFromJSDoc, + getIdentifierGeneratedImportReference, + getIdentifierTypeArguments, getImmediatelyInvokedFunctionExpression, getInitializerOfBinaryExpression, getInterfaceBaseTypeNodes, @@ -375,6 +377,7 @@ import { hasSyntacticModifiers, HeritageClause, Identifier, + identifierToKeywordKind, IdentifierTypePredicate, idText, IfStatement, @@ -888,11 +891,13 @@ import { ReverseMappedType, sameMap, SatisfiesExpression, + scanTokenAtPosition, ScriptKind, ScriptTarget, SetAccessorDeclaration, setCommentRange, setEmitFlags, + setIdentifierTypeArguments, setNodeFlags, setOriginalNode, setParent, @@ -6792,12 +6797,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let qualifier = root.qualifier; if (qualifier) { if (isIdentifier(qualifier)) { - qualifier = factory.updateIdentifier(qualifier, typeArguments); + if (typeArguments !== getIdentifierTypeArguments(qualifier)) { + qualifier = setIdentifierTypeArguments(factory.cloneNode(qualifier), typeArguments); + } } else { - qualifier = factory.updateQualifiedName(qualifier, - qualifier.left, - factory.updateIdentifier(qualifier.right, typeArguments)); + if (typeArguments !== getIdentifierTypeArguments(qualifier.right)) { + qualifier = factory.updateQualifiedName(qualifier, + qualifier.left, + setIdentifierTypeArguments(factory.cloneNode(qualifier.right), typeArguments)); + } } } typeArguments = ref.typeArguments; @@ -6819,12 +6828,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let typeArguments = root.typeArguments; let typeName = root.typeName; if (isIdentifier(typeName)) { - typeName = factory.updateIdentifier(typeName, typeArguments); + if (typeArguments !== getIdentifierTypeArguments(typeName)) { + typeName = setIdentifierTypeArguments(factory.cloneNode(typeName), typeArguments); + } } else { - typeName = factory.updateQualifiedName(typeName, - typeName.left, - factory.updateIdentifier(typeName.right, typeArguments)); + if (typeArguments !== getIdentifierTypeArguments(typeName.right)) { + typeName = factory.updateQualifiedName(typeName, + typeName.left, + setIdentifierTypeArguments(factory.cloneNode(typeName.right), typeArguments)); + } } typeArguments = ref.typeArguments; // then move qualifiers @@ -7542,7 +7555,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { if (!nonRootParts || isEntityName(nonRootParts)) { if (nonRootParts) { const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right; - lastId.typeArguments = undefined; + setIdentifierTypeArguments(lastId, /*typeArguments*/ undefined); } return factory.createImportTypeNode(lit, assertion, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf); } @@ -7562,8 +7575,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } else { const lastId = isIdentifier(entityName) ? entityName : entityName.right; - const lastTypeArgs = lastId.typeArguments; - lastId.typeArguments = undefined; + const lastTypeArgs = getIdentifierTypeArguments(lastId); + setIdentifierTypeArguments(lastId, /*typeArguments*/ undefined); return factory.createTypeReferenceNode(entityName, lastTypeArgs as NodeArray); } @@ -7617,7 +7630,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } } - const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); + if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); identifier.symbol = symbol; if (index > stopper) { @@ -7662,7 +7676,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { text = `${rawtext}_${i}`; } if (text !== rawtext) { - result = factory.createIdentifier(text, result.typeArguments); + const typeArguments = getIdentifierTypeArguments(result); + result = factory.createIdentifier(text); + setIdentifierTypeArguments(result, typeArguments); } // avoiding iterations of the above loop turns out to be worth it when `i` starts to get large, so we cache the max // `i` we've used thus far, to save work later @@ -7697,7 +7713,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { context.flags ^= NodeBuilderFlags.InInitialEntityName; } - const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); + if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); identifier.symbol = symbol; return index > 0 ? factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier; @@ -7726,7 +7743,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context)); } if (index === 0 || canUsePropertyAccess(symbolName, languageVersion)) { - const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); + const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); + if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); identifier.symbol = symbol; return index > 0 ? factory.createPropertyAccessExpression(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier; @@ -7744,8 +7762,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { expression = factory.createNumericLiteral(+symbolName); } if (!expression) { - expression = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping); - (expression as Identifier).symbol = symbol; + const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping); + if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray(typeParameterNodes)); + identifier.symbol = symbol; + expression = identifier; } return factory.createElementAccessExpression(createExpressionFromSymbolChain(chain, index - 1), expression); } @@ -23192,15 +23212,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { break; case SyntaxKind.Parameter: const param = declaration as ParameterDeclaration; - if (isIdentifier(param.name) && - (isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) && - param.parent.parameters.indexOf(param) > -1 && - (resolveName(param, param.name.escapedText, SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) || - param.name.originalKeywordKind && isTypeNodeKind(param.name.originalKeywordKind))) { - const newName = "arg" + param.parent.parameters.indexOf(param); - const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : ""); - errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName); - return; + if (isIdentifier(param.name)) { + const originalKeywordKind = identifierToKeywordKind(param.name); + if ((isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) && + param.parent.parameters.indexOf(param) > -1 && + (resolveName(param, param.name.escapedText, SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) || + originalKeywordKind && isTypeNodeKind(originalKeywordKind))) { + const newName = "arg" + param.parent.parameters.indexOf(param); + const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : ""); + errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName); + return; + } } diagnostic = (declaration as ParameterDeclaration).dotDotDotToken ? noImplicitAny ? Diagnostics.Rest_parameter_0_implicitly_has_an_any_type : Diagnostics.Rest_parameter_0_implicitly_has_an_any_type_but_a_better_type_may_be_inferred_from_usage : @@ -37442,8 +37464,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) { checkGrammarTypeArguments(node, node.typeArguments); - if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJSFile(node) && !isInJSDoc(node)) { - grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); + if (node.kind === SyntaxKind.TypeReference && !isInJSFile(node) && !isInJSDoc(node) && node.typeArguments && node.typeName.end !== node.typeArguments.pos) { + // If there was a token between the type name and the type arguments, check if it was a DotToken + const sourceFile = getSourceFileOfNode(node); + if (scanTokenAtPosition(sourceFile, node.typeName.end) === SyntaxKind.DotToken) { + grammarErrorAtPos(node, skipTrivia(sourceFile.text, node.typeName.end), 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments); + } } forEach(node.typeArguments, checkSourceElement); const type = getTypeFromTypeReference(node); @@ -44578,8 +44604,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // When resolved as an expression identifier, if the given node references an import, return the declaration of // that import. Otherwise, return undefined. function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined { - if (nodeIn.generatedImportReference) { - return nodeIn.generatedImportReference; + const specifier = getIdentifierGeneratedImportReference(nodeIn); + if (specifier) { + return specifier; } const node = getParseTreeNode(nodeIn, isIdentifier); if (node) { @@ -46850,7 +46877,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean { if (name.kind === SyntaxKind.Identifier) { - if (name.originalKeywordKind === SyntaxKind.LetKeyword) { + if (name.escapedText === "let") { return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations); } } diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 07474bbb2abee..4e8bbe723efaa 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -148,6 +148,7 @@ import { getEmitModuleKind, getExternalHelpersModuleName, getExternalModuleName, + getIdentifierTypeArguments, getLeadingCommentRanges, getLineAndCharacterOfPosition, getLinesBetweenPositionAndNextNonWhitespaceCharacter, @@ -2478,7 +2479,7 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri function emitIdentifier(node: Identifier) { const writeText = node.symbol ? writeSymbol : write; writeText(getTextOfNode(node, /*includeTrivia*/ false), node.symbol); - emitList(node, node.typeArguments, ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments + emitList(node, getIdentifierTypeArguments(node), ListFormat.TypeParameters); // Call emitList directly since it could be an array of TypeParameterDeclarations _or_ type arguments } // @@ -5680,15 +5681,16 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri * Generate the text for a generated identifier. */ function generateName(name: GeneratedIdentifier | GeneratedPrivateIdentifier) { - if ((name.autoGenerate.flags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) { + const autoGenerate = name.emitNode.autoGenerate; + if ((autoGenerate.flags & GeneratedIdentifierFlags.KindMask) === GeneratedIdentifierFlags.Node) { // Node names generate unique names based on their original node // and are cached based on that node's id. - return generateNameCached(getNodeForGeneratedName(name), isPrivateIdentifier(name), name.autoGenerate.flags, name.autoGenerate.prefix, name.autoGenerate.suffix); + return generateNameCached(getNodeForGeneratedName(name), isPrivateIdentifier(name), autoGenerate.flags, autoGenerate.prefix, autoGenerate.suffix); } else { // Auto, Loop, and Unique names are cached based on their unique // autoGenerateId. - const autoGenerateId = name.autoGenerate.id; + const autoGenerateId = autoGenerate.id; return autoGeneratedIdToGeneratedName[autoGenerateId] || (autoGeneratedIdToGeneratedName[autoGenerateId] = makeName(name)); } } @@ -5960,27 +5962,28 @@ export function createPrinter(printerOptions: PrinterOptions = {}, handlers: Pri * Generates a unique identifier for a node. */ function makeName(name: GeneratedIdentifier | GeneratedPrivateIdentifier) { - const prefix = formatGeneratedNamePart(name.autoGenerate.prefix, generateName); - const suffix = formatGeneratedNamePart (name.autoGenerate.suffix); - switch (name.autoGenerate.flags & GeneratedIdentifierFlags.KindMask) { + const autoGenerate = name.emitNode.autoGenerate; + const prefix = formatGeneratedNamePart(autoGenerate.prefix, generateName); + const suffix = formatGeneratedNamePart(autoGenerate.suffix); + switch (autoGenerate.flags & GeneratedIdentifierFlags.KindMask) { case GeneratedIdentifierFlags.Auto: - return makeTempVariableName(TempFlags.Auto, !!(name.autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), isPrivateIdentifier(name), prefix, suffix); + return makeTempVariableName(TempFlags.Auto, !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), isPrivateIdentifier(name), prefix, suffix); case GeneratedIdentifierFlags.Loop: Debug.assertNode(name, isIdentifier); - return makeTempVariableName(TempFlags._i, !!(name.autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), /*privateName*/ false, prefix, suffix); + return makeTempVariableName(TempFlags._i, !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), /*privateName*/ false, prefix, suffix); case GeneratedIdentifierFlags.Unique: return makeUniqueName( idText(name), - (name.autoGenerate.flags & GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueName : isUniqueName, - !!(name.autoGenerate.flags & GeneratedIdentifierFlags.Optimistic), - !!(name.autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), + (autoGenerate.flags & GeneratedIdentifierFlags.FileLevel) ? isFileLevelUniqueName : isUniqueName, + !!(autoGenerate.flags & GeneratedIdentifierFlags.Optimistic), + !!(autoGenerate.flags & GeneratedIdentifierFlags.ReservedInNestedScopes), isPrivateIdentifier(name), prefix, suffix ); } - return Debug.fail(`Unsupported GeneratedIdentifierKind: ${Debug.formatEnum(name.autoGenerate.flags & GeneratedIdentifierFlags.KindMask, (ts as any).GeneratedIdentifierFlags, /*isFlags*/ true)}.`); + return Debug.fail(`Unsupported GeneratedIdentifierKind: ${Debug.formatEnum(autoGenerate.flags & GeneratedIdentifierFlags.KindMask, (ts as any).GeneratedIdentifierFlags, /*isFlags*/ true)}.`); } // Comments diff --git a/src/compiler/factory/emitNode.ts b/src/compiler/factory/emitNode.ts index 1fa3027f660b4..0a7964b1bd8ea 100644 --- a/src/compiler/factory/emitNode.ts +++ b/src/compiler/factory/emitNode.ts @@ -2,15 +2,20 @@ import { AccessExpression, append, appendIfUnique, + AutoGenerateInfo, Debug, EmitFlags, EmitHelper, EmitNode, getParseTreeNode, getSourceFileOfNode, + Identifier, + ImportSpecifier, isParseTreeNode, Node, + NodeArray, orderedRemoveItem, + PrivateIdentifier, SnippetElement, some, SourceFile, @@ -19,6 +24,7 @@ import { SynthesizedComment, TextRange, TypeNode, + TypeParameterDeclaration, } from "../_namespaces/ts"; /** @@ -318,3 +324,36 @@ export function setTypeNode(node: T, type: TypeNode): T { export function getTypeNode(node: T): TypeNode | undefined { return node.emitNode?.typeNode; } + +/** @internal */ +export function setIdentifierTypeArguments(node: T, typeArguments: NodeArray | undefined) { + getOrCreateEmitNode(node).identifierTypeArguments = typeArguments; + return node; +} + +/** @internal */ +export function getIdentifierTypeArguments(node: Identifier): NodeArray | undefined { + return node.emitNode?.identifierTypeArguments; +} + +/** @internal */ +export function setIdentifierAutoGenerate(node: T, autoGenerate: AutoGenerateInfo | undefined) { + getOrCreateEmitNode(node).autoGenerate = autoGenerate; + return node; +} + +/** @internal */ +export function getIdentifierAutoGenerate(node: Identifier | PrivateIdentifier): AutoGenerateInfo | undefined { + return node.emitNode?.autoGenerate; +} + +/** @internal */ +export function setIdentifierGeneratedImportReference(node: T, value: ImportSpecifier | undefined) { + getOrCreateEmitNode(node).generatedImportReference = value; + return node; +} + +/** @internal */ +export function getIdentifierGeneratedImportReference(node: Identifier | PrivateIdentifier): ImportSpecifier | undefined { + return node.emitNode?.generatedImportReference; +} diff --git a/src/compiler/factory/nodeFactory.ts b/src/compiler/factory/nodeFactory.ts index 99811f7a315f1..739d47e707a91 100644 --- a/src/compiler/factory/nodeFactory.ts +++ b/src/compiler/factory/nodeFactory.ts @@ -116,6 +116,7 @@ import { getCommentRange, getElementsOfBindingOrAssignmentPattern, getEmitFlags, + getIdentifierTypeArguments, getJSDocTypeAliasName, getLineAndCharacterOfPosition, getNameOfDeclaration, @@ -390,6 +391,8 @@ import { SetAccessorDeclaration, setEachParent, setEmitFlags, + setIdentifierAutoGenerate, + setIdentifierTypeArguments, setParent, setTextRange, setTextRangePosWidth, @@ -532,7 +535,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode createRegularExpressionLiteral, createLiteralLikeNode, createIdentifier, - updateIdentifier, createTempVariable, createLoopVariable, createUniqueName, @@ -1150,34 +1152,29 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode // Identifiers // - function createBaseIdentifier(escapedText: __String, originalKeywordKind: SyntaxKind | undefined) { + function createBaseIdentifier(escapedText: __String) { const node = baseFactory.createBaseIdentifierNode(SyntaxKind.Identifier) as Mutable; - node.originalKeywordKind = originalKeywordKind; node.escapedText = escapedText; - node.autoGenerate = undefined; - node.typeArguments = undefined; - node.hasExtendedUnicodeEscape = undefined; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) node.symbol = undefined!; // initialized by checker return node; } function createBaseGeneratedIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { - const node = createBaseIdentifier(escapeLeadingUnderscores(text), /*originalKeywordKind*/ undefined) as Mutable; - node.autoGenerate = { + const node = createBaseIdentifier(escapeLeadingUnderscores(text)) as Mutable; + setIdentifierAutoGenerate(node, { flags: autoGenerateFlags, id: nextAutoGenerateId, prefix, suffix - }; + }); nextAutoGenerateId++; return node; } // @api - function createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier { + function createIdentifier(text: string, originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier { if (originalKeywordKind === undefined && text) { originalKeywordKind = stringToToken(text); } @@ -1185,28 +1182,20 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode originalKeywordKind = undefined; } - const node = createBaseIdentifier(escapeLeadingUnderscores(text), originalKeywordKind); - node.typeArguments = asNodeArray(typeArguments); - node.hasExtendedUnicodeEscape = hasExtendedUnicodeEscape; + const node = createBaseIdentifier(escapeLeadingUnderscores(text)); + if (hasExtendedUnicodeEscape) node.flags |= NodeFlags.IdentifierHasExtendedUnicodeEscape; // NOTE: we do not include transform flags of typeArguments in an identifier as they do not contribute to transformations - if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) { + if (node.escapedText === "await") { node.transformFlags |= TransformFlags.ContainsPossibleTopLevelAwait; } - if (node.hasExtendedUnicodeEscape) { + if (node.flags & NodeFlags.IdentifierHasExtendedUnicodeEscape) { node.transformFlags |= TransformFlags.ContainsES2015; } return node; } - // @api - function updateIdentifier(node: Identifier, typeArguments?: NodeArray | undefined): Identifier { - return node.typeArguments !== typeArguments - ? update(createIdentifier(idText(node), typeArguments), node) - : node; - } - // @api function createTempVariable(recordTempVariable: ((node: Identifier) => void) | undefined, reservedInNestedScopes?: boolean, prefix?: string | GeneratedNamePart, suffix?: string): GeneratedIdentifier { let flags = GeneratedIdentifierFlags.Auto; @@ -1250,7 +1239,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createBasePrivateIdentifier(escapedText: __String) { const node = baseFactory.createBasePrivateIdentifierNode(SyntaxKind.PrivateIdentifier) as Mutable; node.escapedText = escapedText; - node.autoGenerate = undefined; node.transformFlags |= TransformFlags.ContainsClassFields; return node; } @@ -1263,12 +1251,12 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createBaseGeneratedPrivateIdentifier(text: string, autoGenerateFlags: GeneratedIdentifierFlags, prefix: string | GeneratedNamePart | undefined, suffix: string | undefined) { const node = createBasePrivateIdentifier(escapeLeadingUnderscores(text)); - node.autoGenerate = { + setIdentifierAutoGenerate(node, { flags: autoGenerateFlags, id: nextAutoGenerateId, prefix, suffix, - }; + }); nextAutoGenerateId++; return node; } @@ -1490,7 +1478,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.expression = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -1537,7 +1524,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -1600,7 +1586,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.initializer = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -1655,7 +1640,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode TransformFlags.ContainsClassFields; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -1697,7 +1681,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.typeArguments = undefined; // used in quick info @@ -1773,7 +1756,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeArguments = undefined; // used in quick info node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -1824,7 +1806,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.modifiers = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.endFlowNode = undefined; @@ -1872,7 +1853,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.type = undefined; // initialized by parser for grammar errors node.typeArguments = undefined; // used in quick info node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.endFlowNode = undefined; @@ -1934,7 +1914,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeArguments = undefined; // used in quick info node.typeParameters = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -1997,7 +1976,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeParameters = undefined; // initialized by parser for grammar errors node.type = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -2043,7 +2021,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.typeArguments = undefined; // used in quick info @@ -2077,7 +2054,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.typeArguments = undefined; // used in quick info @@ -2112,7 +2088,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.typeArguments = undefined; // used in quick info @@ -2209,7 +2184,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.modifiers = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.typeArguments = undefined; // used in quick info @@ -2258,7 +2232,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.typeArguments = undefined; // used in quick info @@ -2378,7 +2351,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = TransformFlags.ContainsTypeScript; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -2754,7 +2726,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildrenFlags(node.properties); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -2778,7 +2749,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.name) | TransformFlags.ContainsPrivateIdentifierInExpression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -2846,7 +2816,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.argumentExpression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3055,7 +3024,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags = propagateChildFlags(node.expression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -3106,7 +3074,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeArguments = undefined; // used in quick info node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -3169,7 +3136,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeArguments = undefined; // used in quick info node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -3350,7 +3316,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -3588,7 +3553,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode TransformFlags.ContainsES2015; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -3785,7 +3749,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildrenFlags(node.statements); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; @@ -3812,7 +3775,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3829,7 +3791,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode function createEmptyStatement() { const node = createBaseNode(SyntaxKind.EmptyStatement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -3840,7 +3801,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.expression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3864,7 +3824,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.elseStatement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3888,7 +3847,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.expression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3911,7 +3869,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -3938,7 +3895,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -3967,7 +3923,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -3999,7 +3954,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode if (awaitModifier) node.transformFlags |= TransformFlags.ContainsES2018; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) @@ -4025,7 +3979,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode TransformFlags.ContainsHoistedDeclarationOrCompletion; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4046,7 +3999,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode TransformFlags.ContainsHoistedDeclarationOrCompletion; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4069,7 +4021,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode TransformFlags.ContainsHoistedDeclarationOrCompletion; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4091,7 +4042,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4114,7 +4064,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.caseBlock); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) node.possiblyExhaustive = false; // initialized by binder return node; @@ -4138,7 +4087,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.statement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4158,7 +4106,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildFlags(node.expression); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4182,7 +4129,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildFlags(node.finallyBlock); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4201,7 +4147,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseNode(SyntaxKind.DebuggerStatement); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.flowNode = undefined; // initialized by binder (FlowContainer) return node; } @@ -4219,7 +4164,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode (node.exclamationToken ?? node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4303,7 +4247,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.typeArguments = undefined; // used in quick info node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.endFlowNode = undefined; @@ -4374,7 +4317,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4414,7 +4356,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4459,7 +4400,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; @@ -4507,7 +4447,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4557,7 +4496,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser for grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; @@ -4591,7 +4529,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags |= propagateChildrenFlags(node.statements); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4631,7 +4568,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser to report grammar errors node.modifiers = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4675,7 +4611,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4721,7 +4656,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4912,7 +4846,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -4957,7 +4890,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.illegalDecorators = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5014,7 +4946,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // always parsed in an Await context node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5032,7 +4963,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode const node = createBaseDeclaration(SyntaxKind.MissingDeclaration); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5118,7 +5048,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode (node.type ? TransformFlags.ContainsTypeScript : TransformFlags.None); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) node.typeArguments = undefined; // used in quick info @@ -5171,7 +5100,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.type = type; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) node.locals = undefined; // initialized by binder (LocalsContainer) node.nextContainer = undefined; // initialized by binder (LocalsContainer) return node; @@ -5808,7 +5736,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode propagateChildrenFlags(node.statements); node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5903,7 +5830,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.questionToken = undefined; // initialized by parser to report grammar errors node.exclamationToken = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5942,7 +5868,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode node.questionToken = undefined; // initialized by parser to report grammar errors node.exclamationToken = undefined; // initialized by parser to report grammar errors node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -5976,7 +5901,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode TransformFlags.ContainsObjectRestOrSpread; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -6002,7 +5926,6 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode TransformFlags.ContainsTypeScript; node.jsDoc = undefined; // initialized by parser (JsDocContainer) - node.jsDocCache = undefined; // initialized by parser (JsDocContainer) return node; } @@ -6378,34 +6301,35 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode } function cloneGeneratedIdentifier(node: GeneratedIdentifier): GeneratedIdentifier { - const clone = createBaseIdentifier(node.escapedText, /*originalKeywordKind*/ undefined) as Mutable; + const clone = createBaseIdentifier(node.escapedText) as Mutable; clone.flags |= node.flags & ~NodeFlags.Synthesized; - clone.autoGenerate = { ...node.autoGenerate }; clone.transformFlags = node.transformFlags; setOriginalNode(clone, node); + setIdentifierAutoGenerate(clone, { ...node.emitNode.autoGenerate }); return clone; } function cloneIdentifier(node: Identifier): Identifier { - const clone = createBaseIdentifier(node.escapedText, node.originalKeywordKind); + const clone = createBaseIdentifier(node.escapedText); clone.flags |= node.flags & ~NodeFlags.Synthesized; - clone.typeArguments = node.typeArguments; - clone.hasExtendedUnicodeEscape = node.hasExtendedUnicodeEscape; clone.jsDoc = node.jsDoc; - clone.jsDocCache = node.jsDocCache; clone.flowNode = node.flowNode; clone.symbol = node.symbol; clone.transformFlags = node.transformFlags; setOriginalNode(clone, node); + + // clone type arguments for emitter/typeWriter + const typeArguments = getIdentifierTypeArguments(node); + if (typeArguments) setIdentifierTypeArguments(clone, typeArguments); return clone; } function cloneGeneratedPrivateIdentifier(node: GeneratedPrivateIdentifier): GeneratedPrivateIdentifier { const clone = createBasePrivateIdentifier(node.escapedText) as Mutable; clone.flags |= node.flags & ~NodeFlags.Synthesized; - clone.autoGenerate = { ...node.autoGenerate }; clone.transformFlags = node.transformFlags; setOriginalNode(clone, node); + setIdentifierAutoGenerate(clone, { ...node.emitNode.autoGenerate }); return clone; } diff --git a/src/compiler/factory/utilities.ts b/src/compiler/factory/utilities.ts index 40075da95e036..91823cef7cc1b 100644 --- a/src/compiler/factory/utilities.ts +++ b/src/compiler/factory/utilities.ts @@ -1489,18 +1489,19 @@ export function elideNodes(factory: NodeFactory, nodes: NodeArra * @internal */ export function getNodeForGeneratedName(name: GeneratedIdentifier | GeneratedPrivateIdentifier) { - if (name.autoGenerate.flags & GeneratedIdentifierFlags.Node) { - const autoGenerateId = name.autoGenerate.id; + const autoGenerate = name.emitNode.autoGenerate; + if (autoGenerate.flags & GeneratedIdentifierFlags.Node) { + const autoGenerateId = autoGenerate.id; let node = name as Node; let original = node.original; while (original) { node = original; - + const autoGenerate = node.emitNode?.autoGenerate; // if "node" is a different generated name (having a different "autoGenerateId"), use it and stop traversing. if (isMemberName(node) && ( - node.autoGenerate === undefined || - !!(node.autoGenerate.flags & GeneratedIdentifierFlags.Node) && - node.autoGenerate.id !== autoGenerateId)) { + autoGenerate === undefined || + !!(autoGenerate.flags & GeneratedIdentifierFlags.Node) && + autoGenerate.id !== autoGenerateId)) { break; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 25319bfba5bdd..cdaa764143a34 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -2547,7 +2547,7 @@ namespace Parser { const pos = getNodePos(); const result = - kind === SyntaxKind.Identifier ? factory.createIdentifier("", /*typeArguments*/ undefined, /*originalKeywordKind*/ undefined) : + kind === SyntaxKind.Identifier ? factory.createIdentifier("", /*originalKeywordKind*/ undefined) : isTemplateLiteralKind(kind) ? factory.createTemplateLiteralLikeNode(kind, "", "", /*templateFlags*/ undefined) : kind === SyntaxKind.NumericLiteral ? factory.createNumericLiteral("", /*numericLiteralFlags*/ undefined) : kind === SyntaxKind.StringLiteral ? factory.createStringLiteral("", /*isSingleQuote*/ undefined) : @@ -2576,7 +2576,7 @@ namespace Parser { const text = internIdentifier(scanner.getTokenValue()); const hasExtendedUnicodeEscape = scanner.hasExtendedUnicodeEscape(); nextTokenWithoutCheck(); - return finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind, hasExtendedUnicodeEscape), pos); + return finishNode(factory.createIdentifier(text, originalKeywordKind, hasExtendedUnicodeEscape), pos); } if (token() === SyntaxKind.PrivateIdentifier) { @@ -3058,9 +3058,9 @@ namespace Parser { return undefined; } - if (canHaveJSDoc(node) && node.jsDocCache) { + if (canHaveJSDoc(node) && node.jsDoc?.jsDocCache) { // jsDocCache may include tags from parent nodes, which might have been modified. - node.jsDocCache = undefined; + node.jsDoc.jsDocCache = undefined; } return node; @@ -3185,7 +3185,7 @@ namespace Parser { // into an actual .ConstructorDeclaration. const methodDeclaration = node as MethodDeclaration; const nameIsConstructor = methodDeclaration.name.kind === SyntaxKind.Identifier && - methodDeclaration.name.originalKeywordKind === SyntaxKind.ConstructorKeyword; + methodDeclaration.name.escapedText === "constructor"; return !nameIsConstructor; } @@ -3452,14 +3452,12 @@ namespace Parser { function parseEntityName(allowReservedWords: boolean, diagnosticMessage?: DiagnosticMessage): EntityName { const pos = getNodePos(); let entity: EntityName = allowReservedWords ? parseIdentifierName(diagnosticMessage) : parseIdentifier(diagnosticMessage); - let dotPos = getNodePos(); while (parseOptional(SyntaxKind.DotToken)) { if (token() === SyntaxKind.LessThanToken) { - // the entity is part of a JSDoc-style generic, so record the trailing dot for later error reporting - entity.jsdocDotPos = dotPos; + // The entity is part of a JSDoc-style generic. We will use the gap between `typeName` and + // `typeArguments` to report it as a grammar error in the checker. break; } - dotPos = getNodePos(); entity = finishNode( factory.createQualifiedName( entity, @@ -9254,7 +9252,7 @@ namespace Parser { } if (nested) { - typeNameOrNamespaceName.isInJSDocNamespace = true; + (typeNameOrNamespaceName as Mutable).flags |= NodeFlags.IdentifierIsInJSDocNamespace; } return typeNameOrNamespaceName; } @@ -9477,7 +9475,7 @@ namespace Parser { const end = scanner.getTextPos(); const originalKeywordKind = token(); const text = internIdentifier(scanner.getTokenValue()); - const result = finishNode(factory.createIdentifier(text, /*typeArguments*/ undefined, originalKeywordKind), pos, end); + const result = finishNode(factory.createIdentifier(text, originalKeywordKind), pos, end); nextTokenJSDoc(); return result; } diff --git a/src/compiler/transformers/classFields.ts b/src/compiler/transformers/classFields.ts index 9ef101538df6a..c299f16f2a24a 100644 --- a/src/compiler/transformers/classFields.ts +++ b/src/compiler/transformers/classFields.ts @@ -1553,7 +1553,7 @@ export function transformClassFields(context: TransformationContext): (x: Source // record an alias as the class name is not in scope for statics. enableSubstitutionForClassAliases(); const alias = factory.cloneNode(temp) as GeneratedIdentifier; - alias.autoGenerate.flags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; + alias.emitNode.autoGenerate.flags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes; classAliases[getOriginalNodeId(node)] = alias; } diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index ab5ea56408a4c..85acbeb46ef0a 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -856,7 +856,7 @@ export function transformES2015(context: TransformationContext): (x: SourceFile return convertedLoopState.argumentsName || (convertedLoopState.argumentsName = factory.createUniqueName("arguments")); } } - if (node.hasExtendedUnicodeEscape) { + if (node.flags & NodeFlags.IdentifierHasExtendedUnicodeEscape) { return setOriginalNode(setTextRange( factory.createIdentifier(unescapeLeadingUnderscores(node.escapedText)), node diff --git a/src/compiler/transformers/es5.ts b/src/compiler/transformers/es5.ts index 199cfa582327e..24485e86c95e7 100644 --- a/src/compiler/transformers/es5.ts +++ b/src/compiler/transformers/es5.ts @@ -5,7 +5,7 @@ import { Expression, getOriginalNodeId, Identifier, - idText, + identifierToKeywordKind, isIdentifier, isPrivateIdentifier, isPropertyAccessExpression, @@ -15,12 +15,10 @@ import { JsxOpeningElement, JsxSelfClosingElement, Node, - nodeIsSynthesized, PropertyAccessExpression, PropertyAssignment, setTextRange, SourceFile, - stringToToken, SyntaxKind, TransformationContext, } from "../_namespaces/ts"; @@ -139,7 +137,7 @@ export function transformES5(context: TransformationContext): (x: SourceFile | B * @param name An Identifier */ function trySubstituteReservedName(name: Identifier) { - const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(idText(name)) : undefined); + const token = identifierToKeywordKind(name); if (token !== undefined && token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) { return setTextRange(factory.createStringLiteralFromNode(name), name); } diff --git a/src/compiler/transformers/jsx.ts b/src/compiler/transformers/jsx.ts index 572ed1c594eac..2dc169b2d9a4b 100644 --- a/src/compiler/transformers/jsx.ts +++ b/src/compiler/transformers/jsx.ts @@ -57,6 +57,7 @@ import { NodeFlags, PropertyAssignment, ScriptTarget, + setIdentifierGeneratedImportReference, setParentRecursive, setTextRange, singleOrUndefined, @@ -135,7 +136,7 @@ export function transformJsx(context: TransformationContext): (x: SourceFile | B } const generatedName = factory.createUniqueName(`_${name}`, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel | GeneratedIdentifierFlags.AllowNameSubstitution); const specifier = factory.createImportSpecifier(/*isTypeOnly*/ false, factory.createIdentifier(name), generatedName); - generatedName.generatedImportReference = specifier; + setIdentifierGeneratedImportReference(generatedName, specifier); specifierSourceImports.set(name, specifier); return generatedName; } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index 0a0a1473ade2a..ac9fa5aa134d3 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -2064,7 +2064,7 @@ export function transformModule(context: TransformationContext): (x: SourceFile } return node; } - else if (!(isGeneratedIdentifier(node) && !(node.autoGenerate.flags & GeneratedIdentifierFlags.AllowNameSubstitution)) && !isLocalName(node)) { + else if (!(isGeneratedIdentifier(node) && !(node.emitNode.autoGenerate.flags & GeneratedIdentifierFlags.AllowNameSubstitution)) && !isLocalName(node)) { const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node)); if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) { return setTextRange( diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 44a716a516f7a..3877c51f16c34 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -831,6 +831,10 @@ export const enum NodeFlags { // never cleared on SourceFiles which get re-used in between incremental parses. // See the comment above on `PossiblyContainsDynamicImport` and `PossiblyContainsImportMeta`. /** @internal */ PermanentlySetIncrementalFlags = PossiblyContainsDynamicImport | PossiblyContainsImportMeta, + + // The following flags repurpose other NodeFlags as different meanings for Identifier nodes + /** @internal */ IdentifierHasExtendedUnicodeEscape = ContainsThis, // Indicates whether the identifier contains an extended unicode escape sequence + /** @internal */ IdentifierIsInJSDocNamespace = HasAsyncFunctions, // Indicates whether the identifier is part of a JSDoc namespace } export const enum ModifierFlags { @@ -908,8 +912,12 @@ export interface Node extends ReadonlyTextRange { export interface JSDocContainer extends Node { _jsdocContainerBrand: any; - /** @internal */ jsDoc?: JSDoc[]; // JSDoc that directly precedes this node - /** @internal */ jsDocCache?: readonly JSDocTag[]; // Cache for getJSDocTags + /** @internal */ jsDoc?: JSDocArray; // JSDoc that directly precedes this node +} + +/** @internal */ +export interface JSDocArray extends Array { + jsDocCache?: readonly JSDocTag[]; // Cache for getJSDocTags } export interface LocalsContainer extends Node { @@ -1005,12 +1013,6 @@ export type ForEachChildNodes = | JSDocOverloadTag ; -/** @internal */ -export type VisitEachChildNodes = - | HasChildren - | Identifier - ; - /** @internal */ export type HasChildren = | QualifiedName @@ -1678,13 +1680,6 @@ export interface Identifier extends PrimaryExpression, Declaration, JSDocContain * Text of identifier, but if the identifier begins with two underscores, this will begin with three. */ readonly escapedText: __String; - readonly originalKeywordKind?: SyntaxKind; // Original syntaxKind which get set so that we can report an error later - /** @internal */ readonly autoGenerate: AutoGenerateInfo | undefined; // Used for auto-generated identifiers. - /** @internal */ generatedImportReference?: ImportSpecifier; // Reference to the generated import specifier this identifier refers to - isInJSDocNamespace?: boolean; // if the node is a member in a JSDoc namespace - /** @internal */ typeArguments?: NodeArray; // Only defined on synthesized nodes. Though not syntactically valid, used in emitting diagnostics, quickinfo, and signature help. - /** @internal */ jsdocDotPos?: number; // Identifier occurs in JSDoc-style generic: Id. - /**@internal*/ hasExtendedUnicodeEscape?: boolean; } // Transient identifier node (marked by id === -1) @@ -1702,14 +1697,13 @@ export interface AutoGenerateInfo { /** @internal */ export interface GeneratedIdentifier extends Identifier { - readonly autoGenerate: AutoGenerateInfo; + readonly emitNode: EmitNode & { autoGenerate: AutoGenerateInfo; }; } export interface QualifiedName extends Node, FlowContainer { readonly kind: SyntaxKind.QualifiedName; readonly left: EntityName; readonly right: Identifier; - /** @internal */ jsdocDotPos?: number; // QualifiedName occurs in JSDoc-style generic: Id1.Id2. } export type EntityName = Identifier | QualifiedName; @@ -1780,12 +1774,11 @@ export interface PrivateIdentifier extends PrimaryExpression { // escaping not strictly necessary // avoids gotchas in transforms and utils readonly escapedText: __String; - /** @internal */ readonly autoGenerate: AutoGenerateInfo | undefined; // Used for auto-generated identifiers. } /** @internal */ export interface GeneratedPrivateIdentifier extends PrivateIdentifier { - readonly autoGenerate: AutoGenerateInfo; + readonly emitNode: EmitNode & { autoGenerate: AutoGenerateInfo }; } /** @internal */ @@ -7828,6 +7821,9 @@ export interface EmitNode { startsOnNewLine?: boolean; // If the node should begin on a new line snippetElement?: SnippetElement; // Snippet element of the node typeNode?: TypeNode; // VariableDeclaration type + identifierTypeArguments?: NodeArray; // Only defined on synthesized identifiers. Though not syntactically valid, used in emitting diagnostics, quickinfo, and signature help. + autoGenerate: AutoGenerateInfo | undefined; // Used for auto-generated identifiers and private identifiers. + generatedImportReference?: ImportSpecifier; // Reference to the generated import specifier this identifier refers to } /** @internal */ @@ -8126,8 +8122,7 @@ export interface NodeFactory { // createIdentifier(text: string): Identifier; - /** @internal */ createIdentifier(text: string, typeArguments?: readonly (TypeNode | TypeParameterDeclaration)[], originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures - /** @internal */ updateIdentifier(node: Identifier, typeArguments: NodeArray | undefined): Identifier; + /** @internal */ createIdentifier(text: string, originalKeywordKind?: SyntaxKind, hasExtendedUnicodeEscape?: boolean): Identifier; // eslint-disable-line @typescript-eslint/unified-signatures /** * Create a unique temporary variable. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index d76ea0241da4c..3fb63f9dd0212 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -203,6 +203,7 @@ import { HasTypeArguments, HeritageClause, Identifier, + identifierToKeywordKind, IdentifierTypePredicate, identity, idText, @@ -1649,7 +1650,7 @@ export function tryGetTextOfPropertyName(name: PropertyName | NoSubstitutionTemp switch (name.kind) { case SyntaxKind.Identifier: case SyntaxKind.PrivateIdentifier: - return name.autoGenerate ? undefined : name.escapedText; + return name.emitNode?.autoGenerate ? undefined : name.escapedText; case SyntaxKind.StringLiteral: case SyntaxKind.NumericLiteral: case SyntaxKind.NoSubstitutionTemplateLiteral: @@ -1783,6 +1784,13 @@ export function getSpanOfTokenAtPosition(sourceFile: SourceFile, pos: number): T return createTextSpanFromBounds(start, scanner.getTextPos()); } +/** @internal */ +export function scanTokenAtPosition(sourceFile: SourceFile, pos: number) { + const scanner = createScanner(sourceFile.languageVersion, /*skipTrivia*/ true, sourceFile.languageVariant, sourceFile.text, /*onError:*/ undefined, pos); + scanner.scan(); + return scanner.getToken(); +} + function getErrorSpanForArrowFunction(sourceFile: SourceFile, node: ArrowFunction): TextSpan { const pos = skipTrivia(sourceFile.text, node.pos); if (node.body && node.body.kind === SyntaxKind.Block) { @@ -4339,7 +4347,8 @@ export function isStringAKeyword(name: string) { } /** @internal */ -export function isIdentifierANonContextualKeyword({ originalKeywordKind }: Identifier): boolean { +export function isIdentifierANonContextualKeyword(node: Identifier): boolean { + const originalKeywordKind = identifierToKeywordKind(node); return !!originalKeywordKind && !isContextualKeyword(originalKeywordKind); } @@ -5707,7 +5716,7 @@ export function isThisInTypeQuery(node: Node): boolean { /** @internal */ export function identifierIsThisKeyword(id: Identifier): boolean { - return id.originalKeywordKind === SyntaxKind.ThisKeyword; + return id.escapedText === "this"; } /** @internal */ @@ -6192,7 +6201,7 @@ export function getEffectiveModifierFlagsNoCache(node: Node): ModifierFlags { */ export function getSyntacticModifierFlagsNoCache(node: Node): ModifierFlags { let flags = canHaveModifiers(node) ? modifiersToFlags(node.modifiers) : ModifierFlags.None; - if (node.flags & NodeFlags.NestedNamespace || (node.kind === SyntaxKind.Identifier && (node as Identifier).isInJSDocNamespace)) { + if (node.flags & NodeFlags.NestedNamespace || node.kind === SyntaxKind.Identifier && node.flags & NodeFlags.IdentifierIsInJSDocNamespace) { flags |= ModifierFlags.Export; } return flags; @@ -7325,7 +7334,6 @@ function Identifier(this: Mutable, kind: SyntaxKind, pos: number, end: num this.parent = undefined!; this.original = undefined; this.emitNode = undefined; - (this as Identifier).flowNode = undefined; } function SourceMapSource(this: SourceMapSource, fileName: string, text: string, skipTrivia?: (pos: number) => number) { @@ -7348,9 +7356,21 @@ export const objectAllocator: ObjectAllocator = { getSourceMapSourceConstructor: () => SourceMapSource as any, }; +const objectAllocatorPatchers: ((objectAllocator: ObjectAllocator) => void)[] = []; + +/** + * Used by `deprecatedCompat` to patch the object allocator to apply deprecations. + * @internal + */ +export function addObjectAllocatorPatcher(fn: (objectAllocator: ObjectAllocator) => void) { + objectAllocatorPatchers.push(fn); + fn(objectAllocator); +} + /** @internal */ export function setObjectAllocator(alloc: ObjectAllocator) { Object.assign(objectAllocator, alloc); + forEach(objectAllocatorPatchers, fn => fn(objectAllocator)); } /** @internal */ diff --git a/src/compiler/utilitiesPublic.ts b/src/compiler/utilitiesPublic.ts index 7bb784a3a57bd..2e78151cda548 100644 --- a/src/compiler/utilitiesPublic.ts +++ b/src/compiler/utilitiesPublic.ts @@ -138,6 +138,7 @@ import { isJSDocTypeAlias, isJSDocTypeLiteral, isJSDocTypeTag, + isKeyword, isModuleBlock, isNonNullExpression, isNotEmittedStatement, @@ -189,6 +190,7 @@ import { JsxExpression, JsxOpeningLikeElement, JsxTagNameExpression, + KeywordSyntaxKind, LabeledStatement, lastOrUndefined, LeftHandSideExpression, @@ -249,6 +251,7 @@ import { Statement, StringLiteral, StringLiteralLike, + stringToToken, Symbol, SyntaxKind, TemplateLiteral, @@ -258,6 +261,7 @@ import { TextChangeRange, TextRange, TextSpan, + tryCast, TypeElement, TypeNode, TypeOnlyAliasDeclaration, @@ -761,6 +765,16 @@ export function unescapeLeadingUnderscores(identifier: __String): string { export function idText(identifierOrPrivateName: Identifier | PrivateIdentifier): string { return unescapeLeadingUnderscores(identifierOrPrivateName.escapedText); } + +/** + * If the text of an Identifier matches a keyword (including contextual and TypeScript-specific keywords), returns the + * SyntaxKind for the matching keyword. + */ +export function identifierToKeywordKind(node: Identifier): KeywordSyntaxKind | undefined { + const token = stringToToken(node.escapedText as string); + return token ? tryCast(token, isKeyword) : undefined; +} + export function symbolName(symbol: Symbol): string { if (symbol.valueDeclaration && isPrivateIdentifierClassElementDeclaration(symbol.valueDeclaration)) { return idText(symbol.valueDeclaration.name); @@ -1147,14 +1161,15 @@ export function getJSDocReturnType(node: Node): TypeNode | undefined { function getJSDocTagsWorker(node: Node, noCache?: boolean): readonly JSDocTag[] { if (!canHaveJSDoc(node)) return emptyArray; - let tags = node.jsDocCache; + let tags = node.jsDoc?.jsDocCache; // If cache is 'null', that means we did the work of searching for JSDoc tags and came up with nothing. if (tags === undefined || noCache) { const comments = getJSDocCommentsAndTags(node, noCache); Debug.assert(comments.length < 2 || comments[0] !== comments[1]); tags = flatMap(comments, j => isJSDoc(j) ? j.tags : j); if (!noCache) { - node.jsDocCache = tags; + node.jsDoc ??= []; + node.jsDoc.jsDocCache = tags; } } return tags; @@ -1475,12 +1490,12 @@ export function isStringTextContainingNode(node: Node): node is StringLiteral | /** @internal */ export function isGeneratedIdentifier(node: Node): node is GeneratedIdentifier { - return isIdentifier(node) && node.autoGenerate !== undefined; + return isIdentifier(node) && node.emitNode?.autoGenerate !== undefined; } /** @internal */ export function isGeneratedPrivateIdentifier(node: Node): node is GeneratedPrivateIdentifier { - return isPrivateIdentifier(node) && node.autoGenerate !== undefined; + return isPrivateIdentifier(node) && node.emitNode?.autoGenerate !== undefined; } // Private Identifiers diff --git a/src/compiler/visitorPublic.ts b/src/compiler/visitorPublic.ts index af0fd6e4db0ae..7bd2806644378 100644 --- a/src/compiler/visitorPublic.ts +++ b/src/compiler/visitorPublic.ts @@ -7,6 +7,7 @@ import { FunctionBody, getEmitFlags, getEmitScriptTarget, + HasChildren, Identifier, isArray, isArrayBindingElement, @@ -80,7 +81,6 @@ import { isToken, isTypeElement, isTypeNode, - isTypeNodeOrTypeParameterDeclaration, isTypeParameterDeclaration, isVariableDeclaration, isVariableDeclarationList, @@ -99,7 +99,6 @@ import { Statement, SyntaxKind, TransformationContext, - VisitEachChildNodes, Visitor, } from "./_namespaces/ts"; @@ -513,23 +512,17 @@ type VisitEachChildFunction = (node: T, visitor: Visitor, contex // This looks something like: // // { -// [SyntaxKind.Identifier]: VisitEachChildFunction; // [SyntaxKind.QualifiedName]: VisitEachChildFunction; // [SyntaxKind.ComputedPropertyName]: VisitEachChildFunction; // ... // } // // This is then used as the expected type for `visitEachChildTable`. -type VisitEachChildTable = { [TNode in VisitEachChildNodes as TNode["kind"]]: VisitEachChildFunction }; +type VisitEachChildTable = { [TNode in HasChildren as TNode["kind"]]: VisitEachChildFunction }; // NOTE: Before you can add a new method to `visitEachChildTable`, you must first ensure the `Node` subtype you // wish to add is defined in the `HasChildren` union in types.ts. const visitEachChildTable: VisitEachChildTable = { - [SyntaxKind.Identifier]: function visitEachChildOfIdentifier(node, visitor, context, nodesVisitor, _nodeVisitor, _tokenVisitor) { - return context.factory.updateIdentifier(node, - nodesVisitor(node.typeArguments, visitor, isTypeNodeOrTypeParameterDeclaration)); - }, - [SyntaxKind.QualifiedName]: function visitEachChildOfQualifiedName(node, visitor, context, _nodesVisitor, nodeVisitor, _tokenVisitor) { return context.factory.updateQualifiedName(node, nodeVisitor(node.left, visitor, isEntityName), diff --git a/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts b/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts index caca5fc914394..5b8efa635628e 100644 --- a/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts +++ b/src/deprecatedCompat/4.0/nodeFactoryTopLevelExports.ts @@ -988,7 +988,7 @@ export const createToken = deprecate(function createToken { + const Identifier = objectAllocator.getIdentifierConstructor(); + + if (!hasProperty(Identifier.prototype, "originalKeywordKind")) { + Object.defineProperty(Identifier.prototype, "originalKeywordKind", { + get: deprecate(function (this: Identifier) { + return identifierToKeywordKind(this); + }, { + name: "originalKeywordKind", + since: "5.0", + warnAfter: "5.1", + errorAfter: "5.2", + message: "Use 'identifierToKeywordKind(identifier)' instead." + }) + }); + } + + if (!hasProperty(Identifier.prototype, "isInJSDocNamespace")) { + Object.defineProperty(Identifier.prototype, "isInJSDocNamespace", { + get: deprecate(function (this: Identifier) { + // NOTE: Returns `true` or `undefined` to match previous possible values. + return this.flags & NodeFlags.IdentifierIsInJSDocNamespace ? true : undefined; + }, { + name: "isInJSDocNamespace", + since: "5.0", + warnAfter: "5.1", + errorAfter: "5.2", + message: "Use '.parent' or the surrounding context to determine this instead." + }) + }); + } +}); diff --git a/src/deprecatedCompat/_namespaces/ts.ts b/src/deprecatedCompat/_namespaces/ts.ts index 89b1e1729cf21..e74bb6da37216 100644 --- a/src/deprecatedCompat/_namespaces/ts.ts +++ b/src/deprecatedCompat/_namespaces/ts.ts @@ -9,3 +9,4 @@ export * from "../4.2/abstractConstructorTypes"; export * from "../4.6/importTypeAssertions"; export * from "../4.7/typeParameterModifiers"; export * from "../4.8/mergeDecoratorsAndModifiers"; +export * from "../5.0/identifierProperties"; diff --git a/src/deprecatedCompat/deprecate.ts b/src/deprecatedCompat/deprecate.ts index c56abe2df1ef2..e7db9ef07f3cd 100644 --- a/src/deprecatedCompat/deprecate.ts +++ b/src/deprecatedCompat/deprecate.ts @@ -52,7 +52,7 @@ export function createDeprecation(name: string, options: DeprecationOptions = {} const errorAfter = typeof options.errorAfter === "string" ? new Version(options.errorAfter) : options.errorAfter; const warnAfter = typeof options.warnAfter === "string" ? new Version(options.warnAfter) : options.warnAfter; const since = typeof options.since === "string" ? new Version(options.since) : options.since ?? warnAfter; - const error = options.error || errorAfter && version.compareTo(errorAfter) <= 0; + const error = options.error || errorAfter && version.compareTo(errorAfter) >= 0; const warn = !warnAfter || version.compareTo(warnAfter) >= 0; return error ? createErrorDeprecation(name, errorAfter, since, options.message) : warn ? createWarningDeprecation(name, errorAfter, since, options.message) : diff --git a/src/harness/harnessUtils.ts b/src/harness/harnessUtils.ts index 718d7de802937..f4d006e05aa4a 100644 --- a/src/harness/harnessUtils.ts +++ b/src/harness/harnessUtils.ts @@ -189,7 +189,7 @@ export function sourceFileToJSON(file: ts.Node): string { o.containsParseError = true; } - for (const propertyName of Object.getOwnPropertyNames(n) as readonly (keyof ts.SourceFile | keyof ts.Identifier)[]) { + for (const propertyName of Object.getOwnPropertyNames(n) as readonly (keyof ts.SourceFile | keyof ts.Identifier | keyof ts.StringLiteral)[]) { switch (propertyName) { case "parent": case "symbol": @@ -201,7 +201,7 @@ export function sourceFileToJSON(file: ts.Node): string { case "symbolCount": case "identifierCount": case "scriptSnapshot": - case "autoGenerate": + case "emitNode": // Blocklist of items we never put in the baseline file. break; @@ -219,7 +219,13 @@ export function sourceFileToJSON(file: ts.Node): string { // Clear the flags that are produced by aggregating child values. That is ephemeral // data we don't care about in the dump. We only care what the parser set directly // on the AST. - const flags = n.flags & ~(ts.NodeFlags.JavaScriptFile | ts.NodeFlags.HasAggregatedChildData); + let flags = n.flags & ~(ts.NodeFlags.JavaScriptFile | ts.NodeFlags.HasAggregatedChildData); + if (ts.isIdentifier(n)) { + if (flags & ts.NodeFlags.IdentifierHasExtendedUnicodeEscape) { + o.hasExtendedUnicodeEscape = true; + flags &= ~ts.NodeFlags.IdentifierHasExtendedUnicodeEscape; + } + } if (flags) { o[propertyName] = getNodeFlagName(flags); } diff --git a/src/services/codefixes/convertToEsModule.ts b/src/services/codefixes/convertToEsModule.ts index 959b9ea4538ad..ea296b0a21790 100644 --- a/src/services/codefixes/convertToEsModule.ts +++ b/src/services/codefixes/convertToEsModule.ts @@ -50,7 +50,7 @@ import { isExportsOrModuleExportsOrAlias, isFunctionExpression, isIdentifier, - isNonContextualKeyword, + isIdentifierANonContextualKeyword, isObjectLiteralExpression, isPropertyAccessExpression, isRequireCall, @@ -161,8 +161,8 @@ type ExportRenames = ReadonlyMap; function collectExportRenames(sourceFile: SourceFile, checker: TypeChecker, identifiers: Identifiers): ExportRenames { const res = new Map(); forEachExportReference(sourceFile, node => { - const { text, originalKeywordKind } = node.name; - if (!res.has(text) && (originalKeywordKind !== undefined && isNonContextualKeyword(originalKeywordKind) + const { text } = node.name; + if (!res.has(text) && (isIdentifierANonContextualKeyword(node.name) || checker.resolveName(text, node, SymbolFlags.Value, /*excludeGlobals*/ true))) { // Unconditionally add an underscore in case `text` is a keyword. res.set(text, makeUniqueName(`_${text}`, identifiers)); diff --git a/src/services/completions.ts b/src/services/completions.ts index cec01139bef9d..0bf7c09e19618 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -107,6 +107,7 @@ import { hasInitializer, hasType, Identifier, + identifierToKeywordKind, ImportDeclaration, ImportEqualsDeclaration, ImportKind, @@ -1690,8 +1691,11 @@ function isModifierLike(node: Node): ModifierSyntaxKind | undefined { if (isModifier(node)) { return node.kind; } - if (isIdentifier(node) && node.originalKeywordKind && isModifierKind(node.originalKeywordKind)) { - return node.originalKeywordKind; + if (isIdentifier(node)) { + const originalKeywordKind = identifierToKeywordKind(node); + if (originalKeywordKind && isModifierKind(originalKeywordKind)) { + return originalKeywordKind; + } } return undefined; } @@ -4720,7 +4724,7 @@ function isFunctionLikeBodyKeyword(kind: SyntaxKind) { } function keywordForNode(node: Node): SyntaxKind { - return isIdentifier(node) ? node.originalKeywordKind || SyntaxKind.Unknown : node.kind; + return isIdentifier(node) ? identifierToKeywordKind(node) ?? SyntaxKind.Unknown : node.kind; } function getContextualKeywords( @@ -4824,8 +4828,8 @@ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, } break; case SyntaxKind.Identifier: { - const originalKeywordKind = (location as Identifier).originalKeywordKind; - if (originalKeywordKind && isKeyword(originalKeywordKind)) { + const originalKeywordKind = identifierToKeywordKind(location as Identifier); + if (originalKeywordKind) { return undefined; } // class c { public prop = c| } @@ -4870,7 +4874,7 @@ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile: SourceFile, return undefined; } const isValidKeyword = isClassLike(contextToken.parent.parent) ? isClassMemberCompletionKeyword : isInterfaceOrTypeLiteralCompletionKeyword; - return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)!)) // TODO: GH#18217 + return (isValidKeyword(contextToken.kind) || contextToken.kind === SyntaxKind.AsteriskToken || isIdentifier(contextToken) && isValidKeyword(identifierToKeywordKind(contextToken) ?? SyntaxKind.Unknown)) ? contextToken.parent.parent as ObjectTypeDeclaration : undefined; } } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 01ad83b784169..e8fe0f2a71f03 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1940,8 +1940,8 @@ export namespace Core { // For `export { foo as bar }`, rename `foo`, but not `bar`. if (!isForRenameWithPrefixAndSuffixText(state.options) || alwaysGetReferences) { - const isDefaultExport = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword - || exportSpecifier.name.originalKeywordKind === SyntaxKind.DefaultKeyword; + const isDefaultExport = referenceLocation.escapedText === "default" + || exportSpecifier.name.escapedText === "default"; const exportKind = isDefaultExport ? ExportKind.Default : ExportKind.Named; const exportSymbol = Debug.checkDefined(exportSpecifier.symbol); const exportInfo = getExportInfo(exportSymbol, exportKind, state.checker); diff --git a/src/services/refactors/extractSymbol.ts b/src/services/refactors/extractSymbol.ts index 367a685d484f1..3a0339a357bdf 100644 --- a/src/services/refactors/extractSymbol.ts +++ b/src/services/refactors/extractSymbol.ts @@ -61,6 +61,7 @@ import { hasEffectiveModifier, hasSyntacticModifier, Identifier, + identifierToKeywordKind, isArray, isArrowFunction, isAssignmentExpression, @@ -87,7 +88,6 @@ import { isJsxElement, isJsxFragment, isJsxSelfClosingElement, - isKeyword, isModuleBlock, isParenthesizedTypeNode, isPartOfTypeNode, @@ -1351,7 +1351,7 @@ function extractConstantInScope( // Make a unique name for the extracted variable const file = scope.getSourceFile(); - const localNameText = isPropertyAccessExpression(node) && !isClassLike(scope) && !checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ false) && !isPrivateIdentifier(node.name) && !isKeyword(node.name.originalKeywordKind!) + const localNameText = isPropertyAccessExpression(node) && !isClassLike(scope) && !checker.resolveName(node.name.text, node, SymbolFlags.Value, /*excludeGlobals*/ false) && !isPrivateIdentifier(node.name) && !identifierToKeywordKind(node.name) ? node.name.text : getUniqueName(isClassLike(scope) ? "newProperty" : "newLocal", file); const isJS = isInJSFile(scope); diff --git a/src/services/rename.ts b/src/services/rename.ts index 52ee0b8a3f544..f8b6971e6b37d 100644 --- a/src/services/rename.ts +++ b/src/services/rename.ts @@ -97,7 +97,7 @@ function getRenameInfoForNode( } // Cannot rename `default` as in `import { default as foo } from "./someModule"; - if (isIdentifier(node) && node.originalKeywordKind === SyntaxKind.DefaultKeyword && symbol.parent && symbol.parent.flags & SymbolFlags.Module) { + if (isIdentifier(node) && node.escapedText === "default" && symbol.parent && symbol.parent.flags & SymbolFlags.Module) { return undefined; } diff --git a/src/services/services.ts b/src/services/services.ts index e36785bc33ca1..f5d2f51cd3e98 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -6,7 +6,6 @@ import { ApplicableRefactorInfo, ApplyCodeActionCommandResult, AssignmentDeclarationKind, - AutoGenerateInfo, BaseType, BinaryExpression, BreakpointResolver, @@ -734,7 +733,6 @@ class TokenObject extends TokenOrIdentifierObject impl class IdentifierObject extends TokenOrIdentifierObject implements Identifier { public kind: SyntaxKind.Identifier = SyntaxKind.Identifier; public escapedText!: __String; - public autoGenerate: AutoGenerateInfo | undefined; declare _primaryExpressionBrand: any; declare _memberExpressionBrand: any; declare _leftHandSideExpressionBrand: any; @@ -757,7 +755,6 @@ IdentifierObject.prototype.kind = SyntaxKind.Identifier; class PrivateIdentifierObject extends TokenOrIdentifierObject implements PrivateIdentifier { public kind: SyntaxKind.PrivateIdentifier = SyntaxKind.PrivateIdentifier; public escapedText!: __String; - public autoGenerate: AutoGenerateInfo | undefined; declare _primaryExpressionBrand: any; declare _memberExpressionBrand: any; declare _leftHandSideExpressionBrand: any; diff --git a/src/services/textChanges.ts b/src/services/textChanges.ts index 98a35af0fe3e0..63378707036bb 100644 --- a/src/services/textChanges.ts +++ b/src/services/textChanges.ts @@ -1147,7 +1147,6 @@ function updateJSDocHost(parent: HasJSDoc): HasJSDoc { parent.parent as HasJSDoc : parent.parent.parent as HasJSDoc; jsDocNode.jsDoc = parent.jsDoc; - jsDocNode.jsDocCache = parent.jsDocCache; return jsDocNode; } diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@@ does not start a new tag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@@ does not start a new tag.json index dca1bc102db2a..362e7f146a6ac 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@@ does not start a new tag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.@@ does not start a new tag.json @@ -27,7 +27,6 @@ "end": 18, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "ThisKeyword", "escapedText": "this" }, "isNameFirst": true, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json index 8d57b3d79ab77..3269bdc87fc04 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.leadingAsterisk.json @@ -18,7 +18,6 @@ "end": 13, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "TypeKeyword", "escapedText": "type" }, "typeExpression": { diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.no space before @ is not a new tag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.no space before @ is not a new tag.json index 64de20d9bef39..87597fad44e4c 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.no space before @ is not a new tag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.no space before @ is not a new tag.json @@ -27,7 +27,6 @@ "end": 18, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "ThisKeyword", "escapedText": "this" }, "isNameFirst": true, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json index 8d57b3d79ab77..3269bdc87fc04 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noLeadingAsterisk.json @@ -18,7 +18,6 @@ "end": 13, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "TypeKeyword", "escapedText": "type" }, "typeExpression": { diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json index ad2eea3f2d5c3..ab21f32ef9c61 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.noReturnType.json @@ -18,7 +18,6 @@ "end": 15, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "ReturnKeyword", "escapedText": "return" } }, diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json index 00e574a12c499..a3abbded8b07a 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag1.json @@ -18,7 +18,6 @@ "end": 15, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "ReturnKeyword", "escapedText": "return" }, "typeExpression": { diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json index 7fb31fbd96d6a..474aa807f2be6 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.returnTag2.json @@ -18,7 +18,6 @@ "end": 15, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "ReturnKeyword", "escapedText": "return" }, "comment": "Description text follows", diff --git a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json index 8d57b3d79ab77..3269bdc87fc04 100644 --- a/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json +++ b/tests/baselines/reference/JSDocParsing/DocComments.parsesCorrectly.typeTag.json @@ -18,7 +18,6 @@ "end": 13, "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "TypeKeyword", "escapedText": "type" }, "typeExpression": { diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json index 4dbd3f2959bf8..24e3d75cd7f88 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.keyword1.json @@ -12,7 +12,6 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "VarKeyword", "escapedText": "var" } } \ No newline at end of file diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json index 070cfdabde5dd..9e76619c596bd 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.newType1.json @@ -20,7 +20,6 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "NewKeyword", "escapedText": "new" }, "type": { diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json index 780a7289bd51c..5a970882d3d7f 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.recordType8.json @@ -20,7 +20,6 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "FunctionKeyword", "escapedText": "function" } }, diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json index 2f189e79ae3a0..a03b17581eb67 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.thisType1.json @@ -20,7 +20,6 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "ThisKeyword", "escapedText": "this" }, "type": { diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json index cfbef060a8516..b1778ff786534 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference1.json @@ -12,8 +12,7 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "escapedText": "a", - "jsdocDotPos": 2 + "escapedText": "a" }, "typeArguments": { "0": { diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json index 3802cb3212932..8ac51a4783083 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference2.json @@ -12,8 +12,7 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "escapedText": "a", - "jsdocDotPos": 2 + "escapedText": "a" }, "typeArguments": { "0": { diff --git a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json index 5dde38b4c0b07..3c5435032afdb 100644 --- a/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json +++ b/tests/baselines/reference/JSDocParsing/TypeExpressions.parsesCorrectly.typeReference3.json @@ -28,7 +28,6 @@ "flags": "JSDoc", "modifierFlagsCache": 0, "transformFlags": 0, - "originalKeywordKind": "FunctionKeyword", "escapedText": "function" } } diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 44e2e6143aba9..ca08413acb2b8 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -4584,12 +4584,16 @@ declare namespace ts { * Text of identifier, but if the identifier begins with two underscores, this will begin with three. */ readonly escapedText: __String; - readonly originalKeywordKind?: SyntaxKind; - isInJSDocNamespace?: boolean; } interface Identifier { readonly text: string; } + interface Identifier { + /** @deprecated Use `idKeyword(identifier)` instead. */ + readonly originalKeywordKind?: SyntaxKind; + /** @deprecated Use `.parent` or the surrounding context to determine this instead. */ + readonly isInJSDocNamespace?: boolean; + } interface TransientIdentifier extends Identifier { resolvedSymbol: Symbol; } @@ -8598,6 +8602,11 @@ declare namespace ts { */ function unescapeLeadingUnderscores(identifier: __String): string; function idText(identifierOrPrivateName: Identifier | PrivateIdentifier): string; + /** + * If the text of an Identifier matches a keyword (including contextual and TypeScript-specific keywords), returns the + * SyntaxKind for the matching keyword. + */ + function identifierToKeywordKind(node: Identifier): KeywordSyntaxKind | undefined; function symbolName(symbol: Symbol): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined; diff --git a/tests/baselines/reference/api/typescript.d.ts b/tests/baselines/reference/api/typescript.d.ts index e29bb395fe5f4..25a28c914bec3 100644 --- a/tests/baselines/reference/api/typescript.d.ts +++ b/tests/baselines/reference/api/typescript.d.ts @@ -649,12 +649,16 @@ declare namespace ts { * Text of identifier, but if the identifier begins with two underscores, this will begin with three. */ readonly escapedText: __String; - readonly originalKeywordKind?: SyntaxKind; - isInJSDocNamespace?: boolean; } interface Identifier { readonly text: string; } + interface Identifier { + /** @deprecated Use `idKeyword(identifier)` instead. */ + readonly originalKeywordKind?: SyntaxKind; + /** @deprecated Use `.parent` or the surrounding context to determine this instead. */ + readonly isInJSDocNamespace?: boolean; + } interface TransientIdentifier extends Identifier { resolvedSymbol: Symbol; } @@ -4663,6 +4667,11 @@ declare namespace ts { */ function unescapeLeadingUnderscores(identifier: __String): string; function idText(identifierOrPrivateName: Identifier | PrivateIdentifier): string; + /** + * If the text of an Identifier matches a keyword (including contextual and TypeScript-specific keywords), returns the + * SyntaxKind for the matching keyword. + */ + function identifierToKeywordKind(node: Identifier): KeywordSyntaxKind | undefined; function symbolName(symbol: Symbol): string; function getNameOfJSDocTypedef(declaration: JSDocTypedefTag): Identifier | PrivateIdentifier | undefined; function getNameOfDeclaration(declaration: Declaration | Expression | undefined): DeclarationName | undefined;