Skip to content

Commit 9cdba99

Browse files
authored
Remove some properties from Identifier (#52170)
1 parent 59e4e38 commit 9cdba99

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+334
-256
lines changed

src/compiler/binder.ts

+9-6
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ import {
114114
HasLocals,
115115
hasSyntacticModifier,
116116
Identifier,
117+
identifierToKeywordKind,
117118
idText,
118119
IfStatement,
119120
ImportClause,
@@ -413,7 +414,7 @@ function getModuleInstanceStateWorker(node: Node, visited: Map<number, ModuleIns
413414
case SyntaxKind.Identifier:
414415
// Only jsdoc typedef definition can exist in jsdoc namespace, and it should
415416
// be considered the same as type alias
416-
if ((node as Identifier).isInJSDocNamespace) {
417+
if (node.flags & NodeFlags.IdentifierIsInJSDocNamespace) {
417418
return ModuleInstanceState.NonInstantiated;
418419
}
419420
}
@@ -1030,6 +1031,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
10301031
else if (containerFlags & ContainerFlags.IsInterface) {
10311032
seenThisKeyword = false;
10321033
bindChildren(node);
1034+
Debug.assertNotNode(node, isIdentifier); // ContainsThis cannot overlap with HasExtendedUnicodeEscape on Identifier
10331035
node.flags = seenThisKeyword ? node.flags | NodeFlags.ContainsThis : node.flags & ~NodeFlags.ContainsThis;
10341036
}
10351037
else {
@@ -2420,13 +2422,14 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
24202422
!isIdentifierName(node)) {
24212423

24222424
// strict mode identifiers
2425+
const originalKeywordKind = identifierToKeywordKind(node);
24232426
if (inStrictMode &&
2424-
node.originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord &&
2425-
node.originalKeywordKind! <= SyntaxKind.LastFutureReservedWord) {
2427+
originalKeywordKind! >= SyntaxKind.FirstFutureReservedWord &&
2428+
originalKeywordKind! <= SyntaxKind.LastFutureReservedWord) {
24262429
file.bindDiagnostics.push(createDiagnosticForNode(node,
24272430
getStrictModeIdentifierMessage(node), declarationNameToString(node)));
24282431
}
2429-
else if (node.originalKeywordKind === SyntaxKind.AwaitKeyword) {
2432+
else if (originalKeywordKind === SyntaxKind.AwaitKeyword) {
24302433
if (isExternalModule(file) && isInTopLevelContext(node)) {
24312434
file.bindDiagnostics.push(createDiagnosticForNode(node,
24322435
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 {
24382441
declarationNameToString(node)));
24392442
}
24402443
}
2441-
else if (node.originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) {
2444+
else if (originalKeywordKind === SyntaxKind.YieldKeyword && node.flags & NodeFlags.YieldContext) {
24422445
file.bindDiagnostics.push(createDiagnosticForNode(node,
24432446
Diagnostics.Identifier_expected_0_is_a_reserved_word_that_cannot_be_used_here,
24442447
declarationNameToString(node)));
@@ -2731,7 +2734,7 @@ function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
27312734
// for typedef type names with namespaces, bind the new jsdoc type symbol here
27322735
// because it requires all containing namespaces to be in effect, namely the
27332736
// current "blockScopeContainer" needs to be set to its immediate namespace parent.
2734-
if ((node as Identifier).isInJSDocNamespace) {
2737+
if (node.flags & NodeFlags.IdentifierIsInJSDocNamespace) {
27352738
let parentNode = node.parent;
27362739
while (parentNode && !isJSDocTypeAlias(parentNode)) {
27372740
parentNode = parentNode.parent;

src/compiler/checker.ts

+58-31
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ import {
272272
getFirstIdentifier,
273273
getFunctionFlags,
274274
getHostSignatureFromJSDoc,
275+
getIdentifierGeneratedImportReference,
276+
getIdentifierTypeArguments,
275277
getImmediatelyInvokedFunctionExpression,
276278
getInitializerOfBinaryExpression,
277279
getInterfaceBaseTypeNodes,
@@ -375,6 +377,7 @@ import {
375377
hasSyntacticModifiers,
376378
HeritageClause,
377379
Identifier,
380+
identifierToKeywordKind,
378381
IdentifierTypePredicate,
379382
idText,
380383
IfStatement,
@@ -890,11 +893,13 @@ import {
890893
ReverseMappedType,
891894
sameMap,
892895
SatisfiesExpression,
896+
scanTokenAtPosition,
893897
ScriptKind,
894898
ScriptTarget,
895899
SetAccessorDeclaration,
896900
setCommentRange,
897901
setEmitFlags,
902+
setIdentifierTypeArguments,
898903
setNodeFlags,
899904
setOriginalNode,
900905
setParent,
@@ -6794,12 +6799,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
67946799
let qualifier = root.qualifier;
67956800
if (qualifier) {
67966801
if (isIdentifier(qualifier)) {
6797-
qualifier = factory.updateIdentifier(qualifier, typeArguments);
6802+
if (typeArguments !== getIdentifierTypeArguments(qualifier)) {
6803+
qualifier = setIdentifierTypeArguments(factory.cloneNode(qualifier), typeArguments);
6804+
}
67986805
}
67996806
else {
6800-
qualifier = factory.updateQualifiedName(qualifier,
6801-
qualifier.left,
6802-
factory.updateIdentifier(qualifier.right, typeArguments));
6807+
if (typeArguments !== getIdentifierTypeArguments(qualifier.right)) {
6808+
qualifier = factory.updateQualifiedName(qualifier,
6809+
qualifier.left,
6810+
setIdentifierTypeArguments(factory.cloneNode(qualifier.right), typeArguments));
6811+
}
68036812
}
68046813
}
68056814
typeArguments = ref.typeArguments;
@@ -6821,12 +6830,16 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
68216830
let typeArguments = root.typeArguments;
68226831
let typeName = root.typeName;
68236832
if (isIdentifier(typeName)) {
6824-
typeName = factory.updateIdentifier(typeName, typeArguments);
6833+
if (typeArguments !== getIdentifierTypeArguments(typeName)) {
6834+
typeName = setIdentifierTypeArguments(factory.cloneNode(typeName), typeArguments);
6835+
}
68256836
}
68266837
else {
6827-
typeName = factory.updateQualifiedName(typeName,
6828-
typeName.left,
6829-
factory.updateIdentifier(typeName.right, typeArguments));
6838+
if (typeArguments !== getIdentifierTypeArguments(typeName.right)) {
6839+
typeName = factory.updateQualifiedName(typeName,
6840+
typeName.left,
6841+
setIdentifierTypeArguments(factory.cloneNode(typeName.right), typeArguments));
6842+
}
68306843
}
68316844
typeArguments = ref.typeArguments;
68326845
// then move qualifiers
@@ -7544,7 +7557,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
75447557
if (!nonRootParts || isEntityName(nonRootParts)) {
75457558
if (nonRootParts) {
75467559
const lastId = isIdentifier(nonRootParts) ? nonRootParts : nonRootParts.right;
7547-
lastId.typeArguments = undefined;
7560+
setIdentifierTypeArguments(lastId, /*typeArguments*/ undefined);
75487561
}
75497562
return factory.createImportTypeNode(lit, assertion, nonRootParts as EntityName, typeParameterNodes as readonly TypeNode[], isTypeOf);
75507563
}
@@ -7564,8 +7577,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
75647577
}
75657578
else {
75667579
const lastId = isIdentifier(entityName) ? entityName : entityName.right;
7567-
const lastTypeArgs = lastId.typeArguments;
7568-
lastId.typeArguments = undefined;
7580+
const lastTypeArgs = getIdentifierTypeArguments(lastId);
7581+
setIdentifierTypeArguments(lastId, /*typeArguments*/ undefined);
75697582
return factory.createTypeReferenceNode(entityName, lastTypeArgs as NodeArray<TypeNode>);
75707583
}
75717584

@@ -7619,7 +7632,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
76197632
}
76207633
}
76217634

7622-
const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
7635+
const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping);
7636+
if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray<TypeNode | TypeParameterDeclaration>(typeParameterNodes));
76237637
identifier.symbol = symbol;
76247638

76257639
if (index > stopper) {
@@ -7664,7 +7678,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
76647678
text = `${rawtext}_${i}`;
76657679
}
76667680
if (text !== rawtext) {
7667-
result = factory.createIdentifier(text, result.typeArguments);
7681+
const typeArguments = getIdentifierTypeArguments(result);
7682+
result = factory.createIdentifier(text);
7683+
setIdentifierTypeArguments(result, typeArguments);
76687684
}
76697685
// avoiding iterations of the above loop turns out to be worth it when `i` starts to get large, so we cache the max
76707686
// `i` we've used thus far, to save work later
@@ -7699,7 +7715,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
76997715
context.flags ^= NodeBuilderFlags.InInitialEntityName;
77007716
}
77017717

7702-
const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
7718+
const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping);
7719+
if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray<TypeNode | TypeParameterDeclaration>(typeParameterNodes));
77037720
identifier.symbol = symbol;
77047721

77057722
return index > 0 ? factory.createQualifiedName(createEntityNameFromSymbolChain(chain, index - 1), identifier) : identifier;
@@ -7728,7 +7745,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
77287745
return factory.createStringLiteral(getSpecifierForModuleSymbol(symbol, context));
77297746
}
77307747
if (index === 0 || canUsePropertyAccess(symbolName, languageVersion)) {
7731-
const identifier = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
7748+
const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping);
7749+
if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray<TypeNode | TypeParameterDeclaration>(typeParameterNodes));
77327750
identifier.symbol = symbol;
77337751

77347752
return index > 0 ? factory.createPropertyAccessExpression(createExpressionFromSymbolChain(chain, index - 1), identifier) : identifier;
@@ -7746,8 +7764,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
77467764
expression = factory.createNumericLiteral(+symbolName);
77477765
}
77487766
if (!expression) {
7749-
expression = setEmitFlags(factory.createIdentifier(symbolName, typeParameterNodes), EmitFlags.NoAsciiEscaping);
7750-
(expression as Identifier).symbol = symbol;
7767+
const identifier = setEmitFlags(factory.createIdentifier(symbolName), EmitFlags.NoAsciiEscaping);
7768+
if (typeParameterNodes) setIdentifierTypeArguments(identifier, factory.createNodeArray<TypeNode | TypeParameterDeclaration>(typeParameterNodes));
7769+
identifier.symbol = symbol;
7770+
expression = identifier;
77517771
}
77527772
return factory.createElementAccessExpression(createExpressionFromSymbolChain(chain, index - 1), expression);
77537773
}
@@ -23215,15 +23235,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2321523235
break;
2321623236
case SyntaxKind.Parameter:
2321723237
const param = declaration as ParameterDeclaration;
23218-
if (isIdentifier(param.name) &&
23219-
(isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) &&
23220-
param.parent.parameters.indexOf(param) > -1 &&
23221-
(resolveName(param, param.name.escapedText, SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) ||
23222-
param.name.originalKeywordKind && isTypeNodeKind(param.name.originalKeywordKind))) {
23223-
const newName = "arg" + param.parent.parameters.indexOf(param);
23224-
const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : "");
23225-
errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName);
23226-
return;
23238+
if (isIdentifier(param.name)) {
23239+
const originalKeywordKind = identifierToKeywordKind(param.name);
23240+
if ((isCallSignatureDeclaration(param.parent) || isMethodSignature(param.parent) || isFunctionTypeNode(param.parent)) &&
23241+
param.parent.parameters.indexOf(param) > -1 &&
23242+
(resolveName(param, param.name.escapedText, SymbolFlags.Type, undefined, param.name.escapedText, /*isUse*/ true) ||
23243+
originalKeywordKind && isTypeNodeKind(originalKeywordKind))) {
23244+
const newName = "arg" + param.parent.parameters.indexOf(param);
23245+
const typeName = declarationNameToString(param.name) + (param.dotDotDotToken ? "[]" : "");
23246+
errorOrSuggestion(noImplicitAny, declaration, Diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName);
23247+
return;
23248+
}
2322723249
}
2322823250
diagnostic = (declaration as ParameterDeclaration).dotDotDotToken ?
2322923251
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 :
@@ -37483,8 +37505,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
3748337505

3748437506
function checkTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments) {
3748537507
checkGrammarTypeArguments(node, node.typeArguments);
37486-
if (node.kind === SyntaxKind.TypeReference && node.typeName.jsdocDotPos !== undefined && !isInJSFile(node) && !isInJSDoc(node)) {
37487-
grammarErrorAtPos(node, node.typeName.jsdocDotPos, 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
37508+
if (node.kind === SyntaxKind.TypeReference && !isInJSFile(node) && !isInJSDoc(node) && node.typeArguments && node.typeName.end !== node.typeArguments.pos) {
37509+
// If there was a token between the type name and the type arguments, check if it was a DotToken
37510+
const sourceFile = getSourceFileOfNode(node);
37511+
if (scanTokenAtPosition(sourceFile, node.typeName.end) === SyntaxKind.DotToken) {
37512+
grammarErrorAtPos(node, skipTrivia(sourceFile.text, node.typeName.end), 1, Diagnostics.JSDoc_types_can_only_be_used_inside_documentation_comments);
37513+
}
3748837514
}
3748937515
forEach(node.typeArguments, checkSourceElement);
3749037516
const type = getTypeFromTypeReference(node);
@@ -44622,8 +44648,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4462244648
// When resolved as an expression identifier, if the given node references an import, return the declaration of
4462344649
// that import. Otherwise, return undefined.
4462444650
function getReferencedImportDeclaration(nodeIn: Identifier): Declaration | undefined {
44625-
if (nodeIn.generatedImportReference) {
44626-
return nodeIn.generatedImportReference;
44651+
const specifier = getIdentifierGeneratedImportReference(nodeIn);
44652+
if (specifier) {
44653+
return specifier;
4462744654
}
4462844655
const node = getParseTreeNode(nodeIn, isIdentifier);
4462944656
if (node) {
@@ -46894,7 +46921,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
4689446921

4689546922
function checkGrammarNameInLetOrConstDeclarations(name: Identifier | BindingPattern): boolean {
4689646923
if (name.kind === SyntaxKind.Identifier) {
46897-
if (name.originalKeywordKind === SyntaxKind.LetKeyword) {
46924+
if (name.escapedText === "let") {
4689846925
return grammarErrorOnNode(name, Diagnostics.let_is_not_allowed_to_be_used_as_a_name_in_let_or_const_declarations);
4689946926
}
4690046927
}

0 commit comments

Comments
 (0)