diff --git a/tools/scripts/tsc/ast.json b/tools/scripts/tsc/ast.json index a133915a10665..206dfe47e531d 100644 --- a/tools/scripts/tsc/ast.json +++ b/tools/scripts/tsc/ast.json @@ -1236,7 +1236,7 @@ "members": [ { "name": "Text", - "type": "string" + "type": "SymbolName" } ], "arena": true diff --git a/tools/scripts/tsc/generate-encoder.ts b/tools/scripts/tsc/generate-encoder.ts index 1b106bb8ff555..38bc76258385e 100644 --- a/tools/scripts/tsc/generate-encoder.ts +++ b/tools/scripts/tsc/generate-encoder.ts @@ -22,6 +22,7 @@ import type { KindType, MemberInfo, NodeType, + Type, } from "./schema.ts"; import { api } from "./schema.ts"; @@ -153,7 +154,7 @@ function needsHandWrittenCommonData(node: NodeType): boolean { if (m.isChild() || m.isKindParam()) return false; const dt = m.declaredType; if (dt.kind === "primitive" && dt.name === "bool") return false; - if (dt.kind === "primitive" && dt.name === "string") return false; + if (isStringPrimitive(dt)) return false; if (isSyntaxKindUnion(m)) return false; if (isNodeFlagsMember(m)) return false; return true; @@ -170,7 +171,7 @@ function getHandWrittenDataMembers(node: NodeType): MemberInfo[] { return members.filter(m => { if (m.isChild() || m.isKindParam()) return false; const dt = m.declaredType; - if (dt.kind === "primitive" && dt.name === "string") return false; + if (isStringPrimitive(dt)) return false; if (isNodeFlagsMember(m)) return false; return true; }); @@ -182,12 +183,21 @@ function getHandWrittenDataMembers(node: NodeType): MemberInfo[] { type DataType = "string" | "children" | "extended"; +function isSymbolNamePrimitive(type: Type | undefined): boolean { + return type?.kind === "primitive" && type.name === "SymbolName"; +} + +// SymbolName is an interned string in Go and is encoded as a string. +function isStringPrimitive(type: Type | undefined): boolean { + return type?.kind === "primitive" && (type.name === "string" || type.name === "SymbolName"); +} + function classifyDataType(node: NodeType): DataType { if (node.handWritten) return "extended"; const members = schemaMembers(node); const stringMembers = members.filter(m => !m.isChild() && !m.isKindParam() && - m.declaredType.kind === "primitive" && m.declaredType.name === "string" + isStringPrimitive(m.declaredType) ); if (stringMembers.length > 1) return "extended"; if (stringMembers.length === 1) { @@ -292,7 +302,7 @@ function analyzeNode(node: NodeType): EncoderNodeInfo { const textMember = dataType === "string" ? members.find(m => !m.isChild() && !m.isKindParam() && - m.declaredType.kind === "primitive" && m.declaredType.name === "string" + isStringPrimitive(m.declaredType) ) : undefined; // Factory members include all non-noFactory members (even noTS ones), @@ -538,10 +548,11 @@ function generateGoRecordNodeStrings(w: CodeWriter) { const textAccess = info.textMember.private ? `node.${castName}().${api.capitalize(info.textMember.name)}()` : `node.${castName}().${info.textMember.name}`; + const textValue = isSymbolNamePrimitive(info.textMember.declaredType) ? `${textAccess}.Value()` : textAccess; w.write(`case ${kinds.join(", ")}:`); w.push(); - w.write(`return strs.add(${textAccess}, node.Kind, node.Pos(), node.End())`); + w.write(`return strs.add(${textValue}, node.Kind, node.Pos(), node.End())`); w.pop(); } diff --git a/tools/scripts/tsc/generate-enums.ts b/tools/scripts/tsc/generate-enums.ts index 757f598fa88c6..1dded41804498 100644 --- a/tools/scripts/tsc/generate-enums.ts +++ b/tools/scripts/tsc/generate-enums.ts @@ -84,7 +84,7 @@ function syntaxKindMembers(): EnumMember[] { return [...members, { name: "Count", value: String(members.length) }, ...api.kindMarkers()]; } -function parseGoConstBlock(block: string, def: EnumDef): EnumMember[] { +function parseGoDeclarationBlock(block: string, def: EnumDef): EnumMember[] { const prefix = def.goPrefix; const members: EnumMember[] = []; let iotaCounter = 0; @@ -278,11 +278,12 @@ function translateGoNumericExpression(expression: string, prefix: string): strin } /** - * Resolve a Go string-constant expression (e.g. `Prefix + "call"` or `"export="`) + * Resolve a Go string expression, optionally interned with `MakeSymbolName`, * into a quoted, JS-escaped TypeScript string literal. `replacements` maps bare * Go identifiers (such as a sentinel-prefix constant) to their literal value. */ function parseGoStringValue(goValue: string, replacements: Record): string { + goValue = goValue.replace(/^(?:unique\.Make|MakeSymbolName)\((.*)\)$/, "$1"); let result = ""; for (const part of goValue.split("+").map(p => p.trim())) { if (Object.prototype.hasOwnProperty.call(replacements, part)) { @@ -306,10 +307,11 @@ interface EnumMember { function parseGoEnum(def: EnumDef): EnumMember[] { const source = fs.readFileSync(path.join(ROOT, def.goFile), "utf-8"); - const constBlockRegex = /const\s*\(([\s\S]*?)\n\)/g; + const declarationBlockRegex = /(const|var)\s*\(([\s\S]*?)\n\)/g; - for (const match of source.matchAll(constBlockRegex)) { - const members = parseGoConstBlock(match[1], def).filter(member => !def.excludeMembers?.includes(member.name)); + for (const match of source.matchAll(declarationBlockRegex)) { + if (match[1] === "var" && !def.stringEnum) continue; + const members = parseGoDeclarationBlock(match[2], def).filter(member => !def.excludeMembers?.includes(member.name)); if (members.length > 0) return topoSortMembers(members); } diff --git a/tools/scripts/tsc/generate-go-ast.ts b/tools/scripts/tsc/generate-go-ast.ts index db4d110de8f8a..5e1cfa7f84cab 100644 --- a/tools/scripts/tsc/generate-go-ast.ts +++ b/tools/scripts/tsc/generate-go-ast.ts @@ -44,7 +44,7 @@ function schemaMembers(node: NodeType): MemberInfo[] { function isTextContentType(type: Type): boolean { if (type.kind === "primitive") { - return type.name === "string"; + return type.name === "string" || type.name === "SymbolName"; } if (type.kind === "list" && type.listKind === "raw") { return type.elementType.kind === "primitive" && type.elementType.name === "string"; @@ -494,11 +494,39 @@ function emitNewFactory( w.write(""); } +function isSymbolNameMember(m: MemberInfo): boolean { + return m.type.kind === "primitive" && m.type.name === "SymbolName"; +} + +// Nodes with SymbolName members get a New*FromSymbolName factory taking the +// interned name, plus a New* convenience factory that accepts a string. +function factoryName(name: string, node: NodeType): string { + return schemaMembers(node).some(isSymbolNameMember) ? `New${name}FromSymbolName` : `New${name}`; +} + +function emitStringFactory(w: CodeWriter, name: string, node: NodeType, members: MemberInfo[]) { + const params = members.map(m => `${m.goParamName()} ${isSymbolNameMember(m) ? "string" : m.type.formatGoReference()}`).join(", "); + const args = members.map(m => isSymbolNameMember(m) ? `MakeSymbolName(${m.goParamName()})` : m.goParamName()).join(", "); + w.write(`func (f *NodeFactory) New${name}(${params}) *Node {`); + w.push(); + w.write(`return f.${factoryName(name, node)}(${args})`); + w.pop(); + w.write("}"); + w.write(""); +} + function generateNewFactory(w: CodeWriter, node: NodeType) { const structName = node.name; const members = schemaMembers(node); const kindMember = members.find(m => m.isKindParam()); const nodeFlagsMembers = members.filter(m => isNodeFlagsMember(m)); + const hasSymbolName = members.some(isSymbolNameMember); + const emit = (name: string, kindName: string) => { + if (hasSymbolName) { + emitStringFactory(w, name, node, members); + } + emitNewFactory(w, factoryName(name, node), kindName, structName, node, members, kindMember, nodeFlagsMembers); + }; if (node.name === "Token") { const tokenKinds = new Set(node.allKinds().map(kind => kind.formatGoConstant())); w.write("func (f *NodeFactory) NewToken(kind TokenSyntaxKind) *Node {"); @@ -531,10 +559,10 @@ function generateNewFactory(w: CodeWriter, node: NodeType) { w.write(""); } else { - emitNewFactory(w, `New${node.name}`, node.syntaxKindName, structName, node, members, kindMember, nodeFlagsMembers); + emit(node.name, node.syntaxKindName); } for (const alias of node.kindAliases) { - emitNewFactory(w, `New${alias}`, alias, structName, node, members, kindMember, nodeFlagsMembers); + emit(alias, alias); } } @@ -1044,12 +1072,12 @@ function generateClone(w: CodeWriter, node: NodeType) { w.push(); w.write(`case ${api.kindType(`SyntaxKind.${node.syntaxKindName}`).formatGoConstant()}:`); w.push(); - w.write(`return cloneNode(f.AsNodeFactory().New${node.name}(${args}), node.AsNode(), f.AsNodeFactory().hooks)`); + w.write(`return cloneNode(f.AsNodeFactory().${factoryName(node.name, node)}(${args}), node.AsNode(), f.AsNodeFactory().hooks)`); w.pop(); for (const alias of node.kindAliases) { w.write(`case Kind${alias}:`); w.push(); - w.write(`return cloneNode(f.AsNodeFactory().New${alias}(${args}), node.AsNode(), f.AsNodeFactory().hooks)`); + w.write(`return cloneNode(f.AsNodeFactory().${factoryName(alias, node)}(${args}), node.AsNode(), f.AsNodeFactory().hooks)`); w.pop(); } w.write("default:"); @@ -1060,7 +1088,7 @@ function generateClone(w: CodeWriter, node: NodeType) { w.write("}"); } else { - w.write(`return cloneNode(f.AsNodeFactory().New${node.name}(${args}), node.AsNode(), f.AsNodeFactory().hooks)`); + w.write(`return cloneNode(f.AsNodeFactory().${factoryName(node.name, node)}(${args}), node.AsNode(), f.AsNodeFactory().hooks)`); } w.pop(); diff --git a/tools/scripts/tsc/options.test.ts b/tools/scripts/tsc/options.test.ts index 8d647eeb2d906..2db02dd1f2d95 100644 --- a/tools/scripts/tsc/options.test.ts +++ b/tools/scripts/tsc/options.test.ts @@ -154,6 +154,14 @@ test("other TypeScript enums retain their Go sources", () => { assert.throws(() => generateEnum({ ...def, goFile: "does-not-exist.go" }), /ENOENT/); }); +test("interned internal symbol names retain their escaped string enum values", () => { + const def = enumDefs.find(def => def.name === "InternalSymbolName")!; + const { members, code } = generateEnum(def); + assert.equal(members.length, 20); + const actual = fs.readFileSync(path.join(repoRoot, def.outDir, "internalSymbolName.enum.ts"), "utf8"); + assert.equal(actual.replaceAll("\r\n", "\n"), code); +}); + test("SyntaxKind is generated without reading its Go definition", () => { const def = enumDefs.find(def => def.name === "SyntaxKind")!; const { members, code } = generateEnum({ ...def, goFile: "does-not-exist.go" }); diff --git a/tools/scripts/tsc/schema.ts b/tools/scripts/tsc/schema.ts index 6d2985d433435..7268e0a8e2ef8 100644 --- a/tools/scripts/tsc/schema.ts +++ b/tools/scripts/tsc/schema.ts @@ -100,6 +100,7 @@ export class PrimitiveType extends TypeBase { const typeMap: Record = { bool: "boolean", int: "number", + SymbolName: "string", }; return typeMap[this.name] || this.name; } @@ -804,6 +805,7 @@ export class SchemaAPI { "ModifierFlags", "NodeFlags", "string", + "SymbolName", "TokenFlags", ]); diff --git a/tsc/internal/api/encoder/decoder_test.go b/tsc/internal/api/encoder/decoder_test.go index def2821cb6a25..dc560a1d8ddf2 100644 --- a/tsc/internal/api/encoder/decoder_test.go +++ b/tsc/internal/api/encoder/decoder_test.go @@ -118,7 +118,7 @@ func TestDecodeSourceFile_VariableDeclaration(t *testing.T) { decl := declList.Declarations.Nodes[0].AsVariableDeclaration() assert.Equal(t, decl.Name().Kind, ast.KindIdentifier) - assert.Equal(t, decl.Name().AsIdentifier().Text, "x") + assert.Equal(t, decl.Name().AsIdentifier().Text.Value(), "x") assert.Assert(t, decl.Initializer != nil) assert.Equal(t, decl.Initializer.Kind, ast.KindNumericLiteral) assert.Equal(t, decl.Initializer.AsNumericLiteral().Text, "1") @@ -165,14 +165,14 @@ func TestDecodeSourceFile_FunctionDeclaration(t *testing.T) { funcDecl := decoded.Statements.Nodes[0].AsFunctionDeclaration() assert.Assert(t, funcDecl.Name() != nil) - assert.Equal(t, funcDecl.Name().AsIdentifier().Text, "add") + assert.Equal(t, funcDecl.Name().AsIdentifier().Text.Value(), "add") assert.Assert(t, funcDecl.Parameters != nil) assert.Equal(t, len(funcDecl.Parameters.Nodes), 2) assert.Assert(t, funcDecl.Type != nil) assert.Assert(t, funcDecl.Body != nil) param0 := funcDecl.Parameters.Nodes[0].AsParameterDeclaration() - assert.Equal(t, param0.Name().AsIdentifier().Text, "a") + assert.Equal(t, param0.Name().AsIdentifier().Text.Value(), "a") assert.Assert(t, param0.Type != nil) } @@ -196,7 +196,7 @@ func TestDecodeSourceFile_ImportDeclaration(t *testing.T) { assert.Assert(t, namedImports.Elements != nil) assert.Equal(t, len(namedImports.Elements.Nodes), 1) spec := namedImports.Elements.Nodes[0].AsImportSpecifier() - assert.Equal(t, spec.Name().AsIdentifier().Text, "bar") + assert.Equal(t, spec.Name().AsIdentifier().Text.Value(), "bar") } func TestDecodeSourceFile_SourcePhaseImport(t *testing.T) { @@ -293,7 +293,7 @@ func TestDecodeSourceFile_ClassDeclaration(t *testing.T) { classDecl := decoded.Statements.Nodes[0].AsClassDeclaration() assert.Assert(t, classDecl.Name() != nil) - assert.Equal(t, classDecl.Name().AsIdentifier().Text, "Foo") + assert.Equal(t, classDecl.Name().AsIdentifier().Text.Value(), "Foo") assert.Assert(t, classDecl.Members != nil) assert.Equal(t, len(classDecl.Members.Nodes), 1) assert.Equal(t, classDecl.Members.Nodes[0].Kind, ast.KindMethodDeclaration) @@ -323,7 +323,7 @@ func TestDecodeNodes_SubtreeRoundTrip(t *testing.T) { assert.Equal(t, decoded.Kind, ast.KindFunctionDeclaration) funcDecl := decoded.AsFunctionDeclaration() assert.Assert(t, funcDecl.Name() != nil) - assert.Equal(t, funcDecl.Name().AsIdentifier().Text, "greet") + assert.Equal(t, funcDecl.Name().AsIdentifier().Text.Value(), "greet") assert.Assert(t, funcDecl.Parameters != nil) assert.Equal(t, len(funcDecl.Parameters.Nodes), 1) assert.Assert(t, funcDecl.Body != nil) diff --git a/tsc/internal/api/encoder/encoder_generated.go b/tsc/internal/api/encoder/encoder_generated.go index 3f695dabfb03a..5970b696eac5c 100644 --- a/tsc/internal/api/encoder/encoder_generated.go +++ b/tsc/internal/api/encoder/encoder_generated.go @@ -663,7 +663,7 @@ func getNodeCommonData(node *ast.Node) uint32 { func recordNodeStrings(node *ast.Node, strs *stringTable) uint32 { switch node.Kind { case ast.KindIdentifier: - return strs.add(node.AsIdentifier().Text, node.Kind, node.Pos(), node.End()) + return strs.add(node.AsIdentifier().Text.Value(), node.Kind, node.Pos(), node.End()) case ast.KindPrivateIdentifier: return strs.add(node.AsPrivateIdentifier().Text, node.Kind, node.Pos(), node.End()) case ast.KindJsxText: diff --git a/tsc/internal/api/session.go b/tsc/internal/api/session.go index 93d6ab53c303d..13f2fb88a8c39 100644 --- a/tsc/internal/api/session.go +++ b/tsc/internal/api/session.go @@ -2903,7 +2903,7 @@ func (s *Session) handleResolveName(ctx context.Context, params *ResolveNamePara return nil, err } - symbol := setup.checker.ResolveName(params.Name, location, ast.SymbolFlags(params.Meaning), params.ExcludeGlobals) + symbol := setup.checker.ResolveName(ast.MakeSymbolName(params.Name), location, ast.SymbolFlags(params.Meaning), params.ExcludeGlobals) if symbol == nil { return nil, nil } @@ -3482,7 +3482,7 @@ func (s *Session) resolveSymbolTablePropertyOfSymbol(ctx context.Context, params return order } } - if order := cmp.Compare(left.Name(), right.Name()); order != 0 { + if order := cmp.Compare(left.Name().Value(), right.Name().Value()); order != 0 { return order } return cmp.Compare(ast.GetSymbolId(left), ast.GetSymbolId(right)) @@ -4314,7 +4314,7 @@ func (s *Session) handleGetTypePredicateOfSignature(ctx context.Context, params resp := &TypePredicateResponse{ Kind: int32(pred.Kind()), ParameterIndex: pred.ParameterIndex(), - ParameterName: pred.ParameterName(), + ParameterName: pred.ParameterName().Value(), } if pred.Type() != nil { resp.Type = setup.sd.newTypeResponse(setup.projectID, pred.Type(), setup.checker) @@ -4600,7 +4600,7 @@ func (s *Session) handleGetPropertyOfType(ctx context.Context, params *GetProper return nil, err } - prop := setup.checker.GetPropertyOfType(t, params.Name) + prop := setup.checker.GetPropertyOfType(t, ast.MakeSymbolName(params.Name)) if prop == nil { return nil, nil } @@ -4621,7 +4621,7 @@ func (s *Session) handleGetTypeOfPropertyOfType(ctx context.Context, params *Get return nil, err } - return setup.sd.newTypeResponse(setup.projectID, setup.checker.GetTypeOfPropertyOfType(t, params.Name), setup.checker), nil + return setup.sd.newTypeResponse(setup.projectID, setup.checker.GetTypeOfPropertyOfType(t, ast.MakeSymbolName(params.Name)), setup.checker), nil } // handleGetConstantValue returns the constant value of an enum member or const enum access. @@ -4892,7 +4892,7 @@ func (s *Session) handleGetMemberInModuleExports(ctx context.Context, params *Ge return nil, nil } - member := setup.checker.TryGetMemberInModuleExports(params.Name, symbol) + member := setup.checker.TryGetMemberInModuleExports(ast.MakeSymbolName(params.Name), symbol) if member == nil { return nil, nil } diff --git a/tsc/internal/api/session_symbolresponse_test.go b/tsc/internal/api/session_symbolresponse_test.go index ca60a1bb1fbf4..fc332836f39e8 100644 --- a/tsc/internal/api/session_symbolresponse_test.go +++ b/tsc/internal/api/session_symbolresponse_test.go @@ -61,7 +61,7 @@ func TestTransientSymbolWithFileDeclarationIsSnapshotOwned(t *testing.T) { class := sourceFile.Statements.Nodes[0] symbol := ast.NewSymbol() symbol.SetFlags(ast.SymbolFlagsClass | ast.SymbolFlagsTransient) - symbol.SetName("C") + symbol.SetName(ast.MakeSymbolName("C")) symbol.SetDeclarations([]*ast.Node{class}) sd := newTestSnapshotData() @@ -85,7 +85,7 @@ func TestSymbolReferencesIdentifyOwnerWithoutDescriptor(t *testing.T) { assert.Assert(t, !strings.Contains(string(encoded), "contentHash")) // A file-owned symbol's relationships are references into the same file. - member := class.Members()["property"] + member := class.Members()[ast.MakeSymbolName("property")] response := newFileSymbolResponse(member) assert.DeepEqual(t, response.Parent, reference) } @@ -109,6 +109,6 @@ func TestContentMappedSymbolsAreSnapshotOwned(t *testing.T) { assert.NilError(t, err) assert.Equal(t, resolved, class) - reference := newSymbolReference(class.Members()["property"]) + reference := newSymbolReference(class.Members()[ast.MakeSymbolName("property")]) assert.Equal(t, reference.File, "") } diff --git a/tsc/internal/ast/ast.go b/tsc/internal/ast/ast.go index 48ff1a8d63d56..d270a817103b6 100644 --- a/tsc/internal/ast/ast.go +++ b/tsc/internal/ast/ast.go @@ -244,10 +244,19 @@ func (n *Node) Body() *Node { return nil } +// TextSymbolName returns Text() as a SymbolName. Identifiers are interned when +// created, so this avoids reinterning their text. +func (n *Node) TextSymbolName() SymbolName { + if n.Kind == KindIdentifier { + return n.AsIdentifier().Text + } + return MakeSymbolName(n.Text()) +} + func (n *Node) Text() string { switch n.Kind { case KindIdentifier: - return n.AsIdentifier().Text + return n.AsIdentifier().Text.Value() case KindPrivateIdentifier: return n.AsPrivateIdentifier().Text case KindStringLiteral: diff --git a/tsc/internal/ast/ast_generated.go b/tsc/internal/ast/ast_generated.go index 58aef6d7bc11c..819bbeeabd8f3 100644 --- a/tsc/internal/ast/ast_generated.go +++ b/tsc/internal/ast/ast_generated.go @@ -667,10 +667,14 @@ func IsToken(node *Node) bool { type Identifier struct { PrimaryExpressionBase FlowNodeBase - Text string + Text SymbolName } func (f *NodeFactory) NewIdentifier(text string) *Node { + return f.NewIdentifierFromSymbolName(MakeSymbolName(text)) +} + +func (f *NodeFactory) NewIdentifierFromSymbolName(text SymbolName) *Node { data := f.identifierArena.New() data.Text = text f.textCount++ @@ -678,7 +682,7 @@ func (f *NodeFactory) NewIdentifier(text string) *Node { } func (node *Identifier) Clone(f NodeFactoryCoercible) *Node { - return cloneNode(f.AsNodeFactory().NewIdentifier(node.Text), node.AsNode(), f.AsNodeFactory().hooks) + return cloneNode(f.AsNodeFactory().NewIdentifierFromSymbolName(node.Text), node.AsNode(), f.AsNodeFactory().hooks) } func IsIdentifier(node *Node) bool { diff --git a/tsc/internal/ast/nodeaccessors_test.go b/tsc/internal/ast/nodeaccessors_test.go index c18342076dbdb..3faacc98eb351 100644 --- a/tsc/internal/ast/nodeaccessors_test.go +++ b/tsc/internal/ast/nodeaccessors_test.go @@ -167,7 +167,7 @@ func TestNodeHeaderKeepsPayloadAlive(t *testing.T) { factory = nil runtime.GC() assert.Equal(t, root.AsPropertyAccessExpression().Name(), name) - assert.Equal(t, name.AsIdentifier().Text, "property") + assert.Equal(t, name.Text(), "property") assert.Equal(t, name.Parent, root) clone := root.Clone(ast.NewNodeFactory(ast.NodeFactoryHooks{})) runtime.GC() diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index 00312310691c5..b505258ad3b23 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -1,11 +1,15 @@ package ast import ( + "bytes" + "errors" "strings" "sync/atomic" + "unicode/utf8" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/debug" + "github.com/microsoft/TypeScript/tsc/internal/json" ) // Symbol stores flags, checkFlags, and id uniquely for every symbol instance, but may share @@ -21,7 +25,7 @@ type Symbol struct { // Every symbol references a symbolData structure that may be shared with other symbols. type symbolData struct { - name string + name SymbolName declarations []*Node valueDeclaration *Node parent *Symbol @@ -42,7 +46,7 @@ type SymbolExtraArena struct { func (s *Symbol) Flags() SymbolFlags { return s.flags } func (s *Symbol) CheckFlags() CheckFlags { return s.checkFlags } -func (s *Symbol) Name() string { return s.data.name } +func (s *Symbol) Name() SymbolName { return s.data.name } func (s *Symbol) Declarations() []*Node { return s.data.declarations } func (s *Symbol) ValueDeclaration() *Node { return s.data.valueDeclaration } func (s *Symbol) Parent() *Symbol { return s.data.parent } @@ -70,7 +74,7 @@ func (s *Symbol) ExportSymbol() *Symbol { func (s *Symbol) SetFlags(value SymbolFlags) { s.flags = value } func (s *Symbol) SetCheckFlags(value CheckFlags) { s.checkFlags = value } -func (s *Symbol) SetName(value string) { s.data.name = value } +func (s *Symbol) SetName(value SymbolName) { s.data.name = value } func (s *Symbol) SetDeclarations(value []*Node) { s.data.declarations = value } func (s *Symbol) SetValueDeclaration(value *Node) { s.data.valueDeclaration = value } func (s *Symbol) SetParent(value *Symbol) { s.data.parent = value } @@ -109,6 +113,7 @@ type SymbolWithData struct { // Initializes a SymbolWithData instance and returns the embedded Symbol. func (sd *SymbolWithData) Initialize() *Symbol { sd.s.data = &sd.d + sd.d.name = EmptySymbolName return &sd.s } @@ -163,40 +168,296 @@ func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags { return s.Flags() } -// SymbolTable +// SymbolName is an interned name used for symbol identity and lookup. +// Its zero value denotes an unset name and must not be passed to Value. +type SymbolName struct { + id uint32 +} + +func MakeSymbolName(text string) SymbolName { + return SymbolName{symbolNames.intern(text)} +} + +func (name SymbolName) Value() string { + return symbolNames.text(name.id) +} -type SymbolTable map[string]*Symbol +func (name SymbolName) IsZero() bool { + return name == SymbolName{} +} + +func (name SymbolName) String() string { + if name.IsZero() { + return "" + } + return name.Value() +} + +// MarshalText uses the escaped spelling so internal names remain valid UTF-8. +func (name SymbolName) MarshalText() ([]byte, error) { + if name.IsZero() { + return nil, errors.New("cannot marshal an unset symbol name as text") + } + text := EscapeSymbolName(name) + if !utf8.ValidString(text) { + return nil, errors.New("symbol name contains invalid UTF-8") + } + return []byte(text), nil +} + +func (name *SymbolName) UnmarshalText(text []byte) error { + if !utf8.Valid(text) { + return errors.New("symbol name contains invalid UTF-8") + } + *name = UnescapeSymbolName(string(text)) + return nil +} + +// MarshalJSON preserves the distinction between unset and empty names. +func (name SymbolName) MarshalJSON() ([]byte, error) { + if name.IsZero() { + return []byte("null"), nil + } + text, err := name.MarshalText() + if err != nil { + return nil, err + } + return json.Marshal(string(text)) +} + +func (name *SymbolName) UnmarshalJSON(data []byte) error { + if bytes.Equal(bytes.TrimSpace(data), []byte("null")) { + *name = SymbolName{} + return nil + } + if !utf8.Valid(data) { + return errors.New("symbol name contains invalid UTF-8") + } + var text string + if err := json.Unmarshal(data, &text); err != nil { + return err + } + return name.UnmarshalText([]byte(text)) +} + +// EmptySymbolName is a valid empty name, distinct from an unset zero handle. +var EmptySymbolName = MakeSymbolName("") + +type SymbolTable map[SymbolName]*Symbol + +// Fixed symbol names are interned once and shared by compiler consumers. +var ( + SymbolNameZero = MakeSymbolName("0") + SymbolNameUnresolved = MakeSymbolName("<>") + SymbolNameAbstractModuleSource = MakeSymbolName("AbstractModuleSource") + SymbolNameArray = MakeSymbolName("Array") + SymbolNameArrayBuffer = MakeSymbolName("ArrayBuffer") + SymbolNameArrayConstructor = MakeSymbolName("ArrayConstructor") + SymbolNameArrayLike = MakeSymbolName("ArrayLike") + SymbolNameAsyncDisposable = MakeSymbolName("AsyncDisposable") + SymbolNameAsyncDisposableStack = MakeSymbolName("AsyncDisposableStack") + SymbolNameAsyncGenerator = MakeSymbolName("AsyncGenerator") + SymbolNameAsyncGeneratorFunction = MakeSymbolName("AsyncGeneratorFunction") + SymbolNameAsyncIterable = MakeSymbolName("AsyncIterable") + SymbolNameAsyncIterableIterator = MakeSymbolName("AsyncIterableIterator") + SymbolNameAsyncIterator = MakeSymbolName("AsyncIterator") + SymbolNameAsyncIteratorObject = MakeSymbolName("AsyncIteratorObject") + SymbolNameAtomics = MakeSymbolName("Atomics") + SymbolNameAwaited = MakeSymbolName("Awaited") + SymbolNameBigInt = MakeSymbolName("BigInt") + SymbolNameBigInt64Array = MakeSymbolName("BigInt64Array") + SymbolNameBigUint64Array = MakeSymbolName("BigUint64Array") + SymbolNameBoolean = MakeSymbolName("Boolean") + SymbolNameBuiltinIteratorReturn = MakeSymbolName("BuiltinIteratorReturn") + SymbolNameCallableFunction = MakeSymbolName("CallableFunction") + SymbolNameCapitalize = MakeSymbolName("Capitalize") + SymbolNameClassAccessorDecoratorContext = MakeSymbolName("ClassAccessorDecoratorContext") + SymbolNameClassAccessorDecoratorResult = MakeSymbolName("ClassAccessorDecoratorResult") + SymbolNameClassAccessorDecoratorTarget = MakeSymbolName("ClassAccessorDecoratorTarget") + SymbolNameClassDecoratorContext = MakeSymbolName("ClassDecoratorContext") + SymbolNameClassFieldDecoratorContext = MakeSymbolName("ClassFieldDecoratorContext") + SymbolNameClassGetterDecoratorContext = MakeSymbolName("ClassGetterDecoratorContext") + SymbolNameClassMethodDecoratorContext = MakeSymbolName("ClassMethodDecoratorContext") + SymbolNameClassSetterDecoratorContext = MakeSymbolName("ClassSetterDecoratorContext") + SymbolNameDataView = MakeSymbolName("DataView") + SymbolNameDate = MakeSymbolName("Date") + SymbolNameDateTimeFormat = MakeSymbolName("DateTimeFormat") + SymbolNameDisposable = MakeSymbolName("Disposable") + SymbolNameDisposableStack = MakeSymbolName("DisposableStack") + SymbolNameElement = MakeSymbolName("Element") + SymbolNameElementAttributesProperty = MakeSymbolName("ElementAttributesProperty") + SymbolNameElementChildrenAttribute = MakeSymbolName("ElementChildrenAttribute") + SymbolNameElementClass = MakeSymbolName("ElementClass") + SymbolNameElementType = MakeSymbolName("ElementType") + SymbolNameError = MakeSymbolName("Error") + SymbolNameErrorConstructor = MakeSymbolName("ErrorConstructor") + SymbolNameEventTarget = MakeSymbolName("EventTarget") + SymbolNameExtract = MakeSymbolName("Extract") + SymbolNameFloat16Array = MakeSymbolName("Float16Array") + SymbolNameFloat32Array = MakeSymbolName("Float32Array") + SymbolNameFloat64Array = MakeSymbolName("Float64Array") + SymbolNameFunction = MakeSymbolName("Function") + SymbolNameGenerator = MakeSymbolName("Generator") + SymbolNameIArguments = MakeSymbolName("IArguments") + SymbolNameImportAttributes = MakeSymbolName("ImportAttributes") + SymbolNameImportCallOptions = MakeSymbolName("ImportCallOptions") + SymbolNameImportMeta = MakeSymbolName("ImportMeta") + SymbolNameImportMetaExpression = MakeSymbolName("ImportMetaExpression") + SymbolNameInt16Array = MakeSymbolName("Int16Array") + SymbolNameInt32Array = MakeSymbolName("Int32Array") + SymbolNameInt8Array = MakeSymbolName("Int8Array") + SymbolNameIntl = MakeSymbolName("Intl") + SymbolNameIntrinsicAttributes = MakeSymbolName("IntrinsicAttributes") + SymbolNameIntrinsicClassAttributes = MakeSymbolName("IntrinsicClassAttributes") + SymbolNameIntrinsicElements = MakeSymbolName("IntrinsicElements") + SymbolNameIterable = MakeSymbolName("Iterable") + SymbolNameIterableIterator = MakeSymbolName("IterableIterator") + SymbolNameIterator = MakeSymbolName("Iterator") + SymbolNameIteratorConstructor = MakeSymbolName("IteratorConstructor") + SymbolNameIteratorObject = MakeSymbolName("IteratorObject") + SymbolNameIteratorReturnResult = MakeSymbolName("IteratorReturnResult") + SymbolNameIteratorYieldResult = MakeSymbolName("IteratorYieldResult") + SymbolNameJSON = MakeSymbolName("JSON") + SymbolNameJSX = MakeSymbolName("JSX") + SymbolNameK = MakeSymbolName("K") + SymbolNameLibraryManagedAttributes = MakeSymbolName("LibraryManagedAttributes") + SymbolNameLowercase = MakeSymbolName("Lowercase") + SymbolNameMap = MakeSymbolName("Map") + SymbolNameMapConstructor = MakeSymbolName("MapConstructor") + SymbolNameMath = MakeSymbolName("Math") + SymbolNameNaN = MakeSymbolName("NaN") + SymbolNameNewableFunction = MakeSymbolName("NewableFunction") + SymbolNameNoInfer = MakeSymbolName("NoInfer") + SymbolNameNode = MakeSymbolName("Node") + SymbolNameNodeList = MakeSymbolName("NodeList") + SymbolNameNonNullable = MakeSymbolName("NonNullable") + SymbolNameNumber = MakeSymbolName("Number") + SymbolNameNumberConstructor = MakeSymbolName("NumberConstructor") + SymbolNameNumberFormat = MakeSymbolName("NumberFormat") + SymbolNameObject = MakeSymbolName("Object") + SymbolNameObjectConstructor = MakeSymbolName("ObjectConstructor") + SymbolNameOmit = MakeSymbolName("Omit") + SymbolNamePartial = MakeSymbolName("Partial") + SymbolNamePick = MakeSymbolName("Pick") + SymbolNamePromise = MakeSymbolName("Promise") + SymbolNamePromiseConstructor = MakeSymbolName("PromiseConstructor") + SymbolNamePromiseLike = MakeSymbolName("PromiseLike") + SymbolNameRawJSON = MakeSymbolName("RawJSON") + SymbolNameReadonly = MakeSymbolName("Readonly") + SymbolNameReadonlyArray = MakeSymbolName("ReadonlyArray") + SymbolNameReadonlyMap = MakeSymbolName("ReadonlyMap") + SymbolNameReadonlySet = MakeSymbolName("ReadonlySet") + SymbolNameRecord = MakeSymbolName("Record") + SymbolNameReflect = MakeSymbolName("Reflect") + SymbolNameRegExp = MakeSymbolName("RegExp") + SymbolNameRegExpConstructor = MakeSymbolName("RegExpConstructor") + SymbolNameRegExpExecArray = MakeSymbolName("RegExpExecArray") + SymbolNameRegExpMatchArray = MakeSymbolName("RegExpMatchArray") + SymbolNameRelativeTimeFormat = MakeSymbolName("RelativeTimeFormat") + SymbolNameRequired = MakeSymbolName("Required") + SymbolNameSet = MakeSymbolName("Set") + SymbolNameSharedArrayBuffer = MakeSymbolName("SharedArrayBuffer") + SymbolNameString = MakeSymbolName("String") + SymbolNameStringConstructor = MakeSymbolName("StringConstructor") + SymbolNameSymbol = MakeSymbolName("Symbol") + SymbolNameSymbolConstructor = MakeSymbolName("SymbolConstructor") + SymbolNameT = MakeSymbolName("T") + SymbolNameTemplateStringsArray = MakeSymbolName("TemplateStringsArray") + SymbolNameThisType = MakeSymbolName("ThisType") + SymbolNameTypedPropertyDescriptor = MakeSymbolName("TypedPropertyDescriptor") + SymbolNameUint16Array = MakeSymbolName("Uint16Array") + SymbolNameUint32Array = MakeSymbolName("Uint32Array") + SymbolNameUint8Array = MakeSymbolName("Uint8Array") + SymbolNameUint8ArrayConstructor = MakeSymbolName("Uint8ArrayConstructor") + SymbolNameUint8ClampedArray = MakeSymbolName("Uint8ClampedArray") + SymbolNameUncapitalize = MakeSymbolName("Uncapitalize") + SymbolNameUppercase = MakeSymbolName("Uppercase") + SymbolNameWeakMap = MakeSymbolName("WeakMap") + SymbolNameWeakSet = MakeSymbolName("WeakSet") + SymbolNameESModule = MakeSymbolName("__esModule") + SymbolNameUnderscoreDefault = MakeSymbolName("_default") + SymbolNameAny = MakeSymbolName("any") + SymbolNameArg = MakeSymbolName("arg") + SymbolNameArgs = MakeSymbolName("args") + SymbolNameArguments = MakeSymbolName("arguments") + SymbolNameAsyncIteratorProperty = MakeSymbolName("asyncIterator") + SymbolNameBind = MakeSymbolName("bind") + SymbolNameBooleanKeyword = MakeSymbolName("boolean") + SymbolNameCaller = MakeSymbolName("caller") + SymbolNameChildren = MakeSymbolName("children") + SymbolNameClass = MakeSymbolName("class") + SymbolNameClassName = MakeSymbolName("className") + SymbolNameConst = MakeSymbolName("const") + SymbolNameContext = MakeSymbolName("context") + SymbolNameDescriptor = MakeSymbolName("descriptor") + SymbolNameDone = MakeSymbolName("done") + SymbolNameExports = MakeSymbolName("exports") + SymbolNameFor = MakeSymbolName("for") + SymbolNameGetProperty = MakeSymbolName("get") + SymbolNameGlobal = MakeSymbolName("global") + SymbolNameGlobalThis = MakeSymbolName("globalThis") + SymbolNameHasInstance = MakeSymbolName("hasInstance") + SymbolNameHtmlFor = MakeSymbolName("htmlFor") + SymbolNameIteratorProperty = MakeSymbolName("iterator") + SymbolNameLength = MakeSymbolName("length") + SymbolNameMeta = MakeSymbolName("meta") + SymbolNameModule = MakeSymbolName("module") + SymbolNameName = MakeSymbolName("name") + SymbolNameNever = MakeSymbolName("never") + SymbolNameNext = MakeSymbolName("next") + SymbolNameNumberKeyword = MakeSymbolName("number") + SymbolNameParameterIndex = MakeSymbolName("parameterIndex") + SymbolNamePrivate = MakeSymbolName("private") + SymbolNamePropertyKey = MakeSymbolName("propertyKey") + SymbolNameProps = MakeSymbolName("props") + SymbolNamePrototype = MakeSymbolName("prototype") + SymbolNameRequire = MakeSymbolName("require") + SymbolNameReturn = MakeSymbolName("return") + SymbolNameSelf = MakeSymbolName("self") + SymbolNameSetProperty = MakeSymbolName("set") + SymbolNameStatic = MakeSymbolName("static") + SymbolNameStringKeyword = MakeSymbolName("string") + SymbolNameTarget = MakeSymbolName("target") + SymbolNameThen = MakeSymbolName("then") + SymbolNameThrow = MakeSymbolName("throw") + SymbolNameUndefined = MakeSymbolName("undefined") + SymbolNameUnknown = MakeSymbolName("unknown") + SymbolNameValue = MakeSymbolName("value") + SymbolNameWith = MakeSymbolName("with") + SymbolNameWritable = MakeSymbolName("writable") +) const InternalSymbolNamePrefix = "\xFE" // Invalid UTF8 sequence, will never occur as IdentifierName -const ( - InternalSymbolNameCall = InternalSymbolNamePrefix + "call" // Call signatures - InternalSymbolNameConstructor = InternalSymbolNamePrefix + "constructor" // Constructor implementations - InternalSymbolNameNew = InternalSymbolNamePrefix + "new" // Constructor signatures - InternalSymbolNameIndex = InternalSymbolNamePrefix + "index" // Index signatures - InternalSymbolNameExportStar = InternalSymbolNamePrefix + "export" // Module export * declarations - InternalSymbolNameGlobal = InternalSymbolNamePrefix + "global" // Global self-reference - InternalSymbolNameMissing = InternalSymbolNamePrefix + "missing" // Indicates missing symbol - InternalSymbolNameType = InternalSymbolNamePrefix + "type" // Anonymous type literal symbol - InternalSymbolNameObject = InternalSymbolNamePrefix + "object" // Anonymous object literal declaration - InternalSymbolNameJSXAttributes = InternalSymbolNamePrefix + "jsxAttributes" // Anonymous JSX attributes object literal declaration - InternalSymbolNameClass = InternalSymbolNamePrefix + "class" // Unnamed class expression - InternalSymbolNameFunction = InternalSymbolNamePrefix + "function" // Unnamed function expression - InternalSymbolNameComputed = InternalSymbolNamePrefix + "computed" // Computed property name declaration with dynamic name - InternalSymbolNameAssignmentDeclaration = InternalSymbolNamePrefix + "assignment" // Assignment declarations - InternalSymbolNameInstantiationExpression = InternalSymbolNamePrefix + "instantiationExpression" // Instantiation expressions - InternalSymbolNameImportAttributes = InternalSymbolNamePrefix + "importAttributes" - InternalSymbolNameExportEquals = "export=" // Export assignment symbol - InternalSymbolNameDefault = "default" // Default export symbol (technically not wholly internal, but included here for usability) - InternalSymbolNameThis = "this" - InternalSymbolNameModuleExports = "module.exports" +var ( + InternalSymbolNameCall = MakeSymbolName(InternalSymbolNamePrefix + "call") // Call signatures + InternalSymbolNameConstructor = MakeSymbolName(InternalSymbolNamePrefix + "constructor") // Constructor implementations + InternalSymbolNameNew = MakeSymbolName(InternalSymbolNamePrefix + "new") // Constructor signatures + InternalSymbolNameIndex = MakeSymbolName(InternalSymbolNamePrefix + "index") // Index signatures + InternalSymbolNameExportStar = MakeSymbolName(InternalSymbolNamePrefix + "export") // Module export * declarations + InternalSymbolNameGlobal = MakeSymbolName(InternalSymbolNamePrefix + "global") // Global self-reference + InternalSymbolNameMissing = MakeSymbolName(InternalSymbolNamePrefix + "missing") // Indicates missing symbol + InternalSymbolNameType = MakeSymbolName(InternalSymbolNamePrefix + "type") // Anonymous type literal symbol + InternalSymbolNameObject = MakeSymbolName(InternalSymbolNamePrefix + "object") // Anonymous object literal declaration + InternalSymbolNameJSXAttributes = MakeSymbolName(InternalSymbolNamePrefix + "jsxAttributes") // Anonymous JSX attributes object literal declaration + InternalSymbolNameClass = MakeSymbolName(InternalSymbolNamePrefix + "class") // Unnamed class expression + InternalSymbolNameFunction = MakeSymbolName(InternalSymbolNamePrefix + "function") // Unnamed function expression + InternalSymbolNameComputed = MakeSymbolName(InternalSymbolNamePrefix + "computed") // Computed property name declaration with dynamic name + InternalSymbolNameAssignmentDeclaration = MakeSymbolName(InternalSymbolNamePrefix + "assignment") // Assignment declarations + InternalSymbolNameInstantiationExpression = MakeSymbolName(InternalSymbolNamePrefix + "instantiationExpression") // Instantiation expressions + InternalSymbolNameImportAttributes = MakeSymbolName(InternalSymbolNamePrefix + "importAttributes") + InternalSymbolNameExportEquals = MakeSymbolName("export=") // Export assignment symbol + InternalSymbolNameDefault = MakeSymbolName("default") // Default export symbol (technically not wholly internal, but included here for usability) + InternalSymbolNameThis = MakeSymbolName("this") + InternalSymbolNameModuleExports = MakeSymbolName("module.exports") ) -func SymbolName(symbol *Symbol) string { +// SymbolNameText returns a display name, preserving private identifier spelling. +func SymbolNameText(symbol *Symbol) string { if symbol.ValueDeclaration() != nil && IsPrivateIdentifierClassElementDeclaration(symbol.ValueDeclaration()) { return symbol.ValueDeclaration().Name().Text() } - return symbol.Name() + return symbol.Name().Value() } // EscapeAllInternalSymbolNames replaces internal symbol name markers ("\xFE") with "__". @@ -204,7 +465,8 @@ func EscapeAllInternalSymbolNames(name string) string { return strings.ReplaceAll(name, InternalSymbolNamePrefix, "__") } -func EscapeInternalSymbolName(name string) string { +func EscapeInternalSymbolName(symbolName SymbolName) string { + name := symbolName.Value() if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok { return "__" + rest } @@ -215,7 +477,8 @@ func EscapeInternalSymbolName(name string) string { // form. Internal names (prefixed with the "\xFE" sentinel) become "__"-prefixed, // and user names that already begin with "__" gain an extra leading underscore // so they can be distinguished from internal names. -func EscapeSymbolName(name string) string { +func EscapeSymbolName(symbolName SymbolName) string { + name := symbolName.Value() if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok { return "__" + rest } @@ -224,3 +487,13 @@ func EscapeSymbolName(name string) string { } return name } + +// UnescapeSymbolName reverses EscapeSymbolName and interns the decoded name. +func UnescapeSymbolName(name string) SymbolName { + if strings.HasPrefix(name, "___") { + name = name[1:] + } else if rest, ok := strings.CutPrefix(name, "__"); ok { + name = InternalSymbolNamePrefix + rest + } + return MakeSymbolName(name) +} diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index 1f8f44aaa66d2..8c3757378db33 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -3,13 +3,169 @@ package ast_test import ( "reflect" "runtime" + "strconv" + "strings" + "sync" "testing" "unsafe" "github.com/microsoft/TypeScript/tsc/internal/ast" + "github.com/microsoft/TypeScript/tsc/internal/json" "gotest.tools/v3/assert" ) +func TestSymbolNameInterning(t *testing.T) { + t.Parallel() + for _, text := range []string{"", "name", "__call", "\xFEcall", "#private", "\"module\"", "\u03C0"} { + t.Run(text, func(t *testing.T) { + t.Parallel() + name := ast.MakeSymbolName(text) + otherName := ast.MakeSymbolName(strings.Clone(text)) + symbol := ast.NewSymbol() + symbol.SetName(name) + storedName := symbol.Name() + assert.Assert(t, storedName == otherName) + assert.Equal(t, storedName.Value(), text) + + table := ast.SymbolTable{name: symbol} + assert.Equal(t, table[otherName], symbol) + assert.Equal(t, ast.SymbolNameText(symbol), text) + + shared := ast.NewSymbol() + shared.SetSymbolData(symbol) + assert.Assert(t, shared.Name() == otherName) + shared.SetName(ast.MakeSymbolName(text + "other")) + assert.Assert(t, symbol.Name() == shared.Name()) + }) + } + assert.Assert(t, ast.InternalSymbolNameCall != ast.MakeSymbolName("__call")) + assert.Assert(t, ast.NewSymbol().Name() == ast.MakeSymbolName("")) + assert.Assert(t, new(ast.SymbolWithData).Initialize().Name() == ast.MakeSymbolName("")) + assert.Equal(t, reflect.TypeFor[ast.SymbolName]().Name(), "SymbolName") +} + +func TestConcurrentSymbolNameInterning(t *testing.T) { + t.Parallel() + const workers = 8 + const count = 50_000 + results := make([][]ast.SymbolName, workers) + var wg sync.WaitGroup + for w := range workers { + wg.Go(func() { + var cache ast.SymbolNameCache + names := make([]ast.SymbolName, count) + for i := range count { + // Workers start at different offsets so inserts race. + j := (i + w*count/workers) % count + text := "concurrentName" + strconv.Itoa(j) + if i%2 == 0 { + names[j] = cache.Make(text) + } else { + names[j] = ast.MakeSymbolName(text) + } + } + results[w] = names + }) + } + wg.Wait() + for i := range count { + text := "concurrentName" + strconv.Itoa(i) + for w := range workers { + assert.Assert(t, results[w][i] == results[0][i]) + } + assert.Equal(t, results[0][i].Value(), text) + } +} + +func TestPreinternedSymbolNames(t *testing.T) { + t.Parallel() + for text, name := range map[string]ast.SymbolName{ + "": ast.EmptySymbolName, + "prototype": ast.SymbolNamePrototype, + "Symbol": ast.SymbolNameSymbol, + "JSX": ast.SymbolNameJSX, + "iterator": ast.SymbolNameIteratorProperty, + "Iterator": ast.SymbolNameIterator, + "unknown": ast.SymbolNameUnknown, + } { + t.Run(text, func(t *testing.T) { + t.Parallel() + assert.Assert(t, name == ast.MakeSymbolName(strings.Clone(text))) + assert.Equal(t, name.Value(), text) + }) + } +} + +func TestSymbolNameMarshaling(t *testing.T) { + t.Parallel() + for text, escaped := range map[string]string{ + "": "", + "name": "name", + "\xFEcall": "__call", + "\xFE@iterator": "__@iterator", + "__call": "___call", + "___call": "____call", + "\u03C0": "\u03C0", + } { + t.Run(text, func(t *testing.T) { + t.Parallel() + name := ast.MakeSymbolName(text) + assert.Assert(t, !name.IsZero()) + assert.Equal(t, name.String(), text) + encodedText, err := name.MarshalText() + assert.NilError(t, err) + assert.Equal(t, string(encodedText), escaped) + var decodedText ast.SymbolName + assert.NilError(t, decodedText.UnmarshalText(encodedText)) + assert.Assert(t, decodedText == name) + + encodedJSON, err := json.Marshal(name) + assert.NilError(t, err) + var jsonText string + assert.NilError(t, json.Unmarshal(encodedJSON, &jsonText)) + assert.Equal(t, jsonText, escaped) + var decodedJSON ast.SymbolName + assert.NilError(t, json.Unmarshal(encodedJSON, &decodedJSON)) + assert.Assert(t, decodedJSON == name) + + table := map[ast.SymbolName]int{name: 1} + encodedTable, err := json.Marshal(table) + assert.NilError(t, err) + var decodedTable map[ast.SymbolName]int + assert.NilError(t, json.Unmarshal(encodedTable, &decodedTable)) + assert.Equal(t, decodedTable[name], 1) + }) + } +} + +func TestUnsetSymbolNameMarshaling(t *testing.T) { + t.Parallel() + var name ast.SymbolName + assert.Assert(t, name.IsZero()) + _, err := name.MarshalText() + assert.ErrorContains(t, err, "unset") + data, err := json.Marshal(name) + assert.NilError(t, err) + assert.Equal(t, string(data), "null") + name = ast.EmptySymbolName + assert.NilError(t, json.Unmarshal(data, &name)) + assert.Assert(t, name.IsZero()) +} + +func TestInvalidSymbolNameMarshaling(t *testing.T) { + t.Parallel() + name := ast.MakeSymbolName("name\xFF") + _, err := name.MarshalText() + assert.ErrorContains(t, err, "UTF-8") + _, err = json.Marshal(name) + assert.ErrorContains(t, err, "UTF-8") + assert.ErrorContains(t, name.UnmarshalText([]byte{0xFF}), "UTF-8") + original := name + err = json.Unmarshal([]byte("123"), &name) + assert.Assert(t, err != nil) + assert.Assert(t, name == original) +} + func TestSymbolFieldsArePrivate(t *testing.T) { t.Parallel() for field := range reflect.TypeFor[ast.Symbol]().Fields() { @@ -23,7 +179,7 @@ func TestSymbolAccessors(t *testing.T) { symbol := ast.NewSymbol() assert.Equal(t, symbol.Flags(), ast.SymbolFlagsNone) assert.Equal(t, symbol.CheckFlags(), ast.CheckFlags(0)) - assert.Equal(t, symbol.Name(), "") + assert.Equal(t, symbol.Name().Value(), "") assert.Assert(t, symbol.Declarations() == nil) assert.Assert(t, symbol.ValueDeclaration() == nil) assert.Assert(t, symbol.Members() == nil) @@ -38,12 +194,12 @@ func TestSymbolAccessors(t *testing.T) { parent := ast.NewSymbol() exportSymbol := ast.NewSymbol() declarations := []*ast.Node{declaration} - members := ast.SymbolTable{"member": member} - exports := ast.SymbolTable{"export": export} + members := ast.SymbolTable{ast.MakeSymbolName("member"): member} + exports := ast.SymbolTable{ast.MakeSymbolName("export"): export} symbol.SetFlags(ast.SymbolFlagsClass | ast.SymbolFlagsTransient) symbol.SetCheckFlags(ast.CheckFlagsReadonly) - symbol.SetName("C") + symbol.SetName(ast.MakeSymbolName("C")) symbol.SetDeclarations(declarations) symbol.SetValueDeclaration(declaration) symbol.SetMembers(members, &arena) @@ -53,11 +209,11 @@ func TestSymbolAccessors(t *testing.T) { assert.Equal(t, symbol.Flags(), ast.SymbolFlagsClass|ast.SymbolFlagsTransient) assert.Equal(t, symbol.CheckFlags(), ast.CheckFlagsReadonly) - assert.Equal(t, symbol.Name(), "C") + assert.Equal(t, symbol.Name().Value(), "C") assert.Equal(t, symbol.Declarations()[0], declaration) assert.Equal(t, symbol.ValueDeclaration(), declaration) - assert.Equal(t, symbol.Members()["member"], member) - assert.Equal(t, symbol.Exports()["export"], export) + assert.Equal(t, symbol.Members()[ast.MakeSymbolName("member")], member) + assert.Equal(t, symbol.Exports()[ast.MakeSymbolName("export")], export) assert.Equal(t, symbol.Parent(), parent) assert.Equal(t, symbol.ExportSymbol(), exportSymbol) @@ -65,14 +221,14 @@ func TestSymbolAccessors(t *testing.T) { assert.Equal(t, symbol.Declarations()[0], otherDeclaration) symbol.Declarations()[0] = declaration assert.Equal(t, declarations[0], declaration) - symbol.Members()["added"] = export - assert.Equal(t, members["added"], export) - symbol.Exports()["added"] = member - assert.Equal(t, exports["added"], member) + symbol.Members()[ast.MakeSymbolName("added")] = export + assert.Equal(t, members[ast.MakeSymbolName("added")], export) + symbol.Exports()[ast.MakeSymbolName("added")] = member + assert.Equal(t, exports[ast.MakeSymbolName("added")], member) symbol.SetFlags(ast.SymbolFlagsNone) symbol.SetCheckFlags(0) - symbol.SetName("") + symbol.SetName(ast.MakeSymbolName("")) symbol.SetDeclarations(nil) symbol.SetValueDeclaration(nil) symbol.SetMembers(nil, &arena) @@ -82,7 +238,7 @@ func TestSymbolAccessors(t *testing.T) { assert.Equal(t, symbol.Flags(), ast.SymbolFlagsNone) assert.Equal(t, symbol.CheckFlags(), ast.CheckFlags(0)) - assert.Equal(t, symbol.Name(), "") + assert.Equal(t, symbol.Name().Value(), "") assert.Assert(t, symbol.Declarations() == nil) assert.Assert(t, symbol.ValueDeclaration() == nil) assert.Assert(t, symbol.Members() == nil) @@ -99,14 +255,14 @@ func TestSymbolTableInitialization(t *testing.T) { export := ast.NewSymbol() members := ast.GetMembers(symbol, &arena) - members["member"] = member - assert.Equal(t, symbol.Members()["member"], member) - assert.Equal(t, ast.GetMembers(symbol, &arena)["member"], member) + members[ast.MakeSymbolName("member")] = member + assert.Equal(t, symbol.Members()[ast.MakeSymbolName("member")], member) + assert.Equal(t, ast.GetMembers(symbol, &arena)[ast.MakeSymbolName("member")], member) exports := ast.GetExports(symbol, &arena) - exports["export"] = export - assert.Equal(t, symbol.Exports()["export"], export) - assert.Equal(t, ast.GetExports(symbol, &arena)["export"], export) + exports[ast.MakeSymbolName("export")] = export + assert.Equal(t, symbol.Exports()[ast.MakeSymbolName("export")], export) + assert.Equal(t, ast.GetExports(symbol, &arena)[ast.MakeSymbolName("export")], export) symbol.SetMembers(nil, &arena) symbol.SetExports(nil, &arena) @@ -118,7 +274,7 @@ func TestSymbolTableInitialization(t *testing.T) { func TestSymbolHotRecordLayout(t *testing.T) { t.Parallel() - assert.Equal(t, unsafe.Sizeof(ast.SymbolWithData{}), unsafe.Sizeof(ast.Symbol{})+8*unsafe.Sizeof((*ast.Node)(nil))) + assert.Equal(t, unsafe.Sizeof(ast.SymbolWithData{}), unsafe.Sizeof(ast.Symbol{})+7*unsafe.Sizeof((*ast.Node)(nil))) } func TestSymbolNilExtraFieldsDoNotAllocate(t *testing.T) { //nolint:paralleltest @@ -142,12 +298,12 @@ func TestSymbolSharedExtraData(t *testing.T) { alias.SetSymbolData(symbol) member := ast.NewSymbol() export := ast.NewSymbol() - alias.SetMembers(ast.SymbolTable{"member": member}, &arena) - symbol.SetExports(ast.SymbolTable{"export": export}, &otherArena) + alias.SetMembers(ast.SymbolTable{ast.MakeSymbolName("member"): member}, &arena) + symbol.SetExports(ast.SymbolTable{ast.MakeSymbolName("export"): export}, &otherArena) alias.SetExportSymbol(export, &otherArena) runtime.GC() - assert.Equal(t, symbol.Members()["member"], member) - assert.Equal(t, alias.Exports()["export"], export) + assert.Equal(t, symbol.Members()[ast.MakeSymbolName("member")], member) + assert.Equal(t, alias.Exports()[ast.MakeSymbolName("export")], export) assert.Equal(t, symbol.ExportSymbol(), export) symbol.SetMembers(nil, &otherArena) alias.SetExports(nil, &arena) @@ -155,14 +311,14 @@ func TestSymbolSharedExtraData(t *testing.T) { assert.Assert(t, alias.Members() == nil) assert.Assert(t, symbol.Exports() == nil) assert.Assert(t, alias.ExportSymbol() == nil) - ast.GetMembers(alias, &otherArena)["new"] = export - ast.GetExports(symbol, &arena)["new"] = member + ast.GetMembers(alias, &otherArena)[ast.MakeSymbolName("new")] = export + ast.GetExports(symbol, &arena)[ast.MakeSymbolName("new")] = member for range 1024 { - ast.NewSymbol().SetExports(ast.SymbolTable{"export": export}, &arena) + ast.NewSymbol().SetExports(ast.SymbolTable{ast.MakeSymbolName("export"): export}, &arena) } arena = ast.SymbolExtraArena{} otherArena = ast.SymbolExtraArena{} runtime.GC() - assert.Equal(t, symbol.Members()["new"], export) - assert.Equal(t, alias.Exports()["new"], member) + assert.Equal(t, symbol.Members()[ast.MakeSymbolName("new")], export) + assert.Equal(t, alias.Exports()[ast.MakeSymbolName("new")], member) } diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go new file mode 100644 index 0000000000000..0bf951d5a8285 --- /dev/null +++ b/tsc/internal/ast/symbolname_intern.go @@ -0,0 +1,191 @@ +package ast + +import ( + "sync" + "sync/atomic" +) + +// Symbol names are interned into a process-wide table and identified by a +// 32-bit ID; ID 0 is reserved for the unset name. Interned names are never +// freed. IDs contain no pointers, so nodes, symbol tables, and caches that +// hold them cost the garbage collector nothing to scan or write-barrier. +// +// Texts are stored in fixed-size chunks so an ID's text never moves. Lookups +// are lock-free: each shard publishes an open-addressing table whose slots +// pack a 32-bit hash with an ID. Inserts take the shard lock and may publish +// a larger table; a reader racing with growth may miss and then retry under +// the lock. +const ( + symbolNameShardBits = 6 + symbolNameShardCount = 1 << symbolNameShardBits + symbolNameInitialSlots = 256 + symbolNameChunkBits = 12 + symbolNameChunkSize = 1 << symbolNameChunkBits + symbolNameMaxChunks = 1 << 14 +) + +type symbolNameChunk [symbolNameChunkSize]string + +type symbolNameShard struct { + table atomic.Pointer[[]atomic.Uint64] + mu sync.Mutex + count int + _ [64]byte +} + +type symbolNameTable struct { + shards [symbolNameShardCount]symbolNameShard + nextID atomic.Uint32 + chunks [symbolNameMaxChunks]atomic.Pointer[symbolNameChunk] +} + +var symbolNames = newSymbolNameTable() + +func newSymbolNameTable() *symbolNameTable { + t := &symbolNameTable{} + for i := range t.shards { + slots := make([]atomic.Uint64, symbolNameInitialSlots) + t.shards[i].table.Store(&slots) + } + return t +} + +func (t *symbolNameTable) text(id uint32) string { + return t.chunks[id>>symbolNameChunkBits].Load()[id&(symbolNameChunkSize-1)] +} + +func (t *symbolNameTable) lookup(slots []atomic.Uint64, hash uint64, text string) uint32 { + mask := uint64(len(slots) - 1) + tag := hash >> 32 + for i := (hash >> symbolNameShardBits) & mask; ; i = (i + 1) & mask { + v := slots[i].Load() + if v == 0 { + return 0 + } + if v>>32 == tag { + if id := uint32(v); t.text(id) == text { + return id + } + } + } +} + +func (t *symbolNameTable) intern(text string) uint32 { + return t.internHashed(text, hashSymbolNameText(text)) +} + +func (t *symbolNameTable) internHashed(text string, hash uint64) uint32 { + shard := &t.shards[hash&(symbolNameShardCount-1)] + if id := t.lookup(*shard.table.Load(), hash, text); id != 0 { + return id + } + return t.insert(shard, hash, text) +} + +func (t *symbolNameTable) insert(shard *symbolNameShard, hash uint64, text string) uint32 { + shard.mu.Lock() + defer shard.mu.Unlock() + slots := *shard.table.Load() + if id := t.lookup(slots, hash, text); id != 0 { + return id + } + if (shard.count+1)*4 > len(slots)*3 { + grown := make([]atomic.Uint64, len(slots)*2) + for i := range slots { + if v := slots[i].Load(); v != 0 { + storeSymbolNameSlot(grown, t.hashOf(uint32(v)), v) + } + } + shard.table.Store(&grown) + slots = grown + } + id := t.allocate(string([]byte(text))) + storeSymbolNameSlot(slots, hash, hash>>32<<32|uint64(id)) + shard.count++ + return id +} + +func (t *symbolNameTable) hashOf(id uint32) uint64 { + return hashSymbolNameText(t.text(id)) +} + +func (t *symbolNameTable) allocate(text string) uint32 { + id := t.nextID.Add(1) + if id >= symbolNameMaxChunks*symbolNameChunkSize-1 { + panic("too many symbol names") + } + chunkSlot := &t.chunks[id>>symbolNameChunkBits] + chunk := chunkSlot.Load() + if chunk == nil { + chunk = new(symbolNameChunk) + if !chunkSlot.CompareAndSwap(nil, chunk) { + chunk = chunkSlot.Load() + } + } + chunk[id&(symbolNameChunkSize-1)] = text + return id +} + +func storeSymbolNameSlot(slots []atomic.Uint64, hash uint64, v uint64) { + mask := uint64(len(slots) - 1) + for i := (hash >> symbolNameShardBits) & mask; ; i = (i + 1) & mask { + if slots[i].Load() == 0 { + slots[i].Store(v) + return + } + } +} + +// SymbolNameCache is a small direct-mapped cache in front of the global intern +// table, for callers like the parser that intern many repeated names. It holds +// no pointers, so updating it needs no write barriers. +type SymbolNameCache struct { + slots [symbolNameCacheSize]symbolNameCacheSlot +} + +type symbolNameCacheSlot struct { + hash uint32 + id uint32 +} + +const symbolNameCacheSize = 4096 + +func (c *SymbolNameCache) Make(text string) SymbolName { + return c.MakeHashed(text, hashSymbolNameText(text)) +} + +// MakeHashed is Make for callers that already computed the name's hash with +// SymbolNameHashSeed, SymbolNameHashAdd, and SymbolNameHashFinish. +func (c *SymbolNameCache) MakeHashed(text string, hash uint64) SymbolName { + slot := &c.slots[hash&(symbolNameCacheSize-1)] + if slot.id != 0 && slot.hash == uint32(hash>>32) && symbolNames.text(slot.id) == text { + return SymbolName{slot.id} + } + id := symbolNames.internHashed(text, hash) + *slot = symbolNameCacheSlot{hash: uint32(hash >> 32), id: id} + return SymbolName{id} +} + +// Symbol name hashes are FNV-1a with a final mix. Names are short, so this +// inlines well and beats a general-purpose hash call. The incremental form lets +// the scanner hash identifiers while it scans them. +const SymbolNameHashSeed uint64 = 14695981039346656037 + +func SymbolNameHashAdd(h uint64, b byte) uint64 { + return (h ^ uint64(b)) * 1099511628211 +} + +func SymbolNameHashFinish(h uint64) uint64 { + h ^= h >> 32 + h *= 0x9E3779B97F4A7C15 + h ^= h >> 29 + return h +} + +func hashSymbolNameText(text string) uint64 { + h := SymbolNameHashSeed + for i := range len(text) { + h = SymbolNameHashAdd(h, text[i]) + } + return SymbolNameHashFinish(h) +} diff --git a/tsc/internal/ast/utilities.go b/tsc/internal/ast/utilities.go index ff11fd6a2c2f4..3f7dc64ba1ee9 100644 --- a/tsc/internal/ast/utilities.go +++ b/tsc/internal/ast/utilities.go @@ -1708,14 +1708,15 @@ func IsAmbientModule(node *Node) bool { return IsModuleDeclaration(node) && (node.AsModuleDeclaration().Name().Kind == KindStringLiteral || IsGlobalScopeAugmentation(node)) } -func IsAmbientModuleSymbolName(s string) bool { +func IsAmbientModuleSymbolName(s SymbolName) bool { _, ok := TryGetAmbientModuleNameFromSymbolName(s) return ok } // Ambient module symbols are either of the form `"modulename"` or `InternalSymbolNamePrefix + "\"modulename\"pattern@nodeId"`; // see `getDeclarationName`. -func TryGetAmbientModuleNameFromSymbolName(s string) (string, bool) { +func TryGetAmbientModuleNameFromSymbolName(name SymbolName) (string, bool) { + s := name.Value() if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") { return s[1 : len(s)-1], true } @@ -2666,7 +2667,7 @@ func GetNamespaceDeclarationNode(node *Node) *Node { } func ModuleExportNameIsDefault(node *Node) bool { - return node.Text() == InternalSymbolNameDefault + return node.TextSymbolName() == InternalSymbolNameDefault } func IsDefaultImport(node *Node /*ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration*/) bool { @@ -3282,22 +3283,22 @@ func isShorthandPropertyNameUseSite(useSite *Node) bool { return IsIdentifier(useSite) && IsShorthandPropertyAssignment(useSite.Parent) && useSite.Parent.AsShorthandPropertyAssignment().Name() == useSite } -func GetPropertyNameForPropertyNameNode(name *Node) string { +func GetPropertyNameForPropertyNameNode(name *Node) SymbolName { switch name.Kind { case KindIdentifier, KindPrivateIdentifier, KindStringLiteral, KindNoSubstitutionTemplateLiteral, KindNumericLiteral, KindBigIntLiteral, KindJsxNamespacedName: - return name.Text() + return name.TextSymbolName() case KindComputedPropertyName: nameExpression := name.Expression() if IsStringOrNumericLiteralLike(nameExpression) { - return nameExpression.Text() + return nameExpression.TextSymbolName() } if IsSignedNumericLiteral(nameExpression) { text := nameExpression.AsPrefixUnaryExpression().Operand.Text() if nameExpression.AsPrefixUnaryExpression().Operator == KindMinusToken { text = "-" + text } - return text + return MakeSymbolName(text) } return InternalSymbolNameMissing } diff --git a/tsc/internal/binder/binder.go b/tsc/internal/binder/binder.go index a95bb19ecdff7..1b4109c1fac22 100644 --- a/tsc/internal/binder/binder.go +++ b/tsc/internal/binder/binder.go @@ -129,7 +129,7 @@ func bindSourceFile(file *ast.SourceFile) { }) } -func (b *Binder) newSymbol(flags ast.SymbolFlags, name string) *ast.Symbol { +func (b *Binder) newSymbol(flags ast.SymbolFlags, name ast.SymbolName) *ast.Symbol { b.symbolCount++ result := b.symbolWithDataArena.New().Initialize() result.SetFlags(flags) @@ -153,7 +153,7 @@ func (b *Binder) declareSymbolEx(symbolTable ast.SymbolTable, parent *ast.Symbol debug.Assert(isComputedName || !ast.HasDynamicName(node)) isDefaultExport := ast.HasSyntacticModifier(node, ast.ModifierFlagsDefault) || ast.IsExportSpecifier(node) && ast.ModuleExportNameIsDefault(node.AsExportSpecifier().Name()) // The exported symbol for an export default function/class node is always named "default" - var name string + var name ast.SymbolName switch { case isComputedName: name = ast.InternalSymbolNameComputed @@ -298,7 +298,7 @@ func (b *Binder) declareSymbolEx(symbolTable ast.SymbolTable, parent *ast.Symbol // Should not be called on a declaration with a computed property name, // unless it is a well known Symbol. -func (b *Binder) getDeclarationName(node *ast.Node) string { +func (b *Binder) getDeclarationName(node *ast.Node) ast.SymbolName { if ast.IsExportAssignment(node) { return core.IfElse(node.AsExportAssignment().IsExportEquals, ast.InternalSymbolNameExportEquals, ast.InternalSymbolNameDefault) } @@ -311,10 +311,10 @@ func (b *Binder) getDeclarationName(node *ast.Node) string { } if pattern := core.TryParsePattern(moduleName); pattern.IsValid() && pattern.StarIndex >= 0 { if attributes := node.AsModuleDeclaration().Attributes; attributes != nil { - return ast.InternalSymbolNamePrefix + "\"" + moduleName + "\"pattern@" + strconv.FormatUint(uint64(ast.GetNodeId(attributes)), 10) + return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "\"" + moduleName + "\"pattern@" + strconv.FormatUint(uint64(ast.GetNodeId(attributes)), 10)) } } - return "\"" + moduleName + "\"" + return ast.MakeSymbolName("\"" + moduleName + "\"") } if ast.IsPrivateIdentifier(name) { // containingClass exists because private names only allowed inside classes @@ -326,17 +326,17 @@ func (b *Binder) getDeclarationName(node *ast.Node) string { return GetSymbolNameForPrivateIdentifier(containingClass.Symbol(), name.Text()) } if ast.IsPropertyNameLiteral(name) || ast.IsJsxNamespacedName(name) { - return name.Text() + return name.TextSymbolName() } if ast.IsComputedPropertyName(name) { nameExpression := name.Expression() // treat computed property names where expression is string/numeric literal as just string/numeric literal if ast.IsStringOrNumericLiteralLike(nameExpression) { - return nameExpression.Text() + return nameExpression.TextSymbolName() } if ast.IsSignedNumericLiteral(nameExpression) { unaryExpression := nameExpression.AsPrefixUnaryExpression() - return scanner.TokenToString(unaryExpression.Operator) + unaryExpression.Operand.Text() + return ast.MakeSymbolName(scanner.TokenToString(unaryExpression.Operator) + unaryExpression.Operand.Text()) } panic("Only computed properties with literal names have declaration names") } @@ -366,13 +366,13 @@ func (b *Binder) getDisplayName(node *ast.Node) string { } name := b.getDeclarationName(node) if name != ast.InternalSymbolNameMissing { - return name + return name.Value() } return "(Missing)" } -func GetSymbolNameForPrivateIdentifier(containingClassSymbol *ast.Symbol, description string) string { - return ast.InternalSymbolNamePrefix + "#" + strconv.Itoa(int(ast.GetSymbolId(containingClassSymbol))) + "@" + description +func GetSymbolNameForPrivateIdentifier(containingClassSymbol *ast.Symbol, description string) ast.SymbolName { + return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "#" + strconv.Itoa(int(ast.GetSymbolId(containingClassSymbol))) + "@" + description) } func (b *Binder) declareModuleMember(node *ast.Node, symbolFlags ast.SymbolFlags, symbolExcludes ast.SymbolFlags) *ast.Symbol { @@ -770,7 +770,7 @@ func (b *Binder) bindSourceFileIfExternalModule() { } func (b *Binder) bindSourceFileAsExternalModule() { - b.bindAnonymousDeclaration(b.file.AsNode(), ast.SymbolFlagsValueModule, "\""+b.file.FileName().RemoveFileExtension().AsString()+"\"") + b.bindAnonymousDeclaration(b.file.AsNode(), ast.SymbolFlagsValueModule, ast.MakeSymbolName("\""+b.file.FileName().RemoveFileExtension().AsString()+"\"")) } func (b *Binder) bindModuleDeclaration(node *ast.Node) { @@ -919,7 +919,7 @@ func (b *Binder) bindFunctionExpression(node *ast.Node) { bindingName := ast.InternalSymbolNameFunction if ast.IsFunctionExpression(node) && node.AsFunctionExpression().Name() != nil { b.checkStrictModeFunctionName(node) - bindingName = node.AsFunctionExpression().Name().Text() + bindingName = node.AsFunctionExpression().Name().TextSymbolName() } b.bindAnonymousDeclaration(node, ast.SymbolFlagsFunction, bindingName) } @@ -953,7 +953,7 @@ func (b *Binder) bindClassLikeDeclaration(node *ast.Node) { case ast.KindClassExpression: nameText := ast.InternalSymbolNameClass if name != nil { - nameText = name.Text() + nameText = name.TextSymbolName() } b.bindAnonymousDeclaration(node, ast.SymbolFlagsClass, nameText) } @@ -967,10 +967,10 @@ func (b *Binder) bindClassLikeDeclaration(node *ast.Node) { // Note: we check for this here because this class may be merging into a module. The // module might have an exported variable called 'prototype'. We can't allow that as // that would clash with the built-in 'prototype' for the class. - prototypeSymbol := b.newSymbol(ast.SymbolFlagsProperty|ast.SymbolFlagsPrototype, "prototype") + prototypeSymbol := b.newSymbol(ast.SymbolFlagsProperty|ast.SymbolFlagsPrototype, ast.SymbolNamePrototype) symbolExport := ast.GetExports(symbol, &b.symbolExtraArena)[prototypeSymbol.Name()] if symbolExport != nil { - b.errorOnNode(symbolExport.Declarations()[0], diagnostics.Duplicate_identifier_0, ast.SymbolName(prototypeSymbol)) + b.errorOnNode(symbolExport.Declarations()[0], diagnostics.Duplicate_identifier_0, ast.SymbolNameText(prototypeSymbol)) } ast.GetExports(symbol, &b.symbolExtraArena)[prototypeSymbol.Name()] = prototypeSymbol prototypeSymbol.SetParent(symbol) @@ -1203,7 +1203,7 @@ func (b *Binder) bindParameter(node *ast.Node) { } if ast.IsBindingPattern(decl.Name()) { index := slices.Index(node.Parent.Parameters(), node) - b.bindAnonymousDeclaration(node, ast.SymbolFlagsFunctionScopedVariable, "__"+strconv.Itoa(index)) + b.bindAnonymousDeclaration(node, ast.SymbolFlagsFunctionScopedVariable, ast.MakeSymbolName("__"+strconv.Itoa(index))) } else { b.declareSymbolAndAddToSymbolTable(node, ast.SymbolFlagsFunctionScopedVariable, ast.SymbolFlagsParameterExcludes) } @@ -1235,7 +1235,7 @@ func (b *Binder) getInferTypeContainer(node *ast.Node) *ast.Node { return nil } -func (b *Binder) bindAnonymousDeclaration(node *ast.Node, symbolFlags ast.SymbolFlags, name string) { +func (b *Binder) bindAnonymousDeclaration(node *ast.Node, symbolFlags ast.SymbolFlags, name ast.SymbolName) { symbol := b.newSymbol(symbolFlags, name) if symbolFlags&(ast.SymbolFlagsEnumMember|ast.SymbolFlagsClassMember) != 0 { symbol.SetParent(b.container.Symbol()) @@ -1273,25 +1273,25 @@ func (b *Binder) bindTypeParameter(node *ast.Node) { func (b *Binder) lookupEntity(node *ast.Node, container *ast.Node) *ast.Symbol { if ast.IsIdentifier(node) { - return b.lookupName(node.Text(), container) + return b.lookupName(node.TextSymbolName(), container) } if node.Expression().Kind == ast.KindThisKeyword { if _, symbolTable := b.getThisClassAndSymbolTable(); symbolTable != nil { if name := ast.GetElementOrPropertyAccessName(node); name != nil { - return symbolTable[name.Text()] + return symbolTable[name.TextSymbolName()] } } return nil } if symbol := getInitializerSymbol(b.lookupEntity(node.Expression(), container)); symbol != nil && symbol.Exports() != nil { if name := ast.GetElementOrPropertyAccessName(node); name != nil { - return symbol.Exports()[name.Text()] + return symbol.Exports()[name.TextSymbolName()] } } return nil } -func (b *Binder) lookupName(name string, container *ast.Node) *ast.Symbol { +func (b *Binder) lookupName(name ast.SymbolName, container *ast.Node) *ast.Symbol { if localsContainer := container.LocalsContainerData(); localsContainer != nil { if local := localsContainer.Locals[name]; local != nil { return core.OrElse(local.ExportSymbol(), local) @@ -1613,8 +1613,8 @@ func (b *Binder) bindContainer(node *ast.Node, containerFlags ContainerFlags) { } } if b.file.CommonJSModuleIndicator != nil { - b.declareCommonJSVariable("module") - b.declareCommonJSVariable("exports") + b.declareCommonJSVariable(ast.SymbolNameModule) + b.declareCommonJSVariable(ast.SymbolNameExports) } } if ast.IsSourceFile(node) && ast.IsExternalOrCommonJSModule(node.AsSourceFile()) || ast.IsAmbientModule(node) { @@ -1625,19 +1625,19 @@ func (b *Binder) bindContainer(node *ast.Node, containerFlags ContainerFlags) { b.blockScopeContainer = savedBlockScopeContainer } -func (b *Binder) declareCommonJSVariable(name string) { +func (b *Binder) declareCommonJSVariable(name ast.SymbolName) { locals := ast.GetLocals(b.file.AsNode()) if locals[name] == nil { symbol := b.newSymbol(ast.SymbolFlagsFunctionScopedVariable|ast.SymbolFlagsModuleExports, name) symbol.SetDeclarations(b.newSingleDeclaration(b.file.AsNode())) symbol.SetValueDeclaration(symbol.Declarations()[0]) - if name == "module" { - exportsProperty := b.newSymbol(ast.SymbolFlagsModuleExports|ast.SymbolFlagsProperty, "exports") + if name == ast.SymbolNameModule { + exportsProperty := b.newSymbol(ast.SymbolFlagsModuleExports|ast.SymbolFlagsProperty, ast.SymbolNameExports) exportsProperty.SetDeclarations(symbol.Declarations()) exportsProperty.SetValueDeclaration(symbol.ValueDeclaration()) exportsProperty.SetParent(symbol) symbol.SetMembers(make(ast.SymbolTable, 1), &b.symbolExtraArena) - symbol.Members()["exports"] = exportsProperty + symbol.Members()[ast.SymbolNameExports] = exportsProperty } locals[name] = symbol } diff --git a/tsc/internal/binder/binder_test.go b/tsc/internal/binder/binder_test.go index dc3c4bc1bc26c..a5d756f80207b 100644 --- a/tsc/internal/binder/binder_test.go +++ b/tsc/internal/binder/binder_test.go @@ -10,8 +10,59 @@ import ( "github.com/microsoft/TypeScript/tsc/internal/testutil/fixtures" "github.com/microsoft/TypeScript/tsc/internal/tspath" "github.com/microsoft/TypeScript/tsc/internal/vfs/osvfs" + "gotest.tools/v3/assert" ) +func TestBindInternedSymbolNames(t *testing.T) { + t.Parallel() + const text = ` +export var named = 0; +export var \u006eamed = 1; +export interface Shape { + (): void; + "__call": number; + ["literal"]: number; + 0: number; +} +export { named as renamed }; +export default class First { #value = 1; } +export class Second { #value = 2; } +` + file := parser.ParseSourceFile(ast.SourceFileParseOptions{ + FileName: "/names.ts", + PathKey: tspath.CaseSensitive.PathKey("/names.ts"), + }, text, core.ScriptKindTS) + BindSourceFile(file) + + name := ast.MakeSymbolName("named") + local := file.Locals[name] + exported := file.Symbol.Exports()[name] + assert.Assert(t, local != nil && exported != nil) + assert.Assert(t, local.Name() == name && exported.Name() == name) + assert.Equal(t, len(local.Declarations()), 2) + assert.Equal(t, len(exported.Declarations()), 2) + assert.Equal(t, local.ExportSymbol(), exported) + + members := file.Symbol.Exports()[ast.MakeSymbolName("Shape")].Members() + for _, name := range []ast.SymbolName{ast.InternalSymbolNameCall, ast.MakeSymbolName("__call"), ast.MakeSymbolName("literal"), ast.MakeSymbolName("0")} { + assert.Assert(t, members[name] != nil) + assert.Assert(t, members[name].Name() == name) + } + assert.Assert(t, members[ast.InternalSymbolNameCall] != members[ast.MakeSymbolName("__call")]) + assert.Assert(t, file.Symbol.Exports()[ast.MakeSymbolName("renamed")].Name() == ast.MakeSymbolName("renamed")) + + first := file.Symbol.Exports()[ast.InternalSymbolNameDefault] + second := file.Symbol.Exports()[ast.MakeSymbolName("Second")] + firstPrivate := GetSymbolNameForPrivateIdentifier(first, "#value") + secondPrivate := GetSymbolNameForPrivateIdentifier(second, "#value") + assert.Assert(t, firstPrivate != secondPrivate) + assert.Assert(t, first.Members()[firstPrivate] != nil) + assert.Assert(t, second.Members()[secondPrivate] != nil) + + resolver := NameResolver{CompilerOptions: core.EmptyCompilerOptions} + assert.Equal(t, resolver.Resolve(file.AsNode(), name, ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil, false, false), local) +} + func BenchmarkBind(b *testing.B) { for _, f := range fixtures.BenchFixtures { b.Run(f.Name(), func(b *testing.B) { diff --git a/tsc/internal/binder/nameresolver.go b/tsc/internal/binder/nameresolver.go index a7eff7005e812..c747ce2aa9987 100644 --- a/tsc/internal/binder/nameresolver.go +++ b/tsc/internal/binder/nameresolver.go @@ -13,16 +13,16 @@ type NameResolver struct { Globals ast.SymbolTable ArgumentsSymbol *ast.Symbol RequireSymbol *ast.Symbol - Lookup func(symbols ast.SymbolTable, name string, meaning ast.SymbolFlags) *ast.Symbol + Lookup func(symbols ast.SymbolTable, name ast.SymbolName, meaning ast.SymbolFlags) *ast.Symbol SymbolReferenced func(symbol *ast.Symbol, meaning ast.SymbolFlags) SetRequiresScopeChangeCache func(node *ast.Node, value core.Tristate) GetRequiresScopeChangeCache func(node *ast.Node) core.Tristate - OnPropertyWithInvalidInitializer func(location *ast.Node, name string, declaration *ast.Node, result *ast.Symbol) bool - OnFailedToResolveSymbol func(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message) + OnPropertyWithInvalidInitializer func(location *ast.Node, name ast.SymbolName, declaration *ast.Node, result *ast.Symbol) bool + OnFailedToResolveSymbol func(location *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message) OnSuccessfullyResolvedSymbol func(location *ast.Node, result *ast.Symbol, meaning ast.SymbolFlags, lastLocation *ast.Node, associatedDeclarationForContainingInitializerOrBindingName *ast.Node, withinDeferredContext bool) } -func (r *NameResolver) Resolve(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol { +func (r *NameResolver) Resolve(location *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol { var result *ast.Symbol var lastLocation *ast.Node var lastSelfReferenceLocation *ast.Node @@ -31,7 +31,7 @@ func (r *NameResolver) Resolve(location *ast.Node, name string, meaning ast.Symb var withinDeferredContext bool var grandparent *ast.Node originalLocation := location // needed for did-you-mean error reporting, which gathers candidates starting from the original location - nameIsConst := name == "const" + nameIsConst := name == ast.SymbolNameConst loop: for location != nil { if nameIsConst && ast.IsConstAssertion(location) { @@ -161,7 +161,7 @@ loop: if nameNotFoundMessage != nil && r.CompilerOptions.GetIsolatedModules() && location.Flags&ast.NodeFlagsAmbient == 0 && ast.GetSourceFileOfNode(location) != ast.GetSourceFileOfNode(result.ValueDeclaration()) { isolatedModulesLikeFlagName := core.IfElse(r.CompilerOptions.VerbatimModuleSyntax == core.TSTrue, "verbatimModuleSyntax", "isolatedModules") r.error(originalLocation, diagnostics.Cannot_access_0_from_another_file_without_qualification_when_1_is_enabled_Use_2_instead, - name, isolatedModulesLikeFlagName, enumSymbol.Name()+"."+name) + name.Value(), isolatedModulesLikeFlagName, enumSymbol.Name().Value()+"."+name.Value()) } break loop } @@ -196,7 +196,7 @@ loop: } if ast.IsClassExpression(location) && meaning&ast.SymbolFlagsClass != 0 { className := location.Name() - if className != nil && name == className.Text() { + if className != nil && name == className.TextSymbolName() { result = location.Symbol() break loop } @@ -234,18 +234,18 @@ loop: } } case ast.KindMethodDeclaration, ast.KindConstructor, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindFunctionDeclaration: - if meaning&ast.SymbolFlagsVariable != 0 && name == "arguments" { + if meaning&ast.SymbolFlagsVariable != 0 && name == ast.SymbolNameArguments { result = r.argumentsSymbol() break loop } case ast.KindFunctionExpression: - if meaning&ast.SymbolFlagsVariable != 0 && name == "arguments" { + if meaning&ast.SymbolFlagsVariable != 0 && name == ast.SymbolNameArguments { result = r.argumentsSymbol() break loop } if meaning&ast.SymbolFlagsFunction != 0 { functionName := location.AsFunctionExpression().Name() - if functionName != nil && name == functionName.Text() { + if functionName != nil && name == functionName.TextSymbolName() { result = location.Symbol() break loop } @@ -295,7 +295,7 @@ loop: case ast.KindInferType: if meaning&ast.SymbolFlagsTypeParameter != 0 { parameterName := location.AsInferTypeNode().TypeParameter.AsTypeParameterDeclaration().Name() - if parameterName != nil && name == parameterName.Text() { + if parameterName != nil && name == parameterName.TextSymbolName() { result = location.AsInferTypeNode().TypeParameter.Symbol() break loop } @@ -423,7 +423,7 @@ func (r *NameResolver) getSymbolOfDeclaration(node *ast.Node) *ast.Symbol { return node.Symbol() } -func (r *NameResolver) lookup(symbols ast.SymbolTable, name string, meaning ast.SymbolFlags) *ast.Symbol { +func (r *NameResolver) lookup(symbols ast.SymbolTable, name ast.SymbolName, meaning ast.SymbolFlags) *ast.Symbol { if r.Lookup != nil { return r.Lookup(symbols, name, meaning) } @@ -443,7 +443,7 @@ func (r *NameResolver) argumentsSymbol() *ast.Symbol { if r.ArgumentsSymbol == nil { // Default implementation synthesizes a transient symbol for `arguments` r.ArgumentsSymbol = ast.NewSymbol() - r.ArgumentsSymbol.SetName("arguments") + r.ArgumentsSymbol.SetName(ast.SymbolNameArguments) r.ArgumentsSymbol.SetFlags(ast.SymbolFlagsProperty | ast.SymbolFlagsTransient) } return r.ArgumentsSymbol diff --git a/tsc/internal/binder/referenceresolver.go b/tsc/internal/binder/referenceresolver.go index c7e606328f505..646c10fefa455 100644 --- a/tsc/internal/binder/referenceresolver.go +++ b/tsc/internal/binder/referenceresolver.go @@ -11,19 +11,19 @@ type ReferenceResolver interface { GetReferencedImportDeclaration(node *ast.IdentifierNode) *ast.Declaration GetReferencedValueDeclaration(node *ast.IdentifierNode) *ast.Declaration GetReferencedValueDeclarations(node *ast.IdentifierNode) []*ast.Declaration - GetElementAccessExpressionName(expression *ast.ElementAccessExpression) string + GetElementAccessExpressionName(expression *ast.ElementAccessExpression) ast.SymbolName GetReferencedMemberValueDeclaration(node *ast.Node) *ast.Declaration } type ReferenceResolverHooks struct { - ResolveName func(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol + ResolveName func(location *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol GetResolvedSymbol func(*ast.Node) *ast.Symbol GetMergedSymbol func(*ast.Symbol) *ast.Symbol GetParentOfSymbol func(*ast.Symbol) *ast.Symbol GetSymbolOfDeclaration func(*ast.Declaration) *ast.Symbol GetTypeOnlyAliasDeclaration func(symbol *ast.Symbol, include ast.SymbolFlags) *ast.Declaration GetExportSymbolOfValueSymbolIfExported func(*ast.Symbol) *ast.Symbol - GetElementAccessExpressionName func(*ast.ElementAccessExpression) (string, bool) + GetElementAccessExpressionName func(*ast.ElementAccessExpression) (ast.SymbolName, bool) } var _ ReferenceResolver = &referenceResolver{} @@ -92,7 +92,7 @@ func (r *referenceResolver) getReferencedValueSymbol(reference *ast.IdentifierNo } if r.hooks.ResolveName != nil { - return r.hooks.ResolveName(location, reference.Text(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) + return r.hooks.ResolveName(location, reference.TextSymbolName(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } if r.resolver == nil { @@ -101,7 +101,7 @@ func (r *referenceResolver) getReferencedValueSymbol(reference *ast.IdentifierNo } } - return r.resolver.Resolve(location, reference.Text(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) + return r.resolver.Resolve(location, reference.TextSymbolName(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } func (r *referenceResolver) isTypeOnlyAliasDeclaration(symbol *ast.Symbol) bool { @@ -237,7 +237,7 @@ func (r *referenceResolver) GetReferencedValueDeclarations(node *ast.IdentifierN return declarations } -func (r *referenceResolver) GetElementAccessExpressionName(expression *ast.ElementAccessExpression) string { +func (r *referenceResolver) GetElementAccessExpressionName(expression *ast.ElementAccessExpression) ast.SymbolName { if expression != nil { if r.hooks.GetElementAccessExpressionName != nil { if name, ok := r.hooks.GetElementAccessExpressionName(expression); ok { @@ -245,7 +245,7 @@ func (r *referenceResolver) GetElementAccessExpressionName(expression *ast.Eleme } } } - return "" + return ast.EmptySymbolName } func (r *referenceResolver) GetReferencedMemberValueDeclaration(node *ast.Node) *ast.Declaration { diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index d392785d4181f..bd0c38f7c1ad6 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -361,12 +361,12 @@ const ( IntrinsicTypeKindNoInfer ) -var intrinsicTypeKinds = map[string]IntrinsicTypeKind{ - "Uppercase": IntrinsicTypeKindUppercase, - "Lowercase": IntrinsicTypeKindLowercase, - "Capitalize": IntrinsicTypeKindCapitalize, - "Uncapitalize": IntrinsicTypeKindUncapitalize, - "NoInfer": IntrinsicTypeKindNoInfer, +var intrinsicTypeKinds = map[ast.SymbolName]IntrinsicTypeKind{ + ast.SymbolNameUppercase: IntrinsicTypeKindUppercase, + ast.SymbolNameLowercase: IntrinsicTypeKindLowercase, + ast.SymbolNameCapitalize: IntrinsicTypeKindCapitalize, + ast.SymbolNameUncapitalize: IntrinsicTypeKindUncapitalize, + ast.SymbolNameNoInfer: IntrinsicTypeKindNoInfer, } type MappedTypeModifiers uint32 @@ -523,7 +523,7 @@ const ( ) type IterationTypesResolver struct { - iteratorSymbolName string + iteratorSymbolName ast.SymbolName getGlobalIteratorType func() *Type getGlobalIterableType func() *Type getGlobalIterableTypeChecked func() *Type @@ -540,10 +540,10 @@ type IterationTypesResolver struct { type WideningContext struct { parent *WideningContext // Parent context - propertyName string // Name of property in parent + propertyName ast.SymbolName // Name of property in parent siblings []*Type // Types of siblings resolvedProperties []*ast.Symbol // Properties occurring in sibling object literals - childContexts map[string]*WideningContext + childContexts map[ast.SymbolName]*WideningContext widenedTypes map[*Type]*Type } @@ -639,7 +639,7 @@ type Checker struct { subtypeReductionCache map[CacheHashKey][]*Type cachedTypes map[CachedTypeKey]*Type cachedSignatures map[CachedSignatureKey]*Signature - undefinedProperties map[string]*ast.Symbol + undefinedProperties ast.SymbolTable narrowedTypes map[NarrowedTypeKey]*Type assignmentReducedTypes map[AssignmentReducedKey]*Type discriminatedContextualTypes map[DiscriminatedContextualTypeKey]*Type @@ -655,14 +655,14 @@ type Checker struct { argumentsSymbol *ast.Symbol requireSymbol *ast.Symbol unknownSymbol *ast.Symbol - unresolvedSymbols map[string]*ast.Symbol + unresolvedSymbols ast.SymbolTable errorTypes map[CacheHashKey]*Type moduleSymbols map[*ast.Node]*ast.Symbol globalThisSymbol *ast.Symbol symbolTableAliasCache map[symbolTableID][]*ast.Symbol classExpressionNameTables map[ast.NodeId]ast.SymbolTable - resolveName func(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol - resolveNameForSymbolSuggestion func(location *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol + resolveName func(location *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol + resolveNameForSymbolSuggestion func(location *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message, isUse bool, excludeGlobals bool) *ast.Symbol tupleTypes map[CacheHashKey]*Type unionTypes map[CacheHashKey]*Type unionOfUnionTypes map[UnionOfUnionKey]*Type @@ -977,7 +977,7 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) { c.subtypeReductionCache = make(map[CacheHashKey][]*Type) c.cachedTypes = make(map[CachedTypeKey]*Type) c.cachedSignatures = make(map[CachedSignatureKey]*Signature) - c.undefinedProperties = make(map[string]*ast.Symbol) + c.undefinedProperties = make(ast.SymbolTable) c.narrowedTypes = make(map[NarrowedTypeKey]*Type) c.assignmentReducedTypes = make(map[AssignmentReducedKey]*Type) c.discriminatedContextualTypes = make(map[DiscriminatedContextualTypeKey]*Type) @@ -986,14 +986,14 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) { c.reverseMappedCache = make(map[ReverseMappedTypeKey]*Type) c.reverseHomomorphicMappedCache = make(map[ReverseMappedTypeKey]*Type) c.iterationTypesCache = make(map[IterationTypesKey]IterationTypes) - c.undefinedSymbol = c.newSymbol(ast.SymbolFlagsProperty, "undefined") - c.argumentsSymbol = c.newSymbol(ast.SymbolFlagsProperty, "arguments") - c.requireSymbol = c.newSymbol(ast.SymbolFlagsProperty, "require") - c.unknownSymbol = c.newSymbol(ast.SymbolFlagsProperty, "unknown") - c.unresolvedSymbols = make(map[string]*ast.Symbol) + c.undefinedSymbol = c.newSymbol(ast.SymbolFlagsProperty, ast.SymbolNameUndefined) + c.argumentsSymbol = c.newSymbol(ast.SymbolFlagsProperty, ast.SymbolNameArguments) + c.requireSymbol = c.newSymbol(ast.SymbolFlagsProperty, ast.SymbolNameRequire) + c.unknownSymbol = c.newSymbol(ast.SymbolFlagsProperty, ast.SymbolNameUnknown) + c.unresolvedSymbols = make(ast.SymbolTable) c.errorTypes = make(map[CacheHashKey]*Type) c.moduleSymbols = make(map[*ast.Node]*ast.Symbol) - c.globalThisSymbol = c.newSymbolEx(ast.SymbolFlagsModule, "globalThis", ast.CheckFlagsReadonly) + c.globalThisSymbol = c.newSymbolEx(ast.SymbolFlagsModule, ast.SymbolNameGlobalThis, ast.CheckFlagsReadonly) c.globalThisSymbol.SetExports(c.globals, &c.symbolExtraArena) c.globals[c.globalThisSymbol.Name()] = c.globalThisSymbol c.resolveName = c.createNameResolver().Resolve @@ -1072,7 +1072,7 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) { c.markerSuperTypeForCheck = c.newTypeParameter(nil) c.markerSubTypeForCheck = c.newTypeParameter(nil) c.markerSubTypeForCheck.AsTypeParameter().constraint = c.markerSuperTypeForCheck - c.noTypePredicate = &TypePredicate{kind: TypePredicateKindIdentifier, parameterIndex: 0, parameterName: "<>", t: c.anyType} + c.noTypePredicate = &TypePredicate{kind: TypePredicateKindIdentifier, parameterIndex: 0, parameterName: ast.SymbolNameUnresolved, t: c.anyType} c.anySignature = c.newSignature(SignatureFlagsNone, nil, nil, nil, nil, c.anyType, nil, 0) c.unknownSignature = c.newSignature(SignatureFlagsNone, nil, nil, nil, nil, c.errorType, nil, 0) c.resolvingSignature = c.newSignature(SignatureFlagsNone, nil, nil, nil, nil, c.anyType, nil, 0) @@ -1094,57 +1094,57 @@ func NewChecker(program Program, tracer *Tracer) (*Checker, *sync.Mutex) { c.identityRelation = &Relation{} c.enumRelation = make(map[EnumRelationKey]RelationComparisonResult) c.moduleImportAttributesTypes = make(map[*ast.Symbol]*Type) - c.getGlobalESSymbolType = c.getGlobalTypeResolver("Symbol", 0 /*arity*/, false /*reportErrors*/) - c.getGlobalBigIntType = c.getGlobalTypeResolver("BigInt", 0 /*arity*/, false /*reportErrors*/) - c.getGlobalImportMetaType = c.getGlobalTypeResolver("ImportMeta", 0 /*arity*/, true /*reportErrors*/) - c.getGlobalImportAttributesType = c.getGlobalTypeResolver("ImportAttributes", 0 /*arity*/, false /*reportErrors*/) - c.getGlobalImportAttributesTypeChecked = c.getGlobalTypeResolver("ImportAttributes", 0 /*arity*/, true /*reportErrors*/) - c.getGlobalNonNullableTypeAliasOrNil = c.getGlobalTypeAliasResolver("NonNullable", 1 /*arity*/, false /*reportErrors*/) - c.getGlobalExtractSymbol = c.getGlobalTypeAliasResolver("Extract", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalDisposableType = c.getGlobalTypeResolver("Disposable", 0 /*arity*/, true /*reportErrors*/) - c.getGlobalAsyncDisposableType = c.getGlobalTypeResolver("AsyncDisposable", 0 /*arity*/, true /*reportErrors*/) - c.getGlobalAwaitedSymbol = c.getGlobalTypeAliasResolver("Awaited", 1 /*arity*/, true /*reportErrors*/) - c.getGlobalAwaitedSymbolOrNil = c.getGlobalTypeAliasResolver("Awaited", 1 /*arity*/, false /*reportErrors*/) - c.getGlobalNaNSymbolOrNil = c.getGlobalValueSymbolResolver("NaN", false /*reportErrors*/) - c.getGlobalRecordSymbol = c.getGlobalTypeAliasResolver("Record", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalTemplateStringsArrayType = c.getGlobalTypeResolver("TemplateStringsArray", 0 /*arity*/, true /*reportErrors*/) - c.getGlobalESSymbolConstructorSymbolOrNil = c.getGlobalValueSymbolResolver("Symbol", false /*reportErrors*/) - c.getGlobalESSymbolConstructorTypeSymbolOrNil = c.getGlobalTypeSymbolResolver("SymbolConstructor", false /*reportErrors*/) - c.getGlobalImportCallOptionsType = c.getGlobalTypeResolver("ImportCallOptions", 0 /*arity*/, false /*reportErrors*/) - c.getGlobalImportCallOptionsTypeChecked = c.getGlobalTypeResolver("ImportCallOptions", 0 /*arity*/, true /*reportErrors*/) - c.getGlobalPromiseType = c.getGlobalTypeResolver("Promise", 1 /*arity*/, false /*reportErrors*/) - c.getGlobalPromiseTypeChecked = c.getGlobalTypeResolver("Promise", 1 /*arity*/, true /*reportErrors*/) - c.getGlobalPromiseLikeType = c.getGlobalTypeResolver("PromiseLike", 1 /*arity*/, true /*reportErrors*/) - c.getGlobalAbstractModuleSourceType = c.getGlobalTypeResolver("AbstractModuleSource", 0 /*arity*/, true /*reportErrors*/) - c.getGlobalPromiseConstructorSymbol = c.getGlobalValueSymbolResolver("Promise", true /*reportErrors*/) - c.getGlobalPromiseConstructorSymbolOrNil = c.getGlobalValueSymbolResolver("Promise", false /*reportErrors*/) - c.getGlobalOmitSymbol = c.getGlobalTypeAliasResolver("Omit", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalNoInferSymbolOrNil = c.getGlobalTypeAliasResolver("NoInfer", 1 /*arity*/, false /*reportErrors*/) - c.getGlobalIteratorType = c.getGlobalTypeResolver("Iterator", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIterableType = c.getGlobalTypeResolver("Iterable", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIterableTypeChecked = c.getGlobalTypeResolver("Iterable", 3 /*arity*/, true /*reportErrors*/) - c.getGlobalIterableIteratorType = c.getGlobalTypeResolver("IterableIterator", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIterableIteratorTypeChecked = c.getGlobalTypeResolver("IterableIterator", 3 /*arity*/, true /*reportErrors*/) - c.getGlobalIteratorObjectType = c.getGlobalTypeResolver("IteratorObject", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalGeneratorType = c.getGlobalTypeResolver("Generator", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIteratorType = c.getGlobalTypeResolver("AsyncIterator", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIterableType = c.getGlobalTypeResolver("AsyncIterable", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIterableTypeChecked = c.getGlobalTypeResolver("AsyncIterable", 3 /*arity*/, true /*reportErrors*/) - c.getGlobalAsyncIterableIteratorType = c.getGlobalTypeResolver("AsyncIterableIterator", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIterableIteratorTypeChecked = c.getGlobalTypeResolver("AsyncIterableIterator", 3 /*arity*/, true /*reportErrors*/) - c.getGlobalAsyncIteratorObjectType = c.getGlobalTypeResolver("AsyncIteratorObject", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncGeneratorType = c.getGlobalTypeResolver("AsyncGenerator", 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIteratorYieldResultType = c.getGlobalTypeResolver("IteratorYieldResult", 1 /*arity*/, false /*reportErrors*/) - c.getGlobalIteratorReturnResultType = c.getGlobalTypeResolver("IteratorReturnResult", 1 /*arity*/, false /*reportErrors*/) - c.getGlobalTypedPropertyDescriptorType = c.getGlobalTypeResolver("TypedPropertyDescriptor", 1 /*arity*/, true /*reportErrors*/) - c.getGlobalClassDecoratorContextType = c.getGlobalTypeResolver("ClassDecoratorContext", 1 /*arity*/, true /*reportErrors*/) - c.getGlobalClassMethodDecoratorContextType = c.getGlobalTypeResolver("ClassMethodDecoratorContext", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassGetterDecoratorContextType = c.getGlobalTypeResolver("ClassGetterDecoratorContext", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassSetterDecoratorContextType = c.getGlobalTypeResolver("ClassSetterDecoratorContext", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassAccessorDecoratorContextType = c.getGlobalTypeResolver("ClassAccessorDecoratorContext", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassAccessorDecoratorTargetType = c.getGlobalTypeResolver("ClassAccessorDecoratorTarget", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassAccessorDecoratorResultType = c.getGlobalTypeResolver("ClassAccessorDecoratorResult", 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassFieldDecoratorContextType = c.getGlobalTypeResolver("ClassFieldDecoratorContext", 2 /*arity*/, true /*reportErrors*/) + c.getGlobalESSymbolType = c.getGlobalTypeResolver(ast.SymbolNameSymbol, 0 /*arity*/, false /*reportErrors*/) + c.getGlobalBigIntType = c.getGlobalTypeResolver(ast.SymbolNameBigInt, 0 /*arity*/, false /*reportErrors*/) + c.getGlobalImportMetaType = c.getGlobalTypeResolver(ast.SymbolNameImportMeta, 0 /*arity*/, true /*reportErrors*/) + c.getGlobalImportAttributesType = c.getGlobalTypeResolver(ast.SymbolNameImportAttributes, 0 /*arity*/, false /*reportErrors*/) + c.getGlobalImportAttributesTypeChecked = c.getGlobalTypeResolver(ast.SymbolNameImportAttributes, 0 /*arity*/, true /*reportErrors*/) + c.getGlobalNonNullableTypeAliasOrNil = c.getGlobalTypeAliasResolver(ast.SymbolNameNonNullable, 1 /*arity*/, false /*reportErrors*/) + c.getGlobalExtractSymbol = c.getGlobalTypeAliasResolver(ast.SymbolNameExtract, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalDisposableType = c.getGlobalTypeResolver(ast.SymbolNameDisposable, 0 /*arity*/, true /*reportErrors*/) + c.getGlobalAsyncDisposableType = c.getGlobalTypeResolver(ast.SymbolNameAsyncDisposable, 0 /*arity*/, true /*reportErrors*/) + c.getGlobalAwaitedSymbol = c.getGlobalTypeAliasResolver(ast.SymbolNameAwaited, 1 /*arity*/, true /*reportErrors*/) + c.getGlobalAwaitedSymbolOrNil = c.getGlobalTypeAliasResolver(ast.SymbolNameAwaited, 1 /*arity*/, false /*reportErrors*/) + c.getGlobalNaNSymbolOrNil = c.getGlobalValueSymbolResolver(ast.SymbolNameNaN, false /*reportErrors*/) + c.getGlobalRecordSymbol = c.getGlobalTypeAliasResolver(ast.SymbolNameRecord, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalTemplateStringsArrayType = c.getGlobalTypeResolver(ast.SymbolNameTemplateStringsArray, 0 /*arity*/, true /*reportErrors*/) + c.getGlobalESSymbolConstructorSymbolOrNil = c.getGlobalValueSymbolResolver(ast.SymbolNameSymbol, false /*reportErrors*/) + c.getGlobalESSymbolConstructorTypeSymbolOrNil = c.getGlobalTypeSymbolResolver(ast.SymbolNameSymbolConstructor, false /*reportErrors*/) + c.getGlobalImportCallOptionsType = c.getGlobalTypeResolver(ast.SymbolNameImportCallOptions, 0 /*arity*/, false /*reportErrors*/) + c.getGlobalImportCallOptionsTypeChecked = c.getGlobalTypeResolver(ast.SymbolNameImportCallOptions, 0 /*arity*/, true /*reportErrors*/) + c.getGlobalPromiseType = c.getGlobalTypeResolver(ast.SymbolNamePromise, 1 /*arity*/, false /*reportErrors*/) + c.getGlobalPromiseTypeChecked = c.getGlobalTypeResolver(ast.SymbolNamePromise, 1 /*arity*/, true /*reportErrors*/) + c.getGlobalPromiseLikeType = c.getGlobalTypeResolver(ast.SymbolNamePromiseLike, 1 /*arity*/, true /*reportErrors*/) + c.getGlobalAbstractModuleSourceType = c.getGlobalTypeResolver(ast.SymbolNameAbstractModuleSource, 0 /*arity*/, true /*reportErrors*/) + c.getGlobalPromiseConstructorSymbol = c.getGlobalValueSymbolResolver(ast.SymbolNamePromise, true /*reportErrors*/) + c.getGlobalPromiseConstructorSymbolOrNil = c.getGlobalValueSymbolResolver(ast.SymbolNamePromise, false /*reportErrors*/) + c.getGlobalOmitSymbol = c.getGlobalTypeAliasResolver(ast.SymbolNameOmit, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalNoInferSymbolOrNil = c.getGlobalTypeAliasResolver(ast.SymbolNameNoInfer, 1 /*arity*/, false /*reportErrors*/) + c.getGlobalIteratorType = c.getGlobalTypeResolver(ast.SymbolNameIterator, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIterableType = c.getGlobalTypeResolver(ast.SymbolNameIterable, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIterableTypeChecked = c.getGlobalTypeResolver(ast.SymbolNameIterable, 3 /*arity*/, true /*reportErrors*/) + c.getGlobalIterableIteratorType = c.getGlobalTypeResolver(ast.SymbolNameIterableIterator, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIterableIteratorTypeChecked = c.getGlobalTypeResolver(ast.SymbolNameIterableIterator, 3 /*arity*/, true /*reportErrors*/) + c.getGlobalIteratorObjectType = c.getGlobalTypeResolver(ast.SymbolNameIteratorObject, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalGeneratorType = c.getGlobalTypeResolver(ast.SymbolNameGenerator, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIteratorType = c.getGlobalTypeResolver(ast.SymbolNameAsyncIterator, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIterableType = c.getGlobalTypeResolver(ast.SymbolNameAsyncIterable, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIterableTypeChecked = c.getGlobalTypeResolver(ast.SymbolNameAsyncIterable, 3 /*arity*/, true /*reportErrors*/) + c.getGlobalAsyncIterableIteratorType = c.getGlobalTypeResolver(ast.SymbolNameAsyncIterableIterator, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIterableIteratorTypeChecked = c.getGlobalTypeResolver(ast.SymbolNameAsyncIterableIterator, 3 /*arity*/, true /*reportErrors*/) + c.getGlobalAsyncIteratorObjectType = c.getGlobalTypeResolver(ast.SymbolNameAsyncIteratorObject, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncGeneratorType = c.getGlobalTypeResolver(ast.SymbolNameAsyncGenerator, 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIteratorYieldResultType = c.getGlobalTypeResolver(ast.SymbolNameIteratorYieldResult, 1 /*arity*/, false /*reportErrors*/) + c.getGlobalIteratorReturnResultType = c.getGlobalTypeResolver(ast.SymbolNameIteratorReturnResult, 1 /*arity*/, false /*reportErrors*/) + c.getGlobalTypedPropertyDescriptorType = c.getGlobalTypeResolver(ast.SymbolNameTypedPropertyDescriptor, 1 /*arity*/, true /*reportErrors*/) + c.getGlobalClassDecoratorContextType = c.getGlobalTypeResolver(ast.SymbolNameClassDecoratorContext, 1 /*arity*/, true /*reportErrors*/) + c.getGlobalClassMethodDecoratorContextType = c.getGlobalTypeResolver(ast.SymbolNameClassMethodDecoratorContext, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassGetterDecoratorContextType = c.getGlobalTypeResolver(ast.SymbolNameClassGetterDecoratorContext, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassSetterDecoratorContextType = c.getGlobalTypeResolver(ast.SymbolNameClassSetterDecoratorContext, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassAccessorDecoratorContextType = c.getGlobalTypeResolver(ast.SymbolNameClassAccessorDecoratorContext, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassAccessorDecoratorTargetType = c.getGlobalTypeResolver(ast.SymbolNameClassAccessorDecoratorTarget, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassAccessorDecoratorResultType = c.getGlobalTypeResolver(ast.SymbolNameClassAccessorDecoratorResult, 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassFieldDecoratorContextType = c.getGlobalTypeResolver(ast.SymbolNameClassFieldDecoratorContext, 2 /*arity*/, true /*reportErrors*/) c.initializeClosures() c.initializeIterationResolvers() c.initializeChecker() @@ -1184,27 +1184,27 @@ func (c *Checker) reportUnmeasurableWorker(t *Type) *Type { } // Resolve to the global class or interface by the given name and arity, or emptyObjectType/emptyGenericType otherwise -func (c *Checker) getGlobalTypeResolver(name string, arity int, reportErrors bool) func() *Type { +func (c *Checker) getGlobalTypeResolver(name ast.SymbolName, arity int, reportErrors bool) func() *Type { return core.Memoize(func() *Type { return c.getGlobalType(name, arity, reportErrors) }) } // Resolve to the global type alias symbol by the given name and arity, or nil otherwise -func (c *Checker) getGlobalTypeAliasResolver(name string, arity int, reportErrors bool) func() *ast.Symbol { +func (c *Checker) getGlobalTypeAliasResolver(name ast.SymbolName, arity int, reportErrors bool) func() *ast.Symbol { return core.Memoize(func() *ast.Symbol { return c.getGlobalTypeAliasSymbol(name, arity, reportErrors) }) } // Resolve to the global value symbol by the given name, or nil otherwise -func (c *Checker) getGlobalValueSymbolResolver(name string, reportErrors bool) func() *ast.Symbol { +func (c *Checker) getGlobalValueSymbolResolver(name ast.SymbolName, reportErrors bool) func() *ast.Symbol { return core.Memoize(func() *ast.Symbol { return c.getGlobalSymbol(name, ast.SymbolFlagsValue, core.IfElse(reportErrors, diagnostics.Cannot_find_global_value_0, nil)) }) } -func (c *Checker) getGlobalTypeSymbolResolver(name string, reportErrors bool) func() *ast.Symbol { +func (c *Checker) getGlobalTypeSymbolResolver(name ast.SymbolName, reportErrors bool) func() *ast.Symbol { return core.Memoize(func() *ast.Symbol { return c.getGlobalSymbol(name, ast.SymbolFlagsType, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) }) @@ -1213,12 +1213,12 @@ func (c *Checker) getGlobalTypeSymbolResolver(name string, reportErrors bool) fu func (c *Checker) getGlobalTypesResolver(names []string, arity int, reportErrors bool) func() []*Type { return core.Memoize(func() []*Type { return core.Map(names, func(name string) *Type { - return c.getGlobalType(name, arity, reportErrors) + return c.getGlobalType(ast.MakeSymbolName(name), arity, reportErrors) }) }) } -func (c *Checker) getGlobalTypeAliasSymbol(name string, arity int, reportErrors bool) *ast.Symbol { +func (c *Checker) getGlobalTypeAliasSymbol(name ast.SymbolName, arity int, reportErrors bool) *ast.Symbol { symbol := c.getGlobalSymbol(name, ast.SymbolFlagsTypeAlias, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) if symbol == nil { return nil @@ -1228,7 +1228,7 @@ func (c *Checker) getGlobalTypeAliasSymbol(name string, arity int, reportErrors if len(c.typeAliasLinks.Get(symbol).typeParameters) != arity { if reportErrors { decl := core.Find(symbol.Declarations(), ast.IsTypeAliasDeclaration) - c.error(decl, diagnostics.Global_type_0_must_have_1_type_parameter_s, ast.SymbolName(symbol), arity) + c.error(decl, diagnostics.Global_type_0_must_have_1_type_parameter_s, ast.SymbolNameText(symbol), arity) } return nil } @@ -1243,7 +1243,7 @@ func (c *Checker) GetTypeAliasTypeParameters(symbol *ast.Symbol) []*Type { return c.typeAliasLinks.Get(symbol).typeParameters } -func (c *Checker) getGlobalType(name string, arity int, reportErrors bool) *Type { +func (c *Checker) getGlobalType(name ast.SymbolName, arity int, reportErrors bool) *Type { symbol := c.getGlobalSymbol(name, ast.SymbolFlagsType, core.IfElse(reportErrors, diagnostics.Cannot_find_global_type_0, nil)) if symbol != nil { if symbol.Flags()&(ast.SymbolFlagsClass|ast.SymbolFlagsInterface) != 0 { @@ -1252,10 +1252,10 @@ func (c *Checker) getGlobalType(name string, arity int, reportErrors bool) *Type return t } if reportErrors { - c.error(getGlobalTypeDeclaration(symbol), diagnostics.Global_type_0_must_have_1_type_parameter_s, ast.SymbolName(symbol), arity) + c.error(getGlobalTypeDeclaration(symbol), diagnostics.Global_type_0_must_have_1_type_parameter_s, ast.SymbolNameText(symbol), arity) } } else if reportErrors { - c.error(getGlobalTypeDeclaration(symbol), diagnostics.Global_type_0_must_be_a_class_or_interface_type, ast.SymbolName(symbol)) + c.error(getGlobalTypeDeclaration(symbol), diagnostics.Global_type_0_must_be_a_class_or_interface_type, ast.SymbolNameText(symbol)) } } if arity != 0 { @@ -1274,7 +1274,7 @@ func getGlobalTypeDeclaration(symbol *ast.Symbol) *ast.Declaration { return nil } -func (c *Checker) getGlobalSymbol(name string, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { +func (c *Checker) getGlobalSymbol(name ast.SymbolName, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { // Don't track references for global symbols anyway, so value if `isReference` is arbitrary return c.resolveName(nil, name, meaning, diagnostic, false /*isUse*/, false /*excludeGlobals*/) } @@ -1294,7 +1294,7 @@ func (c *Checker) initializeClosures() { func (c *Checker) initializeIterationResolvers() { c.syncIterationTypesResolver = &IterationTypesResolver{ - iteratorSymbolName: "iterator", + iteratorSymbolName: ast.SymbolNameIteratorProperty, getGlobalIteratorType: c.getGlobalIteratorType, getGlobalIterableType: c.getGlobalIterableType, getGlobalIterableTypeChecked: c.getGlobalIterableTypeChecked, @@ -1311,7 +1311,7 @@ func (c *Checker) initializeIterationResolvers() { mustHaveAValueDiagnostic: diagnostics.The_type_returned_by_the_0_method_of_an_iterator_must_have_a_value_property, } c.asyncIterationTypesResolver = &IterationTypesResolver{ - iteratorSymbolName: "asyncIterator", + iteratorSymbolName: ast.SymbolNameAsyncIteratorProperty, getGlobalIteratorType: c.getGlobalAsyncIteratorType, getGlobalIterableType: c.getGlobalAsyncIterableType, getGlobalIterableTypeChecked: c.getGlobalAsyncIterableTypeChecked, @@ -1336,7 +1336,7 @@ func (c *Checker) initializeChecker() { for _, file := range c.files { if !ast.IsExternalOrCommonJSModule(file) { // It is an error for a non-external-module (i.e. script) to declare its own `globalThis`. - if fileGlobalThisSymbol := file.Locals["globalThis"]; fileGlobalThisSymbol != nil { + if fileGlobalThisSymbol := file.Locals[ast.SymbolNameGlobalThis]; fileGlobalThisSymbol != nil { for _, d := range fileGlobalThisSymbol.Declarations() { c.addDiagnostic(NewDiagnosticForNode(d, diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis")) } @@ -1379,31 +1379,31 @@ func (c *Checker) initializeChecker() { } c.addUndefinedToGlobalsOrErrorOnRedeclaration() c.valueSymbolLinks.Get(c.undefinedSymbol).resolvedType = c.undefinedWideningType - c.valueSymbolLinks.Get(c.argumentsSymbol).resolvedType = c.getGlobalType("IArguments", 0 /*arity*/, true /*reportErrors*/) + c.valueSymbolLinks.Get(c.argumentsSymbol).resolvedType = c.getGlobalType(ast.SymbolNameIArguments, 0 /*arity*/, true /*reportErrors*/) c.valueSymbolLinks.Get(c.unknownSymbol).resolvedType = c.errorType c.valueSymbolLinks.Get(c.globalThisSymbol).resolvedType = c.newObjectType(ObjectFlagsAnonymous, c.globalThisSymbol) // Initialize special types - c.globalArrayType = c.getGlobalType("Array", 1 /*arity*/, true /*reportErrors*/) - c.globalObjectType = c.getGlobalType("Object", 0 /*arity*/, true /*reportErrors*/) - c.globalFunctionType = c.getGlobalType("Function", 0 /*arity*/, true /*reportErrors*/) - c.globalCallableFunctionType = c.getGlobalStrictFunctionType("CallableFunction") - c.globalNewableFunctionType = c.getGlobalStrictFunctionType("NewableFunction") - c.globalStringType = c.getGlobalType("String", 0 /*arity*/, true /*reportErrors*/) - c.globalNumberType = c.getGlobalType("Number", 0 /*arity*/, true /*reportErrors*/) - c.globalBooleanType = c.getGlobalType("Boolean", 0 /*arity*/, true /*reportErrors*/) - c.globalRegExpType = c.getGlobalType("RegExp", 0 /*arity*/, true /*reportErrors*/) + c.globalArrayType = c.getGlobalType(ast.SymbolNameArray, 1 /*arity*/, true /*reportErrors*/) + c.globalObjectType = c.getGlobalType(ast.SymbolNameObject, 0 /*arity*/, true /*reportErrors*/) + c.globalFunctionType = c.getGlobalType(ast.SymbolNameFunction, 0 /*arity*/, true /*reportErrors*/) + c.globalCallableFunctionType = c.getGlobalStrictFunctionType(ast.SymbolNameCallableFunction) + c.globalNewableFunctionType = c.getGlobalStrictFunctionType(ast.SymbolNameNewableFunction) + c.globalStringType = c.getGlobalType(ast.SymbolNameString, 0 /*arity*/, true /*reportErrors*/) + c.globalNumberType = c.getGlobalType(ast.SymbolNameNumber, 0 /*arity*/, true /*reportErrors*/) + c.globalBooleanType = c.getGlobalType(ast.SymbolNameBoolean, 0 /*arity*/, true /*reportErrors*/) + c.globalRegExpType = c.getGlobalType(ast.SymbolNameRegExp, 0 /*arity*/, true /*reportErrors*/) c.anyArrayType = c.createArrayType(c.anyType) c.autoArrayType = c.createArrayType(c.autoType) if c.autoArrayType == c.emptyObjectType { // autoArrayType is used as a marker, so even if global Array type is not defined, it needs to be a unique type c.autoArrayType = c.newAnonymousType(nil, nil, nil, nil, nil) } - c.globalReadonlyArrayType = c.getGlobalType("ReadonlyArray", 1 /*arity*/, false /*reportErrors*/) + c.globalReadonlyArrayType = c.getGlobalType(ast.SymbolNameReadonlyArray, 1 /*arity*/, false /*reportErrors*/) if c.globalReadonlyArrayType == c.emptyGenericType { c.globalReadonlyArrayType = c.globalArrayType } c.anyReadonlyArrayType = c.createTypeFromGenericGlobalType(c.globalReadonlyArrayType, []*Type{c.anyType}) - c.globalThisType = c.getGlobalType("ThisType", 1 /*arity*/, false /*reportErrors*/) + c.globalThisType = c.getGlobalType(ast.SymbolNameThisType, 1 /*arity*/, false /*reportErrors*/) // Now merge global ambient module declarations for _, symbol := range ambientModuleSymbols { c.mergeGlobalSymbol(symbol) @@ -1495,8 +1495,8 @@ func (c *Checker) mergeModuleAugmentation(moduleName *ast.Node) { }) { merged := c.mergeSymbol(moduleAugmentation.Symbol, mainModule, true /*unidirectional*/) // moduleName will be a StringLiteral since this is not `declare global`. - ast.GetSymbolTable(&c.patternAmbientModuleAugmentations)[moduleName.Text()] = merged - ast.GetSymbolTable(&c.patternAmbientModuleAugmentationTargets)[moduleName.Text()] = mainModule + ast.GetSymbolTable(&c.patternAmbientModuleAugmentations)[moduleName.TextSymbolName()] = merged + ast.GetSymbolTable(&c.patternAmbientModuleAugmentationTargets)[moduleName.TextSymbolName()] = mainModule } else { if mainModule.Exports()[ast.InternalSymbolNameExportStar] != nil && len(moduleAugmentation.Symbol.Exports()) != 0 { // We may need to merge the module augmentation's exports into the target symbols of the resolved exports @@ -1522,7 +1522,7 @@ func (c *Checker) addUndefinedToGlobalsOrErrorOnRedeclaration() { if targetSymbol != nil { for _, declaration := range targetSymbol.Declarations() { if !ast.IsTypeDeclaration(declaration) { - c.addDiagnostic(createDiagnosticForNode(declaration, diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, name)) + c.addDiagnostic(createDiagnosticForNode(declaration, diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, name.Value())) } } } else { @@ -1578,7 +1578,7 @@ func (c *Checker) setRequiresScopeChangeCache(node *ast.Node, value core.Tristat // The invalid initializer error is needed in two situation: // 1. When result is undefined, after checking for a missing "this." // 2. When result is defined -func (c *Checker) checkAndReportErrorForInvalidInitializer(errorLocation *ast.Node, name string, propertyWithInvalidInitializer *ast.Node, result *ast.Symbol) bool { +func (c *Checker) checkAndReportErrorForInvalidInitializer(errorLocation *ast.Node, name ast.SymbolName, propertyWithInvalidInitializer *ast.Node, result *ast.Symbol) bool { if !c.compilerOptions.GetEmitStandardClassFields() { if errorLocation != nil && result == nil && c.checkAndReportErrorForMissingPrefix(errorLocation, name) { return true @@ -1590,14 +1590,14 @@ func (c *Checker) checkAndReportErrorForInvalidInitializer(errorLocation *ast.No message := core.IfElse(errorLocation != nil && prop.Type != nil && prop.Type.Loc.ContainsInclusive(errorLocation.Pos()), diagnostics.Type_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor, diagnostics.Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor) - c.error(errorLocation, message, scanner.DeclarationNameToString(prop.Name()), name) + c.error(errorLocation, message, scanner.DeclarationNameToString(prop.Name()), name.Value()) return true } return false } -func (c *Checker) checkAndReportErrorForMissingPrefix(errorLocation *ast.Node, name string) bool { - if !ast.IsIdentifier(errorLocation) || errorLocation.Text() != name || isTypeReferenceIdentifier(errorLocation) || IsInTypeQuery(errorLocation) { +func (c *Checker) checkAndReportErrorForMissingPrefix(errorLocation *ast.Node, name ast.SymbolName) bool { + if !ast.IsIdentifier(errorLocation) || errorLocation.TextSymbolName() != name || isTypeReferenceIdentifier(errorLocation) || IsInTypeQuery(errorLocation) { return false } container := c.getThisContainer(errorLocation, false /*includeArrowFunctions*/, false /*includeClassComputedPropertyName*/) @@ -1610,7 +1610,7 @@ func (c *Checker) checkAndReportErrorForMissingPrefix(errorLocation *ast.Node, n // Check to see if a static member exists. constructorType := c.getTypeOfSymbol(classSymbol) if c.getPropertyOfType(constructorType, name) != nil { - c.error(errorLocation, diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, name, c.symbolToString(classSymbol)) + c.error(errorLocation, diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, name.Value(), c.symbolToString(classSymbol)) return true } // No static member is present. @@ -1619,7 +1619,7 @@ func (c *Checker) checkAndReportErrorForMissingPrefix(errorLocation *ast.Node, n instanceType := c.getDeclaredTypeOfSymbol(classSymbol).AsInterfaceType().thisType // TODO: GH#18217 if c.getPropertyOfType(instanceType, name) != nil { - c.error(errorLocation, diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, name) + c.error(errorLocation, diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, name.Value()) return true } } @@ -1628,7 +1628,7 @@ func (c *Checker) checkAndReportErrorForMissingPrefix(errorLocation *ast.Node, n return false } -func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name string, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message) { +func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags, nameNotFoundMessage *diagnostics.Message) { // The `const` in a `const` assertion (`x as const`) is a syntactic marker, not a real // type reference, and must never be resolved or reported as an unresolvable name. if isConstTypeReferenceName(errorLocation) { @@ -1645,13 +1645,13 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name string, return } declarationName := name - if errorLocation != nil && ast.IsIdentifier(errorLocation) && errorLocation.Text() == name { - declarationName = scanner.DeclarationNameToString(errorLocation) // use escape sequences from original file + if errorLocation != nil && ast.IsIdentifier(errorLocation) && errorLocation.TextSymbolName() == name { + declarationName = ast.MakeSymbolName(scanner.DeclarationNameToString(errorLocation)) // use escape sequences from original file } // Report missing lib first suggestedLib := c.getSuggestedLibForNonExistentName(name) if suggestedLib != "" { - c.error(errorLocation, nameNotFoundMessage, declarationName, suggestedLib) + c.error(errorLocation, nameNotFoundMessage, declarationName.Value(), suggestedLib) return } // Then spelling suggestions @@ -1661,7 +1661,7 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name string, isUncheckedJS := c.isUncheckedJSSuggestion(errorLocation, suggestion, false /*excludeClasses*/) message := core.IfElse(meaning == ast.SymbolFlagsNamespace, diagnostics.Cannot_find_namespace_0_Did_you_mean_1, core.IfElse(isUncheckedJS, diagnostics.Could_not_find_name_0_Did_you_mean_1, diagnostics.Cannot_find_name_0_Did_you_mean_1)) - diagnostic := NewDiagnosticForNode(errorLocation, message, declarationName, suggestionName) + diagnostic := NewDiagnosticForNode(errorLocation, message, declarationName.Value(), suggestionName) if suggestion.ValueDeclaration() != nil { diagnostic.AddRelatedInfo(NewDiagnosticForNode(suggestion.ValueDeclaration(), diagnostics.X_0_is_declared_here, suggestionName)) } @@ -1669,10 +1669,10 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name string, return } // And then fall back to unspecified "not found" - c.error(errorLocation, nameNotFoundMessage, declarationName) + c.error(errorLocation, nameNotFoundMessage, declarationName.Value()) } -func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast.Node, name string, meaning ast.SymbolFlags) bool { +func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags) bool { if meaning == ast.SymbolFlagsNamespace { symbol := c.resolveSymbol(c.resolveName(errorLocation, name, ast.SymbolFlagsType&^ast.SymbolFlagsNamespace, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)) if symbol != nil { @@ -1680,53 +1680,53 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast. if ast.IsQualifiedName(parent) { debug.Assert(parent.AsQualifiedName().Left == errorLocation, "Should only be resolving left side of qualified name as a namespace") propName := parent.AsQualifiedName().Right.Text() - propType := c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), propName) + propType := c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), ast.MakeSymbolName(propName)) if propType != nil { - c.error(parent, diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, name, propName) + c.error(parent, diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, name.Value(), propName) return true } } - c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, name) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, name.Value()) return true } } return false } -func (c *Checker) checkAndReportErrorForExportingPrimitiveType(errorLocation *ast.Node, name string) bool { +func (c *Checker) checkAndReportErrorForExportingPrimitiveType(errorLocation *ast.Node, name ast.SymbolName) bool { if isPrimitiveTypeName(name) && errorLocation.Parent.Kind == ast.KindExportSpecifier { - c.error(errorLocation, diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name) + c.error(errorLocation, diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name.Value()) return true } return false } -func isPrimitiveTypeName(s string) bool { - return s == "any" || s == "string" || s == "number" || s == "boolean" || s == "never" || s == "unknown" +func isPrimitiveTypeName(s ast.SymbolName) bool { + return s == ast.SymbolNameAny || s == ast.SymbolNameStringKeyword || s == ast.SymbolNameNumberKeyword || s == ast.SymbolNameBooleanKeyword || s == ast.SymbolNameNever || s == ast.SymbolNameUnknown } -func (c *Checker) checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation *ast.Node, name string, meaning ast.SymbolFlags) bool { +func (c *Checker) checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocation *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags) bool { if meaning&(ast.SymbolFlagsValue&^ast.SymbolFlagsType) != 0 { symbol := c.resolveSymbol(c.resolveName(errorLocation, name, ast.SymbolFlagsNamespaceModule, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)) if symbol != nil { // `export = ns` may legitimately reference a namespace; checkExportAssignment decides // whether that is an error, so don't report "cannot use namespace as a value" here. if !isExportAssignmentExpressionName(errorLocation) { - c.error(errorLocation, diagnostics.Cannot_use_namespace_0_as_a_value, name) + c.error(errorLocation, diagnostics.Cannot_use_namespace_0_as_a_value, name.Value()) } return true } } else if meaning&(ast.SymbolFlagsType&^ast.SymbolFlagsValue) != 0 { symbol := c.resolveSymbol(c.resolveName(errorLocation, name, ast.SymbolFlagsModule, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)) if symbol != nil { - c.error(errorLocation, diagnostics.Cannot_use_namespace_0_as_a_type, name) + c.error(errorLocation, diagnostics.Cannot_use_namespace_0_as_a_type, name.Value()) return true } } return false } -func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node, name string, meaning ast.SymbolFlags) bool { +func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags) bool { if meaning&ast.SymbolFlagsValue != 0 { if isPrimitiveTypeName(name) { grandparent := errorLocation.Parent.Parent @@ -1734,14 +1734,14 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node heritageKind := grandparent.AsHeritageClause().Token containerKind := grandparent.Parent.Kind if containerKind == ast.KindInterfaceDeclaration && heritageKind == ast.KindExtendsKeyword { - c.error(errorLocation, diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_It_can_only_extend_other_named_object_types, name) + c.error(errorLocation, diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_It_can_only_extend_other_named_object_types, name.Value()) } else if ast.IsClassLike(grandparent.Parent) && heritageKind == ast.KindExtendsKeyword { - c.error(errorLocation, diagnostics.A_class_cannot_extend_a_primitive_type_like_0_Classes_can_only_extend_constructable_values, name) + c.error(errorLocation, diagnostics.A_class_cannot_extend_a_primitive_type_like_0_Classes_can_only_extend_constructable_values, name.Value()) } else if ast.IsClassLike(grandparent.Parent) && heritageKind == ast.KindImplementsKeyword { - c.error(errorLocation, diagnostics.A_class_cannot_implement_a_primitive_type_like_0_It_can_only_implement_other_named_object_types, name) + c.error(errorLocation, diagnostics.A_class_cannot_implement_a_primitive_type_like_0_It_can_only_implement_other_named_object_types, name.Value()) } } else { - c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name.Value()) } return true } @@ -1755,11 +1755,11 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node return true } if isES2015OrLaterConstructorName(name) { - c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, name) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Do_you_need_to_change_your_target_library_Try_changing_the_lib_compiler_option_to_es2015_or_later, name.Value()) } else if c.maybeMappedType(errorLocation, symbol) { - c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, name, core.IfElse(name == "K", "P", "K")) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here_Did_you_mean_to_use_1_in_0, name.Value(), core.IfElse(name == ast.SymbolNameK, "P", "K")) } else { - c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name.Value()) } return true } @@ -1768,8 +1768,8 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node return false } -func isES2015OrLaterConstructorName(s string) bool { - return s == "Promise" || s == "Symbol" || s == "Map" || s == "WeakMap" || s == "Set" || s == "WeakSet" +func isES2015OrLaterConstructorName(s ast.SymbolName) bool { + return s == ast.SymbolNamePromise || s == ast.SymbolNameSymbol || s == ast.SymbolNameMap || s == ast.SymbolNameWeakMap || s == ast.SymbolNameSet || s == ast.SymbolNameWeakSet } func (c *Checker) maybeMappedType(node *ast.Node, symbol *ast.Symbol) bool { @@ -1786,18 +1786,18 @@ func (c *Checker) maybeMappedType(node *ast.Node, symbol *ast.Symbol) bool { return false } -func (c *Checker) checkAndReportErrorForUsingValueAsType(errorLocation *ast.Node, name string, meaning ast.SymbolFlags) bool { +func (c *Checker) checkAndReportErrorForUsingValueAsType(errorLocation *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags) bool { if meaning&(ast.SymbolFlagsType & ^ast.SymbolFlagsNamespace) != 0 { symbol := c.resolveSymbol(c.resolveName(errorLocation, name, ^ast.SymbolFlagsType&ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)) if symbol != nil && symbol.Flags()&ast.SymbolFlagsNamespace == 0 { - c.error(errorLocation, diagnostics.X_0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, name) + c.error(errorLocation, diagnostics.X_0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, name.Value()) return true } } return false } -func (c *Checker) getSuggestedLibForNonExistentName(name string) string { +func (c *Checker) getSuggestedLibForNonExistentName(name ast.SymbolName) string { featureMap := getFeatureMap() if typeFeatures, ok := featureMap[name]; ok { return typeFeatures[0].lib @@ -1805,12 +1805,12 @@ func (c *Checker) getSuggestedLibForNonExistentName(name string) string { return "" } -func (c *Checker) getSuggestedSymbolForNonexistentSymbol(location *ast.Node, outerName string, meaning ast.SymbolFlags) *ast.Symbol { +func (c *Checker) getSuggestedSymbolForNonexistentSymbol(location *ast.Node, outerName ast.SymbolName, meaning ast.SymbolFlags) *ast.Symbol { return c.resolveNameForSymbolSuggestion(location, outerName, meaning, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } -var primitiveTypeAliasSuggestions = sync.OnceValue(func() map[string]*ast.Symbol { - result := make(map[string]*ast.Symbol, 6) +var primitiveTypeAliasSuggestions = sync.OnceValue(func() ast.SymbolTable { + result := make(ast.SymbolTable, 6) for _, e := range []struct{ primitive, builtin string }{ {"string", "String"}, {"number", "Number"}, @@ -1821,8 +1821,8 @@ var primitiveTypeAliasSuggestions = sync.OnceValue(func() map[string]*ast.Symbol } { sym := ast.NewSymbol() sym.SetFlags(ast.SymbolFlagsTypeAlias | ast.SymbolFlagsTransient) - sym.SetName(e.primitive) - result[e.builtin] = sym + sym.SetName(ast.MakeSymbolName(e.primitive)) + result[ast.MakeSymbolName(e.builtin)] = sym } return result }) @@ -1839,7 +1839,7 @@ func getPrimitiveTypeAliasSuggestions(symbols ast.SymbolTable) iter.Seq[*ast.Sym } } -func (c *Checker) getSuggestionForSymbolNameLookup(symbols ast.SymbolTable, name string, meaning ast.SymbolFlags) *ast.Symbol { +func (c *Checker) getSuggestionForSymbolNameLookup(symbols ast.SymbolTable, name ast.SymbolName, meaning ast.SymbolFlags) *ast.Symbol { symbol := c.getSymbol(symbols, name, meaning) if symbol != nil { return symbol @@ -1864,9 +1864,9 @@ func (c *Checker) getSuggestionForSymbolNameLookup(symbols ast.SymbolTable, name // - Whose length differs from the target name by more than 0.34 of the length of the name. // - Whose levenshtein distance is more than 0.4 of the length of the name (0.4 allows 1 substitution/transposition // for every 5 characters, and 1 insertion/deletion at 3 characters) -func (c *Checker) getSpellingSuggestionForName(name string, symbols iter.Seq[*ast.Symbol], meaning ast.SymbolFlags) *ast.Symbol { +func (c *Checker) getSpellingSuggestionForName(name ast.SymbolName, symbols iter.Seq[*ast.Symbol], meaning ast.SymbolFlags) *ast.Symbol { getCandidateName := func(candidate *ast.Symbol) string { - candidateName := ast.SymbolName(candidate) + candidateName := ast.SymbolNameText(candidate) if len(candidateName) == 0 || candidateName[0] == '"' || candidateName[0] == '\xFE' { return "" } @@ -1881,7 +1881,7 @@ func (c *Checker) getSpellingSuggestionForName(name string, symbols iter.Seq[*as } return "" } - return core.GetSpellingSuggestion(name, symbols, getCandidateName, c.compareSymbols) + return core.GetSpellingSuggestion(name.Value(), symbols, getCandidateName, c.compareSymbols) } func (c *Checker) onSuccessfullyResolvedSymbol(errorLocation *ast.Node, result *ast.Symbol, meaning ast.SymbolFlags, lastLocation *ast.Node, associatedDeclarationForContainingInitializerOrBindingName *ast.Node, withinDeferredContext bool) { @@ -1910,7 +1910,7 @@ func (c *Checker) onSuccessfullyResolvedSymbol(errorLocation *ast.Node, result * if len(merged.Declarations()) != 0 && core.Every(merged.Declarations(), func(d *ast.Node) bool { return ast.IsNamespaceExportDeclaration(d) || ast.IsSourceFile(d) && d.AsSourceFile().GlobalExports != nil }) { - c.errorOrSuggestion(c.compilerOptions.AllowUmdGlobalAccess != core.TSTrue, errorLocation, diagnostics.X_0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, name) + c.errorOrSuggestion(c.compilerOptions.AllowUmdGlobalAccess != core.TSTrue, errorLocation, diagnostics.X_0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, name.Value()) } } // If we're in a parameter initializer or binding name, we can't reference the values of the parameter whose initializer we're within or parameters to the right @@ -1930,7 +1930,7 @@ func (c *Checker) onSuccessfullyResolvedSymbol(errorLocation *ast.Node, result * message := core.IfElse(ast.NodeKindIs(typeOnlyDeclaration, ast.KindExportSpecifier, ast.KindExportDeclaration, ast.KindNamespaceExport), diagnostics.X_0_cannot_be_used_as_a_value_because_it_was_exported_using_export_type, diagnostics.X_0_cannot_be_used_as_a_value_because_it_was_imported_using_import_type) - c.addTypeOnlyDeclarationRelatedInfo(c.error(errorLocation, message, name), typeOnlyDeclaration, name) + c.addTypeOnlyDeclarationRelatedInfo(c.error(errorLocation, message, name.Value()), typeOnlyDeclaration, name.Value()) } } // Look at 'compilerOptions.isolatedModules' and not 'getIsolatedModules(...)' (which considers 'verbatimModuleSyntax') @@ -1946,7 +1946,7 @@ func (c *Checker) onSuccessfullyResolvedSymbol(errorLocation *ast.Node, result * return ast.NodeKindIs(d, ast.KindImportSpecifier, ast.KindImportClause, ast.KindNamespaceImport, ast.KindImportEqualsDeclaration) }) if importDecl != nil && !ast.IsTypeOnlyImportDeclaration(importDecl) { - c.error(importDecl, diagnostics.Import_0_conflicts_with_global_value_used_in_this_file_so_must_be_declared_with_a_type_only_import_when_isolatedModules_is_enabled, name) + c.error(importDecl, diagnostics.Import_0_conflicts_with_global_value_used_in_this_file_so_must_be_declared_with_a_type_only_import_when_isolatedModules_is_enabled, name.Value()) } } } @@ -2240,7 +2240,7 @@ func (c *Checker) addTypeOnlyDeclarationRelatedInfo(diagnostic *ast.Diagnostic, return diagnostic.AddRelatedInfo(NewDiagnosticForNode(typeOnlyDeclaration, core.IfElse(isExport, diagnostics.X_0_was_exported_here, diagnostics.X_0_was_imported_here), name)) } -func (c *Checker) getSymbol(symbols ast.SymbolTable, name string, meaning ast.SymbolFlags) *ast.Symbol { +func (c *Checker) getSymbol(symbols ast.SymbolTable, name ast.SymbolName, meaning ast.SymbolFlags) *ast.Symbol { if meaning&ast.SymbolFlagsAll != 0 { symbol := c.getMergedSymbol(symbols[name]) if symbol != nil { @@ -2630,7 +2630,7 @@ func (c *Checker) resolveJSDocMemberName(name *ast.Node) *ast.Symbol { if symbol := c.resolveJSDocMemberName(name.AsQualifiedName().Left); symbol != nil { var t *Type if symbol.Flags()&ast.SymbolFlagsValue != 0 { - proto := c.getPropertyOfType(c.getTypeOfSymbol(symbol), "prototype") + proto := c.getPropertyOfType(c.getTypeOfSymbol(symbol), ast.SymbolNamePrototype) if proto != nil { t = c.getTypeOfSymbol(proto) } @@ -2638,7 +2638,7 @@ func (c *Checker) resolveJSDocMemberName(name *ast.Node) *ast.Symbol { if t == nil { t = c.getDeclaredTypeOfSymbol(symbol) } - return c.getPropertyOfType(t, name.AsQualifiedName().Right.Text()) + return c.getPropertyOfType(t, name.AsQualifiedName().Right.TextSymbolName()) } } } @@ -3081,7 +3081,7 @@ func (c *Checker) checkTypeReferenceOrImport(node *ast.Node) { symbol := c.getResolvedSymbolOrNil(node) if symbol != nil { if core.Some(symbol.Declarations(), func(d *ast.Node) bool { return ast.IsTypeDeclaration(d) && c.IsDeprecatedDeclaration(d) }) { - c.addDeprecatedSuggestion(c.getDeprecatedSuggestionNode(node), symbol.Declarations(), symbol.Name()) + c.addDeprecatedSuggestion(c.getDeprecatedSuggestionNode(node), symbol.Declarations(), symbol.Name().Value()) } } } @@ -3164,7 +3164,7 @@ func (c *Checker) checkTypePredicate(node *ast.Node) { } } if !hasReportedError { - c.error(parameterName, diagnostics.Cannot_find_parameter_0, typePredicate.parameterName) + c.error(parameterName, diagnostics.Cannot_find_parameter_0, typePredicate.parameterName.Value()) } } } @@ -3182,14 +3182,14 @@ func (c *Checker) getTypePredicateParent(node *ast.Node) *ast.SignatureDeclarati return nil } -func (c *Checker) checkIfTypePredicateVariableIsDeclaredInBindingPattern(pattern *ast.Node, predicateVariableNode *ast.Node, predicateVariableName string) bool { +func (c *Checker) checkIfTypePredicateVariableIsDeclaredInBindingPattern(pattern *ast.Node, predicateVariableNode *ast.Node, predicateVariableName ast.SymbolName) bool { for _, element := range pattern.Elements() { name := element.Name() if name == nil { continue } - if ast.IsIdentifier(name) && name.Text() == predicateVariableName { - c.error(predicateVariableNode, diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName) + if ast.IsIdentifier(name) && name.TextSymbolName() == predicateVariableName { + c.error(predicateVariableNode, diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName.Value()) return true } if ast.IsArrayBindingPattern(name) || ast.IsObjectBindingPattern(name) { @@ -3214,21 +3214,21 @@ func (c *Checker) checkTypeLiteral(node *ast.Node) { } func (c *Checker) checkObjectTypeForDuplicateDeclarations(node *ast.Node, checkPrivateNames bool) { - var instanceNames map[string]int - var staticNames map[string]int - var privateNames map[string]int + var instanceNames map[ast.SymbolName]int + var staticNames map[ast.SymbolName]int + var privateNames map[ast.SymbolName]int nodeInAmbientContext := node.Flags&ast.NodeFlagsAmbient != 0 checkPropertyOrAccessor := func(symbol *ast.Symbol, kind int, isStatic bool) { if len(symbol.Declarations()) > 1 { - var names map[string]int + var names map[ast.SymbolName]int if isStatic { if staticNames == nil { - staticNames = make(map[string]int) + staticNames = make(map[ast.SymbolName]int) } names = staticNames } else { if instanceNames == nil { - instanceNames = make(map[string]int) + instanceNames = make(map[ast.SymbolName]int) } names = instanceNames } @@ -3256,8 +3256,8 @@ func (c *Checker) checkObjectTypeForDuplicateDeclarations(node *ast.Node, checkP symbol := c.getSymbolOfDeclaration(member) isStatic := ast.HasStaticModifier(member) // In non-ambient contexts, check that static members are not named 'prototype'. - if !nodeInAmbientContext && isStatic && symbol != nil && symbol.Name() == "prototype" { - c.error(member.Name(), diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1, symbol.Name(), c.symbolToString(c.getSymbolOfDeclaration(node))) + if !nodeInAmbientContext && isStatic && symbol != nil && symbol.Name() == ast.SymbolNamePrototype { + c.error(member.Name(), diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1, symbol.Name().Value(), c.symbolToString(c.getSymbolOfDeclaration(node))) } // Check that this object type declaration doesn't contain multiple declarations of the same property, // or accessor and property declarations with the same name. @@ -3272,7 +3272,7 @@ func (c *Checker) checkObjectTypeForDuplicateDeclarations(node *ast.Node, checkP if flags := privateNames[symbol.Name()]; flags != 3 { flags |= core.IfElse(ast.IsStatic(member), 2, 1) if privateNames == nil { - privateNames = make(map[string]int) + privateNames = make(map[ast.SymbolName]int) } privateNames[symbol.Name()] = flags if flags == 3 { @@ -3284,7 +3284,7 @@ func (c *Checker) checkObjectTypeForDuplicateDeclarations(node *ast.Node, checkP } } -func (c *Checker) reportDuplicateMemberErrors(node *ast.Node, name string, checkStatic bool, isStatic bool, message *diagnostics.Message) { +func (c *Checker) reportDuplicateMemberErrors(node *ast.Node, name ast.SymbolName, checkStatic bool, isStatic bool, message *diagnostics.Message) { for _, member := range node.Members() { if ast.IsConstructorDeclaration(member) { for _, param := range member.Parameters() { @@ -3726,7 +3726,7 @@ func (c *Checker) checkFunctionOrConstructorSymbolWorker(symbol *ast.Symbol) { diagnostic = diagnostics.Function_with_bodies_can_only_merge_with_classes_that_are_ambient } if diagnostic != nil { - c.error(core.OrElse(ast.GetNameOfDeclaration(declaration), declaration), diagnostic, symbol.Name()).SetRelatedInfo(relatedDiagnostics) + c.error(core.OrElse(ast.GetNameOfDeclaration(declaration), declaration), diagnostic, symbol.Name().Value()).SetRelatedInfo(relatedDiagnostics) } } } @@ -4314,7 +4314,7 @@ func (c *Checker) checkCatchClause(node *ast.Node) { if blockLocals != nil { for caughtName := range node.Locals() { if blockLocal := blockLocals[caughtName]; blockLocal != nil && blockLocal.ValueDeclaration() != nil && blockLocal.Flags()&ast.SymbolFlagsBlockScopedVariable != 0 { - c.grammarErrorOnNode(blockLocal.ValueDeclaration(), diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName) + c.grammarErrorOnNode(blockLocal.ValueDeclaration(), diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName.Value()) } } } @@ -4469,11 +4469,11 @@ func (c *Checker) checkClassForStaticPropertyNameConflicts(node *ast.Node) { if isStaticMember && memberNameNode != nil { memberName, _ := c.getEffectivePropertyNameForPropertyNameNode(memberNameNode) switch memberName { - case "name", "length", "caller", "arguments": + case ast.SymbolNameName, ast.SymbolNameLength, ast.SymbolNameCaller, ast.SymbolNameArguments: c.error( memberNameNode, diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1, - memberName, + memberName.Value(), c.symbolToString(c.getSymbolOfDeclaration(node)), ) } @@ -4523,7 +4523,7 @@ func (c *Checker) areTypeParametersIdentical(declarations []*ast.Node, targetPar target := targetParameters[i] // If the type parameter node does not have the same name as the resolved type // parameter at this position, we report an error. - if source.Name().Text() != target.symbol.Name() { + if source.Name().TextSymbolName() != target.symbol.Name() { return false } // If the type parameter node does not have an identical constraintNode as the resolved @@ -4841,7 +4841,7 @@ func (c *Checker) checkMemberForOverrideModifierWorker(node *ast.Node, staticTyp if prop != nil && baseProp == nil && memberHasOverrideModifier { if errorNode != nil { - suggestion := c.getSuggestedSymbolForNonexistentClassMember(ast.SymbolName(member), baseType) + suggestion := c.getSuggestedSymbolForNonexistentClassMember(ast.MakeSymbolName(ast.SymbolNameText(member)), baseType) if suggestion != nil { c.error(errorNode, core.IfElse(isJs, diagnostics.This_member_cannot_have_a_JSDoc_comment_with_an_override_tag_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1, diagnostics.This_member_cannot_have_an_override_modifier_because_it_is_not_declared_in_the_base_class_0_Did_you_mean_1), c.TypeToString(baseWithThis), c.symbolToString(suggestion)) } else { @@ -4882,7 +4882,7 @@ func (c *Checker) checkMemberForOverrideModifierWorker(node *ast.Node, staticTyp return MemberOverrideStatusNone } -func (c *Checker) getSuggestedSymbolForNonexistentClassMember(name string, baseType *Type) *ast.Symbol { +func (c *Checker) getSuggestedSymbolForNonexistentClassMember(name ast.SymbolName, baseType *Type) *ast.Symbol { return c.getSpellingSuggestionForName(name, slices.Values(c.getPropertiesOfType(baseType)), ast.SymbolFlagsClassMember) } @@ -5143,7 +5143,7 @@ func (c *Checker) checkInheritedPropertiesAreIdentical(t *Type, typeNode *ast.No if len(baseTypes) < 2 { return true } - seen := make(map[string]InheritanceInfo) + seen := make(map[ast.SymbolName]InheritanceInfo) for id, p := range c.resolveDeclaredMembers(t).declaredMembers { if c.isNamedMember(p, id) { seen[p.Name()] = InheritanceInfo{prop: p, containingType: t} @@ -5600,7 +5600,7 @@ func (c *Checker) checkImportAttributesExpression(node *ast.Node) *Type { symbol := c.newSymbol(ast.SymbolFlagsObjectLiteral, ast.InternalSymbolNameImportAttributes) members := make(ast.SymbolTable) for _, attribute := range node.AsImportAttributes().Attributes.Nodes { - member := c.newSymbol(ast.SymbolFlagsProperty, attribute.Name().Text()) + member := c.newSymbol(ast.SymbolFlagsProperty, attribute.Name().TextSymbolName()) c.valueSymbolLinks.Get(member).resolvedType = c.getRegularTypeOfLiteralType(c.checkExpressionCached(attribute.AsImportAttribute().Value)) members[member.Name()] = member } @@ -5620,7 +5620,7 @@ func (c *Checker) getImportAttributesTypeForModuleSpecifier(moduleSpecifier *ast return c.getTypeFromImportAttributes(ast.GetImportAttributes(parent.Parent)) case ast.IsImportCall(parent) && len(parent.Arguments()) > 1: options := parent.Arguments()[1] - return c.getTypeOfPropertyOfType(c.checkExpressionCached(options), "with") + return c.getTypeOfPropertyOfType(c.checkExpressionCached(options), ast.SymbolNameWith) } return nil } @@ -5743,7 +5743,7 @@ func (c *Checker) checkExportSpecifier(node *ast.ExportSpecifierNode) { return // Skip for invalid syntax like this: export { "x" } } // find immediate value referenced by exported name (SymbolFlags.Alias is set so we don't chase down aliases) - symbol := c.resolveName(exportedName, exportedName.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false) + symbol := c.resolveName(exportedName, exportedName.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false) if symbol != nil && (symbol == c.undefinedSymbol || symbol == c.globalThisSymbol || symbol.Declarations() != nil && ast.IsGlobalSourceFile(ast.GetDeclarationContainer(symbol.Declarations()[0]))) { c.error(exportedName, diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, exportedName.Text()) } else { @@ -5909,7 +5909,7 @@ func (c *Checker) checkExternalModuleExports(node *ast.Node) { }) { for _, declaration := range symbol.Declarations() { if isNotOverload(declaration) { - c.error(declaration, diagnostics.Cannot_redeclare_exported_variable_0, id) + c.error(declaration, diagnostics.Cannot_redeclare_exported_variable_0, id.Value()) } } } @@ -6193,7 +6193,7 @@ func (c *Checker) checkVarDeclaredNamesNotShadowed(node *ast.Node) { if !ast.IsIdentifier(name) { panic("Identifier expected") } - localDeclarationSymbol := c.resolveName(node, name.Text(), ast.SymbolFlagsVariable, nil /*nameNotFoundMessage*/, false /*isUse*/, false) + localDeclarationSymbol := c.resolveName(node, name.TextSymbolName(), ast.SymbolFlagsVariable, nil /*nameNotFoundMessage*/, false /*isUse*/, false) if localDeclarationSymbol != nil && localDeclarationSymbol != symbol && localDeclarationSymbol.Flags()&ast.SymbolFlagsBlockScopedVariable != 0 { if c.getDeclarationNodeFlagsFromSymbol(localDeclarationSymbol)&ast.NodeFlagsBlockScoped != 0 { varDeclList := ast.FindAncestorKind(localDeclarationSymbol.ValueDeclaration(), ast.KindVariableDeclarationList) @@ -6729,21 +6729,21 @@ func (c *Checker) getIterationTypesOfIteratorFast(t *Type, r *IterationTypesReso func (c *Checker) getIterationTypesOfIteratorSlow(t *Type, r *IterationTypesResolver, errorNode *ast.Node, diagnosticOutput *[]*ast.Diagnostic) IterationTypes { return c.combineIterationTypes([]IterationTypes{ - c.getIterationTypesOfMethod(t, r, "next", errorNode, diagnosticOutput), - c.getIterationTypesOfMethod(t, r, "return", errorNode, diagnosticOutput), - c.getIterationTypesOfMethod(t, r, "throw", errorNode, diagnosticOutput), + c.getIterationTypesOfMethod(t, r, ast.SymbolNameNext, errorNode, diagnosticOutput), + c.getIterationTypesOfMethod(t, r, ast.SymbolNameReturn, errorNode, diagnosticOutput), + c.getIterationTypesOfMethod(t, r, ast.SymbolNameThrow, errorNode, diagnosticOutput), }) } -func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesResolver, methodName string, errorNode *ast.Node, diagnosticOutput *[]*ast.Diagnostic) IterationTypes { +func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesResolver, methodName ast.SymbolName, errorNode *ast.Node, diagnosticOutput *[]*ast.Diagnostic) IterationTypes { method := c.getPropertyOfType(t, methodName) // Ignore 'return' or 'throw' if they are missing. - if method == nil && methodName != "next" { + if method == nil && methodName != ast.SymbolNameNext { return IterationTypes{} } var methodType *Type - if method != nil && !(methodName == "next" && method.Flags()&ast.SymbolFlagsOptional != 0) { - if methodName == "next" { + if method != nil && !(methodName == ast.SymbolNameNext && method.Flags()&ast.SymbolFlagsOptional != 0) { + if methodName == ast.SymbolNameNext { methodType = c.getTypeOfSymbol(method) } else { methodType = c.getTypeWithFacts(c.getTypeOfSymbol(method), TypeFactsNEUndefinedOrNull) @@ -6759,8 +6759,8 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes } if len(methodSignatures) == 0 { if errorNode != nil { - diagnostic := core.IfElse(methodName == "next", resolver.mustHaveANextMethodDiagnostic, resolver.mustBeAMethodDiagnostic) - c.reportDiagnostic(NewDiagnosticForNode(errorNode, diagnostic, methodName), diagnosticOutput) + diagnostic := core.IfElse(methodName == ast.SymbolNameNext, resolver.mustHaveANextMethodDiagnostic, resolver.mustBeAMethodDiagnostic) + c.reportDiagnostic(NewDiagnosticForNode(errorNode, diagnostic, methodName.Value()), diagnosticOutput) } return IterationTypes{} } @@ -6780,7 +6780,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes typeParameters := core.IfElse(isGeneratorMethod, globalGeneratorType, globalIteratorType).AsInterfaceType().TypeParameters() mapper := methodType.Mapper() var nextType *Type - if methodName == "next" { + if methodName == ast.SymbolNameNext { nextType = getMappedType(typeParameters[2], mapper) } return IterationTypes{getMappedType(typeParameters[0], mapper), getMappedType(typeParameters[1], mapper), nextType} @@ -6790,7 +6790,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes var methodParameterTypes []*Type var methodReturnTypes []*Type for _, signature := range methodSignatures { - if methodName != "throw" && len(signature.parameters) != 0 { + if methodName != ast.SymbolNameThrow && len(signature.parameters) != 0 { methodParameterTypes = append(methodParameterTypes, c.getTypeAtPosition(signature, 0)) } methodReturnTypes = append(methodReturnTypes, c.getReturnTypeOfSignature(signature)) @@ -6799,17 +6799,17 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes // `return()` method, respectively. var returnTypes []*Type var nextType *Type - if methodName != "throw" { + if methodName != ast.SymbolNameThrow { var methodParameterType *Type if methodParameterTypes != nil { methodParameterType = c.getUnionType(methodParameterTypes) } else { methodParameterType = c.unknownType } - if methodName == "next" { + if methodName == ast.SymbolNameNext { // The value of `next(value)` is *not* awaited by async generators nextType = methodParameterType - } else if methodName == "return" { + } else if methodName == ast.SymbolNameReturn { // The value of `return(value)` *is* awaited by async generators resolvedMethodParameterType := core.OrElse(resolver.resolveIterationType(methodParameterType, errorNode), c.anyType) returnTypes = append(returnTypes, resolvedMethodParameterType) @@ -6827,7 +6827,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes iterationTypes := c.getIterationTypesOfIteratorResult(resolvedMethodReturnType) if !iterationTypes.hasTypes() { if errorNode != nil { - c.reportDiagnostic(NewDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName), diagnosticOutput) + c.reportDiagnostic(NewDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName.Value()), diagnosticOutput) } yieldType = c.anyType returnTypes = append(returnTypes, c.anyType) @@ -6859,12 +6859,12 @@ func (c *Checker) getIterationTypesOfIteratorResult(t *Type) IterationTypes { yieldIteratorResult := c.filterType(t, c.isYieldIteratorResult) var yieldType *Type if yieldIteratorResult != c.neverType { - yieldType = c.getTypeOfPropertyOfType(yieldIteratorResult, "value" /* as __String */) + yieldType = c.getTypeOfPropertyOfType(yieldIteratorResult, ast.SymbolNameValue /* as __String */) } returnIteratorResult := c.filterType(t, c.isReturnIteratorResult) var returnType *Type if returnIteratorResult != c.neverType { - returnType = c.getTypeOfPropertyOfType(returnIteratorResult, "value" /* as __String */) + returnType = c.getTypeOfPropertyOfType(returnIteratorResult, ast.SymbolNameValue /* as __String */) } if yieldType == nil && returnType == nil { return IterationTypes{} @@ -6889,7 +6889,7 @@ func (c *Checker) isIteratorResult(t *Type, kind IterationTypeKind) bool { // > [done] is the result status of an iterator `next` method call. If the end of the iterator was reached `done` is `true`. // > If the end was not reached `done` is `false` and a value is available. // > If a `done` property (either own or inherited) does not exist, it is consider to have the value `false`. - doneType := core.OrElse(c.getTypeOfPropertyOfType(t, "done"), c.falseType) + doneType := core.OrElse(c.getTypeOfPropertyOfType(t, ast.SymbolNameDone), c.falseType) return c.isTypeAssignableTo(core.IfElse(kind == IterationTypeKindYield, c.falseType, c.trueType), doneType) } @@ -6922,9 +6922,9 @@ func (c *Checker) getIterationDiagnosticDetails(use IterationUse, inputType *Typ return diagnostics.Type_0_is_not_an_array_type, true } -func isES2015OrLaterIterable(n string) bool { +func isES2015OrLaterIterable(n ast.SymbolName) bool { switch n { - case "Float32Array", "Float64Array", "Int16Array", "Int32Array", "Int8Array", "NodeList", "Uint16Array", "Uint32Array", "Uint8Array", "Uint8ClampedArray": + case ast.SymbolNameFloat32Array, ast.SymbolNameFloat64Array, ast.SymbolNameInt16Array, ast.SymbolNameInt32Array, ast.SymbolNameInt8Array, ast.SymbolNameNodeList, ast.SymbolNameUint16Array, ast.SymbolNameUint32Array, ast.SymbolNameUint8Array, ast.SymbolNameUint8ClampedArray: return true } return false @@ -6951,16 +6951,16 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { if ast.IsExportSpecifier(node) { diag := c.error(errorNode, diagnostics.Types_cannot_appear_in_export_declarations_in_JavaScript_files) if sourceSymbol := ast.GetSourceFileOfNode(node).AsNode().Symbol(); sourceSymbol != nil { - if alreadyExportedSymbol := sourceSymbol.Exports()[node.PropertyNameOrName().Text()]; alreadyExportedSymbol == target { + if alreadyExportedSymbol := sourceSymbol.Exports()[node.PropertyNameOrName().TextSymbolName()]; alreadyExportedSymbol == target { if exportingDeclaration := core.Find(alreadyExportedSymbol.Declarations(), ast.IsJSTypeAliasDeclaration); exportingDeclaration != nil { - diag.AddRelatedInfo(NewDiagnosticForNode(exportingDeclaration, diagnostics.X_0_is_automatically_exported_here, alreadyExportedSymbol.Name())) + diag.AddRelatedInfo(NewDiagnosticForNode(exportingDeclaration, diagnostics.X_0_is_automatically_exported_here, alreadyExportedSymbol.Name().Value())) } } } } else { identifierText := symbol.Name() if ast.IsIdentifier(errorNode) { - identifierText = errorNode.Text() + identifierText = errorNode.TextSymbolName() } specifierText := "..." if importDeclaration := ast.FindAncestor(node, func(n *ast.Node) bool { @@ -6972,9 +6972,9 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { } importText := "import(\"" + specifierText + "\")" if ast.IsImportSpecifier(node) { - importText = importText + "." + identifierText + importText = importText + "." + identifierText.Value() } - c.error(errorNode, diagnostics.X_0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation, identifierText, importText) + c.error(errorNode, diagnostics.X_0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation, identifierText.Value(), importText) } return } @@ -7055,7 +7055,7 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { if ast.IsImportSpecifier(node) { targetSymbol := c.resolveAliasWithDeprecationCheck(symbol, node) if c.isDeprecatedSymbol(targetSymbol) && targetSymbol.Declarations() != nil { - c.addDeprecatedSuggestion(node, targetSymbol.Declarations(), targetSymbol.Name()) + c.addDeprecatedSuggestion(node, targetSymbol.Declarations(), targetSymbol.Name().Value()) } } } @@ -7086,7 +7086,7 @@ func (c *Checker) checkTypeAliasDeclaration(node *ast.Node) { c.checkTypeParameters(typeParameters) if typeNode != nil && typeNode.Kind == ast.KindIntrinsicKeyword { if !(len(typeParameters) == 0 && node.Name().Text() == "BuiltinIteratorReturn" || - len(typeParameters) == 1 && intrinsicTypeKinds[node.Name().Text()] != IntrinsicTypeKindUnknown) { + len(typeParameters) == 1 && intrinsicTypeKinds[node.Name().TextSymbolName()] != IntrinsicTypeKindUnknown) { c.error(typeNode, diagnostics.The_intrinsic_keyword_can_only_be_used_to_declare_compiler_provided_intrinsic_types) } // The `intrinsic` keyword is a leaf type node with no child nodes to check, @@ -7324,7 +7324,7 @@ func (c *Checker) checkUnusedClassMembers(node *ast.Node) { case ast.KindConstructor: for _, parameter := range member.AsConstructorDeclaration().Parameters.Nodes { if !c.isReferenced(parameter.Symbol()) && ast.HasSyntacticModifier(parameter, ast.ModifierFlagsPrivate) { - c.reportUnused(parameter, UnusedKindLocal, NewDiagnosticForNode(parameter.Name(), diagnostics.Property_0_is_declared_but_its_value_is_never_read, ast.SymbolName(parameter.Symbol()))) + c.reportUnused(parameter, UnusedKindLocal, NewDiagnosticForNode(parameter.Name(), diagnostics.Property_0_is_declared_but_its_value_is_never_read, ast.SymbolNameText(parameter.Symbol()))) } } case ast.KindIndexSignature, ast.KindSemicolonClassElement, ast.KindClassStaticBlockDeclaration, ast.KindJSTypeAliasDeclaration: @@ -7359,7 +7359,7 @@ func (c *Checker) checkUnusedLocalsAndParameters(node *ast.Node) { } default: if !ast.IsTypeParameterDeclaration(declaration) && !ast.IsAmbientModule(declaration) { - c.reportUnusedLocal(declaration, ast.SymbolName(local)) + c.reportUnusedLocal(declaration, ast.SymbolNameText(local)) } } } @@ -7784,7 +7784,7 @@ func (c *Checker) checkConstEnumAccess(node *ast.Node, t *Type) { // --verbatimModuleSyntax only gets checked here when the enum usage does not // resolve to an import, because imports of ambient const enums get checked // separately in `checkAliasSymbol`. - if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, ast.GetFirstIdentifier(node).Text(), ast.SymbolFlagsAlias, nil, false, true) == nil { + if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, ast.GetFirstIdentifier(node).TextSymbolName(), ast.SymbolFlagsAlias, nil, false, true) == nil { debug.Assert(t.symbol.Flags()&ast.SymbolFlagsConstEnum != 0) constEnumDeclaration := t.symbol.ValueDeclaration() redirect := c.program.GetProjectReferenceFromOutputDts(ast.GetSourceFileOfNode(constEnumDeclaration).PathKey()) @@ -7906,19 +7906,20 @@ func (c *Checker) getUniqueTypeParameters(context *InferenceContext, typeParamet return result } -func hasTypeParameterByName(typeParameters []*Type, name string) bool { +func hasTypeParameterByName(typeParameters []*Type, name ast.SymbolName) bool { return core.Some(typeParameters, func(tp *Type) bool { return tp.symbol.Name() == name }) } -func getUniqueTypeParameterName(typeParameters []*Type, baseName string) string { - for len(baseName) > 1 && baseName[len(baseName)-1] >= '0' && baseName[len(baseName)-1] <= '9' { - baseName = baseName[:len(baseName)-1] +func getUniqueTypeParameterName(typeParameters []*Type, baseName ast.SymbolName) ast.SymbolName { + baseText := baseName.Value() + for len(baseText) > 1 && baseText[len(baseText)-1] >= '0' && baseText[len(baseText)-1] <= '9' { + baseText = baseText[:len(baseText)-1] } index := 1 for { - augmentedName := baseName + strconv.Itoa(index) + augmentedName := ast.MakeSymbolName(baseText + strconv.Itoa(index)) if !hasTypeParameterByName(typeParameters, augmentedName) { return augmentedName } @@ -8044,7 +8045,7 @@ func (c *Checker) checkPrivateIdentifierExpression(node *ast.Node) *Type { func (c *Checker) getSymbolForPrivateIdentifierExpression(node *ast.Node) *ast.Symbol { links := c.symbolNodeLinks.Get(node) if links.resolvedSymbol == nil { - links.resolvedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(node.Text(), node) + links.resolvedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(node.TextSymbolName(), node) } return links.resolvedSymbol } @@ -8436,7 +8437,7 @@ func (c *Checker) checkIndexedAccessIndexType(t *Type, accessNode *ast.Node) *Ty if propertyName != ast.InternalSymbolNameMissing { propertySymbol := c.getConstituentProperty(objectType, propertyName) if propertySymbol != nil && getDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsNonPublicAccessibilityModifier != 0 { - c.error(accessNode, diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, propertyName) + c.error(accessNode, diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, propertyName.Value()) return c.errorType } } @@ -8445,7 +8446,7 @@ func (c *Checker) checkIndexedAccessIndexType(t *Type, accessNode *ast.Node) *Ty return c.errorType } -func (c *Checker) getConstituentProperty(objectType *Type, propertyName string) *ast.Symbol { +func (c *Checker) getConstituentProperty(objectType *Type, propertyName ast.SymbolName) *ast.Symbol { for _, t := range c.getApparentType(objectType).Distributed() { prop := c.getPropertyOfType(t, propertyName) if prop != nil { @@ -8493,7 +8494,7 @@ func (c *Checker) checkImportCallExpression(node *ast.Node) *Type { } } } - importAttributesType = c.getTypeOfPropertyOfType(optionsType, "with") + importAttributesType = c.getTypeOfPropertyOfType(optionsType, ast.SymbolNameWith) } if ast.IsSourcePhaseImportCall(node) { return c.createPromiseReturnType(node, c.getGlobalAbstractModuleSourceType()) @@ -8598,7 +8599,7 @@ func (c *Checker) isSymbolOrSymbolForCall(node *ast.Node) bool { if globalESSymbol == nil { return false } - return globalESSymbol == c.resolveName(left, "Symbol", ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) + return globalESSymbol == c.resolveName(left, ast.SymbolNameSymbol, ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) } /** @@ -10046,7 +10047,7 @@ func (c *Checker) isPromiseResolveArityError(node *ast.Node) bool { if !ast.IsCallExpression(node) || !ast.IsIdentifier(node.Expression()) { return false } - symbol := c.resolveName(node.Expression(), node.Expression().Text(), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) + symbol := c.resolveName(node.Expression(), node.Expression().TextSymbolName(), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) if symbol == nil { return false } @@ -11509,7 +11510,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l c.checkExternalEmitHelpers(node, ExternalEmitHelpersClassPrivateFieldGet) } } - lexicallyScopedSymbol := c.lookupSymbolForPrivateIdentifierDeclaration(right.Text(), right) + lexicallyScopedSymbol := c.lookupSymbolForPrivateIdentifierDeclaration(right.TextSymbolName(), right) if assignmentKind != AssignmentKindNone && lexicallyScopedSymbol != nil && lexicallyScopedSymbol.ValueDeclaration() != nil && ast.IsMethodDeclaration(lexicallyScopedSymbol.ValueDeclaration()) { c.grammarErrorOnNode(right, diagnostics.Cannot_assign_to_private_method_0_Private_methods_are_not_writable, right.Text()) } @@ -11553,14 +11554,14 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l } return apparentType } - prop = c.getPropertyOfTypeEx(apparentType, right.Text(), isConstEnumObjectType(apparentType) /*skipObjectFunctionPropertyAugment*/, node.Kind == ast.KindQualifiedName /*includeTypeOnlyMembers*/) + prop = c.getPropertyOfTypeEx(apparentType, right.TextSymbolName(), isConstEnumObjectType(apparentType) /*skipObjectFunctionPropertyAugment*/, node.Kind == ast.KindQualifiedName /*includeTypeOnlyMembers*/) } c.markLinkedReferences(node, ReferenceHintProperty, prop, leftType) var propType *Type if prop == nil { var indexInfo *IndexInfo if !ast.IsPrivateIdentifier(right) && (assignmentKind == AssignmentKindNone || !c.isGenericObjectType(leftType) || isThisTypeParameter(leftType)) { - indexInfo = c.getApplicableIndexInfoForName(apparentType, right.Text()) + indexInfo = c.getApplicableIndexInfoForName(apparentType, right.TextSymbolName()) } if indexInfo == nil { isUncheckedJS := c.isUncheckedJSSuggestion(node, leftType.symbol, true /*excludeClasses*/) @@ -11568,7 +11569,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l return c.anyType } if leftType.symbol == c.globalThisSymbol { - globalSymbol := c.globalThisSymbol.Exports()[right.Text()] + globalSymbol := c.globalThisSymbol.Exports()[right.TextSymbolName()] if globalSymbol != nil && globalSymbol.Flags()&ast.SymbolFlagsBlockScoped != 0 { c.error(right, diagnostics.Property_0_does_not_exist_on_type_1, right.Text(), c.TypeToString(leftType)) } else if c.noImplicitAny { @@ -11705,10 +11706,10 @@ func (c *Checker) isMethodAccessForCall(node *ast.Node) bool { } // Lookup the private identifier lexically. -func (c *Checker) lookupSymbolForPrivateIdentifierDeclaration(propName string, location *ast.Node) *ast.Symbol { +func (c *Checker) lookupSymbolForPrivateIdentifierDeclaration(propName ast.SymbolName, location *ast.Node) *ast.Symbol { for containingClass := getContainingClassExcludingClassDecorators(location); containingClass != nil; containingClass = ast.GetContainingClass(containingClass) { symbol := containingClass.Symbol() - name := binder.GetSymbolNameForPrivateIdentifier(symbol, propName) + name := binder.GetSymbolNameForPrivateIdentifier(symbol, propName.Value()) prop := symbol.Members()[name] if prop != nil { return prop @@ -11778,19 +11779,19 @@ func (c *Checker) reportNonexistentProperty(propNode *ast.Node, containingType * var diagnostic *ast.Diagnostic if !ast.IsPrivateIdentifier(propNode) && containingType.flags&TypeFlagsUnion != 0 && containingType.flags&TypeFlagsPrimitive == 0 { for _, subtype := range containingType.Types() { - if c.getPropertyOfType(subtype, propNode.Text()) == nil && c.getApplicableIndexInfoForName(subtype, propNode.Text()) == nil { + if c.getPropertyOfType(subtype, propNode.TextSymbolName()) == nil && c.getApplicableIndexInfoForName(subtype, propNode.TextSymbolName()) == nil { diagnostic = NewDiagnosticChainForNode(diagnostic, propNode, diagnostics.Property_0_does_not_exist_on_type_1, scanner.DeclarationNameToString(propNode), c.TypeToString(subtype)) break } } } - if c.typeHasStaticProperty(propNode.Text(), containingType) { + if c.typeHasStaticProperty(propNode.TextSymbolName(), containingType) { propName := scanner.DeclarationNameToString(propNode) typeName := c.TypeToString(containingType) diagnostic = NewDiagnosticChainForNode(diagnostic, propNode, diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName, typeName, typeName+"."+propName) } else { promisedType := c.GetPromisedTypeOfPromise(containingType) - if promisedType != nil && c.getPropertyOfType(promisedType, propNode.Text()) != nil { + if promisedType != nil && c.getPropertyOfType(promisedType, propNode.TextSymbolName()) != nil { diagnostic = NewDiagnosticChainForNode(diagnostic, propNode, diagnostics.Property_0_does_not_exist_on_type_1, scanner.DeclarationNameToString(propNode), c.TypeToString(containingType)) diagnostic.AddRelatedInfo(NewDiagnosticForNode(propNode, diagnostics.Did_you_forget_to_use_await)) } else { @@ -11802,7 +11803,7 @@ func (c *Checker) reportNonexistentProperty(propNode *ast.Node, containingType * } else { suggestion := c.getSuggestedSymbolForNonexistentProperty(propNode, containingType) if suggestion != nil { - suggestedName := ast.SymbolName(suggestion) + suggestedName := ast.SymbolNameText(suggestion) message := core.IfElse(isUncheckedJS, diagnostics.Property_0_may_not_exist_on_type_1_Did_you_mean_2, diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2) diagnostic = NewDiagnosticChainForNode(diagnostic, propNode, message, missingProperty, container, suggestedName) if suggestion.ValueDeclaration() != nil { @@ -11847,7 +11848,7 @@ func (c *Checker) getSuggestedSymbolForNonexistentProperty(name *ast.Node, conta return c.isValidPropertyAccessForCompletions(parent, containingType, prop) }) } - return c.getSpellingSuggestionForName(name.Text(), slices.Values(props), ast.SymbolFlagsValue) + return c.getSpellingSuggestionForName(name.TextSymbolName(), slices.Values(props), ast.SymbolFlagsValue) } // Checks if an existing property access is valid for completions purposes. @@ -11894,7 +11895,7 @@ func hasCommonDomTypeName(t *Type) bool { return false } name := t.symbol.Name() - return name == "EventTarget" || name == "Node" || name == "Element" || strings.HasPrefix(name, "HTML") && strings.HasSuffix(name, "Element") + return name == ast.SymbolNameEventTarget || name == ast.SymbolNameNode || name == ast.SymbolNameElement || strings.HasPrefix(name.Value(), "HTML") && strings.HasSuffix(name.Value(), "Element") } func (c *Checker) checkAndReportErrorForExtendingInterface(errorLocation *ast.Node) bool { @@ -13010,7 +13011,7 @@ func (c *Checker) checkAssignmentOperator(left *ast.Node, operator ast.Kind, rig if c.checkReferenceExpression(left, diagnostics.The_left_hand_side_of_an_assignment_expression_must_be_a_variable_or_a_property_access, diagnostics.The_left_hand_side_of_an_assignment_expression_may_not_be_an_optional_property_access) { var headMessage *diagnostics.Message if c.exactOptionalPropertyTypes && ast.IsPropertyAccessExpression(left) && c.maybeTypeOfKind(rightType, TypeFlagsUndefined) { - target := c.getTypeOfPropertyOfType(c.getTypeOfExpression(left.Expression()), left.Name().Text()) + target := c.getTypeOfPropertyOfType(c.getTypeOfExpression(left.Expression()), left.Name().TextSymbolName()) if c.isExactOptionalPropertyMismatch(rightType, target) { headMessage = diagnostics.Type_0_is_not_assignable_to_type_1_with_exactOptionalPropertyTypes_Colon_true_Consider_adding_undefined_to_the_type_of_the_target } @@ -13610,7 +13611,7 @@ func (c *Checker) checkDeprecatedProperty(name *ast.Node, contextualType *Type) if contextualType == nil { return } - prop := c.getPropertyOfType(contextualType, name.Text()) + prop := c.getPropertyOfType(contextualType, name.TextSymbolName()) if prop == nil || len(prop.Declarations()) == 0 { return } @@ -13623,7 +13624,7 @@ func (c *Checker) checkSpreadPropOverrides(t *Type, props ast.SymbolTable, sprea for _, right := range c.getPropertiesOfType(t) { if right.Flags()&ast.SymbolFlagsOptional == 0 && right.CheckFlags()&ast.CheckFlagsPartial == 0 { if left := props[right.Name()]; left != nil { - diagnostic := c.error(left.ValueDeclaration(), diagnostics.X_0_is_specified_more_than_once_so_this_usage_will_be_overwritten, left.Name()) + diagnostic := c.error(left.ValueDeclaration(), diagnostics.X_0_is_specified_more_than_once_so_this_usage_will_be_overwritten, left.Name().Value()) diagnostic.AddRelatedInfo(NewDiagnosticForNode(spread, diagnostics.This_spread_always_overwrites_this_property)) } } @@ -13688,7 +13689,7 @@ func (c *Checker) getSpreadType(left *Type, right *Type, symbol *ast.Symbol, obj return c.getIntersectionType([]*Type{left, right}) } members := make(ast.SymbolTable) - var skippedPrivateMembers collections.Set[string] + var skippedPrivateMembers collections.Set[ast.SymbolName] var indexInfos []*IndexInfo if left == c.emptyObjectType { indexInfos = c.getIndexInfosOfType(right) @@ -14099,8 +14100,8 @@ func (c *Checker) isReadonlyAssignmentDeclaration(node *ast.Node) bool { return false } propertyDescriptorType := c.checkExpressionCached(node.Arguments()[2]) - if valueType := c.getTypeOfPropertyOfType(propertyDescriptorType, "value"); valueType != nil { - if writableProp := c.getPropertyOfType(propertyDescriptorType, "writable"); writableProp != nil { + if valueType := c.getTypeOfPropertyOfType(propertyDescriptorType, ast.SymbolNameValue); valueType != nil { + if writableProp := c.getPropertyOfType(propertyDescriptorType, ast.SymbolNameWritable); writableProp != nil { var writableType *Type if writableProp.ValueDeclaration() != nil && ast.IsPropertyAssignment(writableProp.ValueDeclaration()) { writableType = c.checkExpression(writableProp.ValueDeclaration().Initializer()) @@ -14111,7 +14112,7 @@ func (c *Checker) isReadonlyAssignmentDeclaration(node *ast.Node) bool { } return true } - return c.getTypeOfPropertyOfType(propertyDescriptorType, "set") == nil + return c.getTypeOfPropertyOfType(propertyDescriptorType, ast.SymbolNameSetProperty) == nil } func (c *Checker) isReadonlySymbol(symbol *ast.Symbol) bool { @@ -14160,7 +14161,7 @@ func (c *Checker) getResolvedSymbol(node *ast.Node) *ast.Symbol { if links.resolvedSymbol == nil { var symbol *ast.Symbol if !ast.NodeIsMissing(node) { - symbol = c.resolveName(node, node.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, + symbol = c.resolveName(node, node.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, c.getCannotFindNameDiagnosticForName(node), !ast.IsWriteOnlyAccess(node), false /*excludeGlobals*/) } links.resolvedSymbol = core.OrElse(symbol, c.unknownSymbol) @@ -14177,7 +14178,7 @@ func (c *Checker) getReferencedValueOrAliasSymbol(reference *ast.Node) *ast.Symb if resolvedSymbol != nil && resolvedSymbol != c.unknownSymbol { return resolvedSymbol } - return c.resolveName(reference, reference.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias, nil, false /*isUse*/, false /*excludeGlobals*/) + return c.resolveName(reference, reference.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias, nil, false /*isUse*/, false /*excludeGlobals*/) } func (c *Checker) getCannotFindNameDiagnosticForName(node *ast.Node) *diagnostics.Message { @@ -14335,7 +14336,7 @@ func (c *Checker) hasParseDiagnostics(sourceFile *ast.SourceFile) bool { return len(sourceFile.Diagnostics()) > 0 } -func (c *Checker) newSymbol(flags ast.SymbolFlags, name string) *ast.Symbol { +func (c *Checker) newSymbol(flags ast.SymbolFlags, name ast.SymbolName) *ast.Symbol { c.SymbolCount++ result := c.symbolWithDataArena.New().Initialize() result.SetFlags(flags | ast.SymbolFlagsTransient) @@ -14351,19 +14352,19 @@ func (c *Checker) newSharedDataSymbol(symbol *ast.Symbol) *ast.Symbol { return result } -func (c *Checker) newSymbolEx(flags ast.SymbolFlags, name string, checkFlags ast.CheckFlags) *ast.Symbol { +func (c *Checker) newSymbolEx(flags ast.SymbolFlags, name ast.SymbolName, checkFlags ast.CheckFlags) *ast.Symbol { result := c.newSymbol(flags, name) result.SetCheckFlags(checkFlags) return result } -func (c *Checker) newParameter(name string, t *Type) *ast.Symbol { +func (c *Checker) newParameter(name ast.SymbolName, t *Type) *ast.Symbol { symbol := c.newSymbol(ast.SymbolFlagsFunctionScopedVariable, name) c.valueSymbolLinks.Get(symbol).resolvedType = t return symbol } -func (c *Checker) newProperty(name string, t *Type) *ast.Symbol { +func (c *Checker) newProperty(name ast.SymbolName, t *Type) *ast.Symbol { symbol := c.newSymbol(ast.SymbolFlagsProperty, name) c.valueSymbolLinks.Get(symbol).resolvedType = t return symbol @@ -14804,7 +14805,7 @@ func (c *Checker) getTargetOfImportClause(node *ast.Node) *ast.Symbol { alias := c.getSymbolOfDeclaration(node) links := c.aliasSymbolLinks.Get(alias) if links.immediateTarget == nil { - symbol := c.newSymbol(ast.SymbolFlagsFunctionScopedVariable, node.Name().Text()) + symbol := c.newSymbol(ast.SymbolFlagsFunctionScopedVariable, node.Name().TextSymbolName()) symbol.SetDeclarations(alias.Declarations()) c.valueSymbolLinks.Get(symbol).resolvedType = c.getGlobalAbstractModuleSourceType() links.immediateTarget = symbol @@ -14906,7 +14907,7 @@ func (c *Checker) reportNonDefaultExport(moduleSymbol *ast.Symbol, node *ast.Nod } } -func (c *Checker) resolveExportByName(moduleSymbol *ast.Symbol, name string, sourceNode *ast.Node, dontResolveAlias bool) *ast.Symbol { +func (c *Checker) resolveExportByName(moduleSymbol *ast.Symbol, name ast.SymbolName, sourceNode *ast.Node, dontResolveAlias bool) *ast.Symbol { exportValue := moduleSymbol.Exports()[ast.InternalSymbolNameExportEquals] var exportSymbol *ast.Symbol if exportValue != nil { @@ -14995,9 +14996,9 @@ func (c *Checker) getExternalModuleMember(node *ast.Node, specifier *ast.Node, d var symbolFromVariable *ast.Symbol // First check if module was specified with "export=". If so, get the member from the resolved type if moduleSymbol != nil && moduleSymbol.Exports()[ast.InternalSymbolNameExportEquals] != nil { - symbolFromVariable = c.getPropertyOfTypeEx(c.getTypeOfSymbol(targetSymbol), nameText, true /*skipObjectFunctionPropertyAugment*/, false /*includeTypeOnlyMembers*/) + symbolFromVariable = c.getPropertyOfTypeEx(c.getTypeOfSymbol(targetSymbol), ast.MakeSymbolName(nameText), true /*skipObjectFunctionPropertyAugment*/, false /*includeTypeOnlyMembers*/) } else { - symbolFromVariable = c.getPropertyOfVariable(targetSymbol, nameText) + symbolFromVariable = c.getPropertyOfVariable(targetSymbol, ast.MakeSymbolName(nameText)) } // if symbolFromVariable is export - get its final target symbolFromVariable = c.resolveSymbolEx(symbolFromVariable, dontResolveAlias) @@ -15006,8 +15007,8 @@ func (c *Checker) getExternalModuleMember(node *ast.Node, specifier *ast.Node, d // For `export =` modules, supplemental type/namespace exports live on the original module symbol. exportContainer = moduleSymbol } - symbolFromModule := c.getExportOfModule(exportContainer, nameText, specifier, dontResolveAlias) - if symbolFromModule == nil && nameText == ast.InternalSymbolNameDefault { + symbolFromModule := c.getExportOfModule(exportContainer, ast.MakeSymbolName(nameText), specifier, dontResolveAlias) + if symbolFromModule == nil && ast.MakeSymbolName(nameText) == ast.InternalSymbolNameDefault { file := core.Find(moduleSymbol.Declarations(), ast.IsSourceFile) if c.isOnlyImportableAsDefault(moduleSpecifier, moduleSymbol, importAttributesType) || c.canHaveSyntheticDefault(file, moduleSymbol, dontResolveAlias, moduleSpecifier) { symbolFromModule = c.resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias) @@ -15023,7 +15024,7 @@ func (c *Checker) getExternalModuleMember(node *ast.Node, specifier *ast.Node, d symbol = c.combineValueAndTypeSymbols(symbolFromVariable, symbolFromModule) } } - if ast.IsImportOrExportSpecifier(specifier) && c.isOnlyImportableAsDefault(moduleSpecifier, moduleSymbol, importAttributesType) && nameText != ast.InternalSymbolNameDefault { + if ast.IsImportOrExportSpecifier(specifier) && c.isOnlyImportableAsDefault(moduleSpecifier, moduleSymbol, importAttributesType) && ast.MakeSymbolName(nameText) != ast.InternalSymbolNameDefault { c.error(name, diagnostics.Named_imports_from_a_JSON_file_into_an_ECMAScript_module_are_not_allowed_when_module_is_set_to_0, c.moduleKind.String()) } else if symbol == nil { c.errorNoModuleMemberSymbol(moduleSymbol, targetSymbol, node, name) @@ -15034,7 +15035,7 @@ func (c *Checker) getExternalModuleMember(node *ast.Node, specifier *ast.Node, d return nil } -func (c *Checker) getPropertyOfVariable(symbol *ast.Symbol, name string) *ast.Symbol { +func (c *Checker) getPropertyOfVariable(symbol *ast.Symbol, name ast.SymbolName) *ast.Symbol { if symbol.Flags()&ast.SymbolFlagsVariable != 0 { typeAnnotation := symbol.ValueDeclaration().Type() if typeAnnotation != nil { @@ -15085,7 +15086,7 @@ func (c *Checker) combineValueAndTypeSymbols(valueSymbol *ast.Symbol, typeSymbol return result } -func (c *Checker) getExportOfModule(symbol *ast.Symbol, nameText string, specifier *ast.Node, dontResolveAlias bool) *ast.Symbol { +func (c *Checker) getExportOfModule(symbol *ast.Symbol, nameText ast.SymbolName, specifier *ast.Node, dontResolveAlias bool) *ast.Symbol { if symbol.Flags()&ast.SymbolFlagsModule != 0 { exportSymbol := c.getExportsOfSymbol(symbol)[nameText] resolved := c.resolveSymbolEx(exportSymbol, dontResolveAlias) @@ -15154,7 +15155,7 @@ func (c *Checker) canHaveSyntheticDefault(file *ast.Node, moduleSymbol *ast.Symb } // It _might_ still be incorrect to assume there is no __esModule marker on the import at runtime, even if there is no `default` member // So we check a bit more, - if c.resolveExportByName(moduleSymbol, "__esModule", nil /*sourceNode*/, dontResolveAlias) != nil { + if c.resolveExportByName(moduleSymbol, ast.SymbolNameESModule, nil /*sourceNode*/, dontResolveAlias) != nil { // If there is an `__esModule` specified in the declaration (meaning someone explicitly added it or wrote it in their code), // it definitely is a module and does not have a synthetic default return false @@ -15170,7 +15171,7 @@ func (c *Checker) canHaveSyntheticDefault(file *ast.Node, moduleSymbol *ast.Symb } // JS files have a synthetic default if they do not contain ES2015+ module syntax (export = is not valid in js) _and_ do not have an __esModule marker - return (file.AsSourceFile().ExternalModuleIndicator == nil || file.AsSourceFile().ExternalModuleIndicator == file) && c.resolveExportByName(moduleSymbol, "__esModule", nil /*sourceNode*/, dontResolveAlias) == nil + return (file.AsSourceFile().ExternalModuleIndicator == nil || file.AsSourceFile().ExternalModuleIndicator == file) && c.resolveExportByName(moduleSymbol, ast.SymbolNameESModule, nil /*sourceNode*/, dontResolveAlias) == nil } func (c *Checker) getEmitSyntaxForModuleSpecifierExpression(usage *ast.Node) core.ResolutionMode { @@ -15208,7 +15209,7 @@ func (c *Checker) errorNoModuleMemberSymbol(moduleSymbol *ast.Symbol, targetSymb func (c *Checker) reportNonExportedMember(name *ast.Node, declarationName string, moduleSymbol *ast.Symbol, moduleName string) { var localSymbol *ast.Symbol if locals := moduleSymbol.ValueDeclaration().Locals(); locals != nil { - localSymbol = locals[name.Text()] + localSymbol = locals[name.TextSymbolName()] } exports := moduleSymbol.Exports() if localSymbol != nil { @@ -15789,8 +15790,8 @@ func (c *Checker) tryResolvePatternAmbientModule(resolvedSymbol *ast.Symbol, mod }) if len(candidates) > 0 { - augmentation := c.patternAmbientModuleAugmentations[moduleReference] - augmentationTarget := c.patternAmbientModuleAugmentationTargets[moduleReference] + augmentation := c.patternAmbientModuleAugmentations[ast.MakeSymbolName(moduleReference)] + augmentationTarget := c.patternAmbientModuleAugmentationTargets[ast.MakeSymbolName(moduleReference)] if len(candidates) == 1 { mergedCandidate := c.getMergedSymbol(candidates[0].Symbol) @@ -15933,7 +15934,7 @@ func (c *Checker) tryFindAmbientModule(moduleName string, withAugmentations bool if tspath.IsExternalModuleNameRelative(moduleName) { return nil } - symbol := c.getSymbol(c.globals, "\""+moduleName+"\"", ast.SymbolFlagsValueModule) + symbol := c.getSymbol(c.globals, ast.MakeSymbolName("\""+moduleName+"\""), ast.SymbolFlagsValueModule) // merged symbol is module declaration symbol combined with all augmentations if withAugmentations { return c.getMergedSymbol(symbol) @@ -16087,7 +16088,7 @@ func (c *Checker) isCommonJSRequire(node *ast.Node) bool { panic("Expected identifier for require call") } // Make sure require is not a local function - resolvedRequire := c.resolveName(node.Expression(), node.Expression().Text(), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + resolvedRequire := c.resolveName(node.Expression(), node.Expression().TextSymbolName(), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if resolvedRequire == c.requireSymbol { return true } @@ -16197,19 +16198,19 @@ func (c *Checker) resolveEntityName(name *ast.Node, meaning ast.SymbolFlags, ign resolveLocation = name } if meaning == ast.SymbolFlagsNamespace { - symbol = c.getMergedSymbol(c.resolveName(resolveLocation, name.Text(), meaning, nil, true /*isUse*/, false /*excludeGlobals*/)) + symbol = c.getMergedSymbol(c.resolveName(resolveLocation, name.TextSymbolName(), meaning, nil, true /*isUse*/, false /*excludeGlobals*/)) if symbol == nil { - alias := c.getMergedSymbol(c.resolveName(resolveLocation, name.Text(), ast.SymbolFlagsAlias, nil, true /*isUse*/, false /*excludeGlobals*/)) + alias := c.getMergedSymbol(c.resolveName(resolveLocation, name.TextSymbolName(), ast.SymbolFlagsAlias, nil, true /*isUse*/, false /*excludeGlobals*/)) if alias != nil && alias.Name() == ast.InternalSymbolNameExportEquals { // resolve typedefs exported from commonjs, stored on the module symbol symbol = alias.Parent() } } if symbol == nil && message != nil { - c.resolveName(resolveLocation, name.Text(), meaning, message, true /*isUse*/, false /*excludeGlobals*/) + c.resolveName(resolveLocation, name.TextSymbolName(), meaning, message, true /*isUse*/, false /*excludeGlobals*/) } } else { - symbol = c.getMergedSymbol(c.resolveName(resolveLocation, name.Text(), meaning, message, true /*isUse*/, false /*excludeGlobals*/)) + symbol = c.getMergedSymbol(c.resolveName(resolveLocation, name.TextSymbolName(), meaning, message, true /*isUse*/, false /*excludeGlobals*/)) } case ast.KindQualifiedName: qualified := name.AsQualifiedName() @@ -16257,10 +16258,10 @@ func (c *Checker) resolveQualifiedName(name *ast.Node, left *ast.Node, right *as } } text := right.Text() - symbol := c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(namespace), text, meaning)) + symbol := c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(namespace), ast.MakeSymbolName(text), meaning)) if symbol == nil && namespace.Flags()&ast.SymbolFlagsAlias != 0 { // `namespace` can be resolved further if there was a symbol merge with a re-export - symbol = c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(c.resolveAlias(namespace)), text, meaning)) + symbol = c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(c.resolveAlias(namespace)), ast.MakeSymbolName(text), meaning)) } if symbol == nil { if !ignoreErrors { @@ -16282,7 +16283,7 @@ func (c *Checker) resolveQualifiedName(name *ast.Node, left *ast.Node, right *as } if meaning&ast.SymbolFlagsNamespace != 0 { if ast.IsQualifiedName(name.Parent) { - exportedTypeSymbol := c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(namespace), text, ast.SymbolFlagsType)) + exportedTypeSymbol := c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(namespace), ast.MakeSymbolName(text), ast.SymbolFlagsType)) if exportedTypeSymbol != nil { qualified := name.Parent.AsQualifiedName() c.error(qualified.Right, diagnostics.Cannot_access_0_1_because_0_is_a_type_but_not_a_namespace_Did_you_mean_to_retrieve_the_type_of_the_property_1_in_0_with_0_1, c.symbolToString(exportedTypeSymbol), qualified.Right.Text()) @@ -16298,14 +16299,14 @@ func (c *Checker) resolveQualifiedName(name *ast.Node, left *ast.Node, right *as func (c *Checker) tryGetQualifiedNameAsValue(node *ast.Node) *ast.Symbol { id := ast.GetFirstIdentifier(node) - symbol := c.resolveName(id, id.Text(), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + symbol := c.resolveName(id, id.TextSymbolName(), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if symbol == nil { return nil } n := id for ast.IsQualifiedName(n.Parent) { t := c.getTypeOfSymbol(symbol) - symbol = c.getPropertyOfType(t, n.Parent.AsQualifiedName().Right.Text()) + symbol = c.getPropertyOfType(t, n.Parent.AsQualifiedName().Right.TextSymbolName()) if symbol == nil { return nil } @@ -16315,7 +16316,7 @@ func (c *Checker) tryGetQualifiedNameAsValue(node *ast.Node) *ast.Symbol { } func (c *Checker) getSuggestedSymbolForNonexistentModule(name *ast.Node, targetModule *ast.Symbol) *ast.Symbol { - return c.getSpellingSuggestionForName(name.Text(), maps.Values(c.getExportsOfModule(targetModule)), ast.SymbolFlagsModuleMember) + return c.getSpellingSuggestionForName(name.TextSymbolName(), maps.Values(c.getExportsOfModule(targetModule)), ast.SymbolFlagsModuleMember) } func (c *Checker) getFullyQualifiedName(symbol *ast.Symbol, containingLocation *ast.Node) string { @@ -16451,12 +16452,12 @@ func (c *Checker) lateBindMember(parent *ast.Symbol, earlySymbols ast.SymbolTabl } name := memberName if t.flags&TypeFlagsUniqueESSymbol != 0 { - name = scanner.DeclarationNameToString(declName) + name = ast.MakeSymbolName(scanner.DeclarationNameToString(declName)) } for _, d := range declarations { - c.error(core.OrElse(ast.GetNameOfDeclaration(d), d), diagnostics.Duplicate_identifier_0, name) + c.error(core.OrElse(ast.GetNameOfDeclaration(d), d), diagnostics.Duplicate_identifier_0, name.Value()) } - c.error(core.OrElse(declName, decl), diagnostics.Duplicate_identifier_0, name) + c.error(core.OrElse(declName, decl), diagnostics.Duplicate_identifier_0, name.Value()) if lateSymbol.Flags()&ast.SymbolFlagsAccessor != 0 && lateSymbol.Flags()&ast.SymbolFlagsAccessor != symbolFlags&ast.SymbolFlagsAccessor { lateSymbol.SetFlags(lateSymbol.Flags() | ast.SymbolFlagsAccessor) } @@ -16551,11 +16552,11 @@ type ExportCollision struct { exportsWithDuplicate []*ast.Node } -type ExportCollisionTable = map[string]*ExportCollision +type ExportCollisionTable = map[ast.SymbolName]*ExportCollision -func (c *Checker) getExportsOfModuleWorker(moduleSymbol *ast.Symbol) (exports ast.SymbolTable, typeOnlyExportStarMap map[string]*ast.Node) { +func (c *Checker) getExportsOfModuleWorker(moduleSymbol *ast.Symbol) (exports ast.SymbolTable, typeOnlyExportStarMap map[ast.SymbolName]*ast.Node) { var visitedSymbols []*ast.Symbol - nonTypeOnlyNames := collections.NewSetWithSizeHint[string](len(moduleSymbol.Exports())) + nonTypeOnlyNames := collections.NewSetWithSizeHint[ast.SymbolName](len(moduleSymbol.Exports())) // The ES6 spec permits export * declarations in a module to circularly reference the module itself. For example, // module 'a' can 'export * from "b"' and 'b' can 'export * from "a"' without error. var visit func(*ast.Symbol, *ast.Node, bool) ast.SymbolTable @@ -16589,14 +16590,14 @@ func (c *Checker) getExportsOfModuleWorker(moduleSymbol *ast.Symbol) (exports as continue } for _, node := range s.exportsWithDuplicate { - c.addDiagnostic(createDiagnosticForNode(node, diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, s.specifierText, id)) + c.addDiagnostic(createDiagnosticForNode(node, diagnostics.Module_0_has_already_exported_a_member_named_1_Consider_explicitly_re_exporting_to_resolve_the_ambiguity, s.specifierText, id.Value())) } } c.extendExportSymbols(symbols, nestedSymbols, nil, nil) } if exportStar != nil && exportStar.IsTypeOnly() { if typeOnlyExportStarMap == nil { - typeOnlyExportStarMap = make(map[string]*ast.Node) + typeOnlyExportStarMap = make(map[ast.SymbolName]*ast.Node) } for name := range symbols { typeOnlyExportStarMap[name] = exportStar @@ -16732,7 +16733,7 @@ func (c *Checker) resolveAliasWithDeprecationCheck(symbol *ast.Symbol, location } if len(target.Declarations()) != 0 { if c.isDeprecatedSymbol(target) { - c.addDeprecatedSuggestion(location, target.Declarations(), target.Name()) + c.addDeprecatedSuggestion(location, target.Declarations(), target.Name().Value()) break } else { if symbol == targetSymbol { @@ -17006,7 +17007,7 @@ func (c *Checker) getTypeOfVariableOrParameterOrPropertyWorker(symbol *ast.Symbo return c.reportCircularityError(symbol) } if symbol.Flags()&ast.SymbolFlagsModuleExports != 0 { - if symbol.Name() == "exports" { + if symbol.Name() == ast.SymbolNameExports { return c.getTypeOfSymbol(c.resolveExternalModuleSymbol(symbol.ValueDeclaration().Symbol(), false /*dontResolveAlias*/)) } return c.newAnonymousType(symbol, symbol.Members(), nil, nil, nil) @@ -17256,7 +17257,7 @@ func (c *Checker) padObjectLiteralType(t *Type, pattern *ast.Node) *Type { return result } -func (c *Checker) getPropertyNameFromBindingElement(e *ast.Node) string { +func (c *Checker) getPropertyNameFromBindingElement(e *ast.Node) ast.SymbolName { exprType := c.getLiteralTypeFromPropertyName(e.PropertyNameOrName()) if isTypeUsableAsPropertyName(exprType) { return getPropertyNameFromType(exprType) @@ -18290,7 +18291,7 @@ func (c *Checker) getSyntheticElementAccess(node *ast.Node) *ast.Node { parentAccess := c.getParentElementAccess(node) if parentAccess != nil && getFlowNodeOfNode(parentAccess) != nil { if propName, ok := c.getDestructuringPropertyName(node); ok { - literal := c.factory.NewStringLiteral(propName, ast.TokenFlagsNone) + literal := c.factory.NewStringLiteral(propName.Value(), ast.TokenFlagsNone) literal.Loc = node.Loc lhsExpr := parentAccess if !ast.IsLeftHandSideExpression(parentAccess) { @@ -18601,15 +18602,15 @@ func (c *Checker) containsSameNamedThisProperty(thisProperty *ast.Node, expressi func (c *Checker) getTypeFromPropertyDescriptor(node *ast.Node) *Type { objectLiteralType := c.checkExpressionCached(node) - if valueType := c.getTypeOfPropertyOfType(objectLiteralType, "value"); valueType != nil { + if valueType := c.getTypeOfPropertyOfType(objectLiteralType, ast.SymbolNameValue); valueType != nil { return valueType } - if getFunc := c.getTypeOfPropertyOfType(objectLiteralType, "get"); getFunc != nil { + if getFunc := c.getTypeOfPropertyOfType(objectLiteralType, ast.SymbolNameGetProperty); getFunc != nil { if getSig := c.getSingleCallSignature(getFunc); getSig != nil { return c.getReturnTypeOfSignature(getSig) } } - if setFunc := c.getTypeOfPropertyOfType(objectLiteralType, "set"); setFunc != nil { + if setFunc := c.getTypeOfPropertyOfType(objectLiteralType, ast.SymbolNameSetProperty); setFunc != nil { if setSig := c.getSingleCallSignature(setFunc); setSig != nil { return c.getTypeOfFirstParameterOfSignature(setSig) } @@ -18883,13 +18884,13 @@ func (c *Checker) getWidenedProperty(prop *ast.Symbol, context *WideningContext) return c.createSymbolWithType(prop, widened) } -func (w *WideningContext) getChildContext(propertyName string) *WideningContext { +func (w *WideningContext) getChildContext(propertyName ast.SymbolName) *WideningContext { if cached := w.childContexts[propertyName]; cached != nil { return cached } result := &WideningContext{parent: w, propertyName: propertyName} if w.childContexts == nil { - w.childContexts = make(map[string]*WideningContext) + w.childContexts = make(map[ast.SymbolName]*WideningContext) } w.childContexts[propertyName] = result return result @@ -18897,7 +18898,7 @@ func (w *WideningContext) getChildContext(propertyName string) *WideningContext func (c *Checker) getPropertiesOfContext(context *WideningContext) []*ast.Symbol { if context.resolvedProperties == nil { - var names collections.OrderedMap[string, *ast.Symbol] + var names collections.OrderedMap[ast.SymbolName, *ast.Symbol] for _, t := range c.getSiblingsOfContext(context) { if isObjectLiteralType(t) && t.objectFlags&ObjectFlagsContainsSpread == 0 { for _, prop := range c.getPropertiesOfType(t) { @@ -19136,7 +19137,7 @@ func (c *Checker) isVarConstLike(node *ast.Node) bool { return blockScopeKind == ast.NodeFlagsConst || blockScopeKind == ast.NodeFlagsUsing || blockScopeKind == ast.NodeFlagsAwaitUsing } -func (c *Checker) getEffectivePropertyNameForPropertyNameNode(node *ast.PropertyName) (string, bool) { +func (c *Checker) getEffectivePropertyNameForPropertyNameNode(node *ast.PropertyName) (ast.SymbolName, bool) { name := ast.GetPropertyNameForPropertyNameNode(node) switch { case name != ast.InternalSymbolNameMissing: @@ -19152,21 +19153,21 @@ func (c *Checker) getEffectivePropertyNameForPropertyNameNode(node *ast.Property links.hasName = &exists return name, exists } - return "", false + return ast.EmptySymbolName, false } -func (c *Checker) tryGetNameFromType(t *Type) (name string, ok bool) { +func (c *Checker) tryGetNameFromType(t *Type) (name ast.SymbolName, ok bool) { switch { case t.flags&TypeFlagsUniqueESSymbol != 0: return t.AsUniqueESSymbolType().name, true case t.flags&TypeFlagsStringLiteral != 0: s := getStringLiteralValue(t) - return s, true + return ast.MakeSymbolName(s), true case t.flags&TypeFlagsNumberLiteral != 0: s := getNumberLiteralValue(t).String() - return s, true + return ast.MakeSymbolName(s), true default: - return "", false + return ast.EmptySymbolName, false } } @@ -19297,7 +19298,7 @@ func (c *Checker) getPropertiesOfObjectType(t *Type) []*ast.Symbol { func (c *Checker) getPropertiesOfUnionOrIntersectionType(t *Type) []*ast.Symbol { d := t.AsUnionOrIntersectionType() if d.resolvedProperties == nil { - var checked collections.Set[string] + var checked collections.Set[ast.SymbolName] props := []*ast.Symbol{} for _, current := range d.types { for _, prop := range c.getPropertiesOfType(current) { @@ -19320,7 +19321,7 @@ func (c *Checker) getPropertiesOfUnionOrIntersectionType(t *Type) []*ast.Symbol return d.resolvedProperties } -func (c *Checker) getPropertyOfType(t *Type, name string) *ast.Symbol { +func (c *Checker) getPropertyOfType(t *Type, name ast.SymbolName) *ast.Symbol { return c.getPropertyOfTypeEx(t, name, false /*skipObjectFunctionPropertyAugment*/, false /*includeTypeOnlyMembers*/) } @@ -19332,7 +19333,7 @@ func (c *Checker) getPropertyOfType(t *Type, name string) *ast.Symbol { * @param type a type to look up property from * @param name a name of property to look up in a given type */ -func (c *Checker) getPropertyOfTypeEx(t *Type, name string, skipObjectFunctionPropertyAugment bool, includeTypeOnlyMembers bool) *ast.Symbol { +func (c *Checker) getPropertyOfTypeEx(t *Type, name ast.SymbolName, skipObjectFunctionPropertyAugment bool, includeTypeOnlyMembers bool) *ast.Symbol { t = c.getReducedApparentType(t) switch { case t.flags&TypeFlagsObject != 0: @@ -19384,7 +19385,7 @@ func (c *Checker) getPropertyOfTypeEx(t *Type, name string, skipObjectFunctionPr } // Return the type of the given property in the given type, or nil if no such property exists -func (c *Checker) getTypeOfPropertyOfType(t *Type, name string) *Type { +func (c *Checker) getTypeOfPropertyOfType(t *Type, name ast.SymbolName) *Type { prop := c.getPropertyOfType(t, name) if prop != nil { return c.getTypeOfSymbol(prop) @@ -19448,11 +19449,11 @@ func (c *Checker) getApplicableIndexInfo(t *Type, keyType *Type) *IndexInfo { return c.findApplicableIndexInfo(c.getIndexInfosOfType(t), keyType) } -func (c *Checker) getApplicableIndexInfoForName(t *Type, name string) *IndexInfo { +func (c *Checker) getApplicableIndexInfoForName(t *Type, name ast.SymbolName) *IndexInfo { if isLateBoundName(name) { return c.getApplicableIndexInfo(t, c.esSymbolType) } - return c.getApplicableIndexInfo(t, c.getStringLiteralType(name)) + return c.getApplicableIndexInfo(t, c.getStringLiteralType(name.Value())) } func (c *Checker) findApplicableIndexInfo(indexInfos []*IndexInfo, keyType *Type) *IndexInfo { @@ -20186,7 +20187,7 @@ func (c *Checker) isSymbolWithSymbolName(symbol *ast.Symbol) bool { } func (c *Checker) isSymbolWithNumericName(symbol *ast.Symbol) bool { - if isNumericLiteralName(symbol.Name()) { + if isNumericLiteralName(symbol.Name().Value()) { return true } if len(symbol.Declarations()) != 0 { @@ -21012,7 +21013,7 @@ func (c *Checker) checkIfExpressionRefinesAnyParameter(fn *ast.Node, expr *ast.N } trueType := c.checkIfExpressionRefinesParameter(fn, expr, param, initType) if trueType != nil { - return c.newTypePredicate(TypePredicateKindIdentifier, param.Name().Text(), int32(i), trueType) + return c.newTypePredicate(TypePredicateKindIdentifier, param.Name().TextSymbolName(), int32(i), trueType) } } return nil @@ -21511,7 +21512,7 @@ func (c *Checker) resolveUnionTypeMembers(t *Type) { func (c *Checker) getArrayMemberCallSignatures(t *Type) []*Signature { // Check if union is exclusively instantiations of a member of the global Array or ReadonlyArray type. - var memberName string + var memberName ast.SymbolName for i, t := range t.Types() { if t.objectFlags&ObjectFlagsInstantiated == 0 || t.symbol == nil || t.symbol.Parent() == nil || !c.isArrayOrTupleSymbol(t.symbol.Parent()) { return nil @@ -21685,24 +21686,24 @@ func (c *Checker) combineUnionOrIntersectionParameters(left *Signature, right *S combinedParamType := c.getUnionOrIntersectionType([]*Type{longestParamType, shorterParamType}, !isUnion, UnionReductionLiteral) isRestParam := eitherHasEffectiveRest && !needsExtraRestElement && i == (longestCount-1) isOptional := i >= c.getMinArgumentCount(longest) && i >= c.getMinArgumentCount(shorter) - var leftName, rightName string + leftName, rightName := ast.EmptySymbolName, ast.EmptySymbolName if i < leftCount { leftName = c.getParameterNameAtPosition(left, i) } if i < rightCount { rightName = c.getParameterNameAtPosition(right, i) } - var paramName string + paramName := ast.EmptySymbolName switch { case leftName == rightName: paramName = leftName - case leftName == "": + case leftName == ast.EmptySymbolName: paramName = rightName - case rightName == "": + case rightName == ast.EmptySymbolName: paramName = leftName } - if paramName == "" { - paramName = "arg" + strconv.Itoa(i) + if paramName == ast.EmptySymbolName { + paramName = ast.MakeSymbolName("arg" + strconv.Itoa(i)) } paramSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable|core.IfElse(isOptional && !isRestParam, ast.SymbolFlagsOptional, 0), paramName, core.IfElse(isRestParam, ast.CheckFlagsRestParameter, core.IfElse(isOptional, ast.CheckFlagsOptionalParameter, 0))) @@ -21715,7 +21716,7 @@ func (c *Checker) combineUnionOrIntersectionParameters(left *Signature, right *S params[i] = paramSymbol } if needsExtraRestElement { - restParamSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, "args", ast.CheckFlagsRestParameter) + restParamSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, ast.SymbolNameArgs, ast.CheckFlagsRestParameter) links := c.valueSymbolLinks.Get(restParamSymbol) links.resolvedType = c.createArrayType(c.getTypeAtPosition(shorter, longestCount)) if shorter == right { @@ -21841,7 +21842,7 @@ func (c *Checker) includeMixinType(t *Type, types []*Type, mixinFlags []bool, in * If the given type is an object type and that type has a property by the given name, * return the symbol for that property. Otherwise return undefined. */ -func (c *Checker) getPropertyOfObjectType(t *Type, name string) *ast.Symbol { +func (c *Checker) getPropertyOfObjectType(t *Type, name ast.SymbolName) *ast.Symbol { if t.flags&TypeFlagsObject != 0 { resolved := c.resolveStructuredTypeMembers(t) symbol := resolved.members[name] @@ -21852,7 +21853,7 @@ func (c *Checker) getPropertyOfObjectType(t *Type, name string) *ast.Symbol { return nil } -func (c *Checker) getPropertyOfUnionOrIntersectionType(t *Type, name string, skipObjectFunctionPropertyAugment bool) *ast.Symbol { +func (c *Checker) getPropertyOfUnionOrIntersectionType(t *Type, name ast.SymbolName, skipObjectFunctionPropertyAugment bool) *ast.Symbol { prop := c.getUnionOrIntersectionProperty(t, name, skipObjectFunctionPropertyAugment) // We need to filter out partial properties in union types if prop != nil && prop.CheckFlags()&ast.CheckFlagsReadPartial != 0 { @@ -21866,7 +21867,7 @@ func (c *Checker) getPropertyOfUnionOrIntersectionType(t *Type, name string, ski // constituents, in which case the isPartial flag is set when the containing type is union type. We need // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. -func (c *Checker) getUnionOrIntersectionProperty(t *Type, name string, skipObjectFunctionPropertyAugment bool) *ast.Symbol { +func (c *Checker) getUnionOrIntersectionProperty(t *Type, name ast.SymbolName, skipObjectFunctionPropertyAugment bool) *ast.Symbol { var cache ast.SymbolTable if skipObjectFunctionPropertyAugment { cache = ast.GetSymbolTable(&t.AsUnionOrIntersectionType().propertyCacheWithoutFunctionPropertyAugment) @@ -21890,7 +21891,7 @@ func (c *Checker) getUnionOrIntersectionProperty(t *Type, name string, skipObjec return prop } -func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name string, skipObjectFunctionPropertyAugment bool) *ast.Symbol { +func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name ast.SymbolName, skipObjectFunctionPropertyAugment bool) *ast.Symbol { propFlags := ast.SymbolFlagsNone var singleProp *ast.Symbol var propSet collections.OrderedSet[*ast.Symbol] @@ -22581,7 +22582,7 @@ func (c *Checker) isDeclarationContainedBy(symbol *ast.Symbol, container *ast.Sy return false } -func (c *Checker) isNamedMember(symbol *ast.Symbol, id string) bool { +func (c *Checker) isNamedMember(symbol *ast.Symbol, id ast.SymbolName) bool { return !isReservedMemberName(id) && c.symbolIsValue(symbol) } @@ -22659,7 +22660,7 @@ func (c *Checker) getCircularTypeNames() []string { if t.alias != nil { symbol = t.alias.symbol } - if symbol != nil && len(symbol.Name()) != 0 && symbol.Name()[0] != '\xFE' { + if symbol != nil && len(symbol.Name().Value()) != 0 && symbol.Name().Value()[0] != '\xFE' { if name := c.SymbolToString(symbol); !slices.Contains(circularTypeNames, name) { circularTypeNames = append(circularTypeNames, name) } @@ -23514,10 +23515,10 @@ func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type { var b strings.Builder b.WriteString(ast.InternalSymbolNamePrefix) b.WriteByte('@') - b.WriteString(symbol.Name()) + b.WriteString(symbol.Name().Value()) b.WriteByte('@') b.WriteString(strconv.FormatUint(uint64(ast.GetSymbolId(symbol)), 10)) - uniqueType = c.newUniqueESSymbolType(symbol, b.String()) + uniqueType = c.newUniqueESSymbolType(symbol, ast.MakeSymbolName(b.String())) c.uniqueESSymbolTypes[symbol] = uniqueType } return uniqueType @@ -23686,10 +23687,10 @@ func (c *Checker) getUnresolvedSymbolForEntityName(name *ast.Node) *ast.Symbol { } else { path = text } - result := c.unresolvedSymbols[path] + result := c.unresolvedSymbols[ast.MakeSymbolName(path)] if result == nil { - result = c.newSymbolEx(ast.SymbolFlagsTypeAlias, text, ast.CheckFlagsUnresolved) - c.unresolvedSymbols[path] = result + result = c.newSymbolEx(ast.SymbolFlagsTypeAlias, ast.MakeSymbolName(text), ast.CheckFlagsUnresolved) + c.unresolvedSymbols[ast.MakeSymbolName(path)] = result result.SetParent(parentSymbol) c.typeAliasLinks.Get(result).declaredType = c.unresolvedType } @@ -23700,9 +23701,9 @@ func (c *Checker) getUnresolvedSymbolForEntityName(name *ast.Node) *ast.Symbol { func getSymbolPath(symbol *ast.Symbol) string { if symbol.Parent() != nil { - return getSymbolPath(symbol.Parent()) + "." + symbol.Name() + return getSymbolPath(symbol.Parent()) + "." + symbol.Name().Value() } - return symbol.Name() + return symbol.Name().Value() } func (c *Checker) getTypeReferenceType(node *ast.Node, symbol *ast.Symbol) *Type { @@ -24104,11 +24105,11 @@ func (c *Checker) isEmptyLiteralType(t *Type) bool { } func (c *Checker) isTupleLikeType(t *Type) bool { - if isTupleType(t) || c.getPropertyOfType(t, "0") != nil { + if isTupleType(t) || c.getPropertyOfType(t, ast.SymbolNameZero) != nil { return true } if c.isArrayLikeType(t) { - if lengthType := c.getTypeOfPropertyOfType(t, "length"); lengthType != nil { + if lengthType := c.getTypeOfPropertyOfType(t, ast.SymbolNameLength); lengthType != nil { return everyType(lengthType, func(t *Type) bool { return t.flags&TypeFlagsNumberLiteral != 0 }) } } @@ -24124,7 +24125,7 @@ func (c *Checker) isArrayOrTupleOrIntersection(t *Type) bool { } func (c *Checker) getTupleElementType(t *Type, index int) *Type { - propType := c.getTypeOfPropertyOfType(t, strconv.Itoa(index)) + propType := c.getTypeOfPropertyOfType(t, ast.MakeSymbolName(strconv.Itoa(index))) if propType != nil { return propType } @@ -24426,7 +24427,7 @@ func (c *Checker) getDeclaredTypeOfTypeAlias(symbol *ast.Symbol) *Type { links.instantiations = make(map[CacheHashKey]*Type) links.instantiations[getTypeListKey(typeParameters)] = t } - if t == c.intrinsicMarkerType && symbol.Name() == "BuiltinIteratorReturn" { + if t == c.intrinsicMarkerType && symbol.Name() == ast.SymbolNameBuiltinIteratorReturn { t = c.getBuiltinIteratorReturnType() } } else { @@ -24601,7 +24602,7 @@ func (c *Checker) evaluateEntity(expr *ast.Node, location *ast.Node) evaluator.R return evaluator.NewResult(nil, false, false, false) } if expr.Kind == ast.KindIdentifier { - if ast.IsInfinityOrNaNString(expr.Text()) && (symbol == c.getGlobalSymbol(expr.Text(), ast.SymbolFlagsValue, nil /*diagnostic*/)) { + if ast.IsInfinityOrNaNString(expr.Text()) && (symbol == c.getGlobalSymbol(expr.TextSymbolName(), ast.SymbolFlagsValue, nil /*diagnostic*/)) { // Technically we resolved a global lib file here, but the decision to treat this as numeric // is more predicated on the fact that the single-file resolution *didn't* resolve to a // different meaning of `Infinity` or `NaN`. Transpilers handle this no problem. @@ -24632,7 +24633,7 @@ func (c *Checker) evaluateEntity(expr *ast.Node, location *ast.Node) evaluator.R rootSymbol := c.resolveEntityName(root, ast.SymbolFlagsValue, true /*ignoreErrors*/, false, nil) if rootSymbol != nil && rootSymbol.Flags()&ast.SymbolFlagsEnum != 0 { name := expr.AsElementAccessExpression().ArgumentExpression.Text() - member := rootSymbol.Exports()[name] + member := rootSymbol.Exports()[ast.MakeSymbolName(name)] if member != nil { if location != nil { return c.evaluateEnumMember(expr, member, location) @@ -25178,9 +25179,9 @@ func (c *Checker) getTypeFromImportTypeNode(node *ast.Node) *Type { var symbolFromVariable *ast.Symbol var symbolFromModule *ast.Symbol if n.IsTypeOf { - symbolFromVariable = c.getPropertyOfTypeEx(c.getTypeOfSymbol(mergedResolvedSymbol), current.Text(), false /*skipObjectFunctionPropertyAugment*/, true /*includeTypeOnlyMembers*/) + symbolFromVariable = c.getPropertyOfTypeEx(c.getTypeOfSymbol(mergedResolvedSymbol), current.TextSymbolName(), false /*skipObjectFunctionPropertyAugment*/, true /*includeTypeOnlyMembers*/) } else { - symbolFromModule = c.getSymbol(c.getExportsOfSymbol(mergedResolvedSymbol), current.Text(), meaning) + symbolFromModule = c.getSymbol(c.getExportsOfSymbol(mergedResolvedSymbol), current.TextSymbolName(), meaning) if symbolFromModule == nil { // a CommonJS module might have typedefs exported alongside an export= // !!! @@ -25188,7 +25189,7 @@ func (c *Checker) getTypeFromImportTypeNode(node *ast.Node) *Type { if immediateModuleSymbol != nil && core.Some(immediateModuleSymbol.Declarations(), func(d *ast.Node) bool { return ast.GetAssignmentDeclarationKind(d) == ast.JSDeclarationKindModuleExports }) { - symbolFromModule = c.getSymbol(c.getExportsOfSymbol(immediateModuleSymbol.Parent()), current.Text(), meaning) + symbolFromModule = c.getSymbol(c.getExportsOfSymbol(immediateModuleSymbol.Parent()), current.TextSymbolName(), meaning) } } } @@ -25244,7 +25245,7 @@ func (c *Checker) createTypeFromGenericGlobalType(genericGlobalType *Type, typeA return c.emptyObjectType } -func (c *Checker) getGlobalStrictFunctionType(name string) *Type { +func (c *Checker) getGlobalStrictFunctionType(name ast.SymbolName) *Type { if c.strictBindCallApply { return c.getGlobalType(name, 0 /*arity*/, true /*reportErrors*/) } @@ -25254,9 +25255,9 @@ func (c *Checker) getGlobalStrictFunctionType(name string) *Type { func (c *Checker) getGlobalImportMetaExpressionType() *Type { if c.deferredGlobalImportMetaExpressionType == nil { // Create a synthetic type `ImportMetaExpression { meta: MetaProperty }` - symbol := c.newSymbol(ast.SymbolFlagsNone, "ImportMetaExpression") + symbol := c.newSymbol(ast.SymbolFlagsNone, ast.SymbolNameImportMetaExpression) importMetaType := c.getGlobalImportMetaType() - metaPropertySymbol := c.newSymbolEx(ast.SymbolFlagsProperty, "meta", ast.CheckFlagsReadonly) + metaPropertySymbol := c.newSymbolEx(ast.SymbolFlagsProperty, ast.SymbolNameMeta, ast.CheckFlagsReadonly) metaPropertySymbol.SetParent(symbol) c.valueSymbolLinks.Get(metaPropertySymbol).resolvedType = importMetaType members := createSymbolTable([]*ast.Symbol{metaPropertySymbol}) @@ -25360,7 +25361,7 @@ func (c *Checker) createTupleTargetType(elementInfos []TupleElementInfo, readonl flags := elementInfos[i].flags combinedFlags |= flags if combinedFlags&ElementFlagsVariable == 0 { - property := c.newSymbolEx(ast.SymbolFlagsProperty|core.IfElse(flags&ElementFlagsOptional != 0, ast.SymbolFlagsOptional, 0), strconv.Itoa(i), core.IfElse(readonly, ast.CheckFlagsReadonly, 0)) + property := c.newSymbolEx(ast.SymbolFlagsProperty|core.IfElse(flags&ElementFlagsOptional != 0, ast.SymbolFlagsOptional, 0), ast.MakeSymbolName(strconv.Itoa(i)), core.IfElse(readonly, ast.CheckFlagsReadonly, 0)) c.valueSymbolLinks.Get(property).resolvedType = typeParameter // c.valueSymbolLinks.get(property).tupleLabelDeclaration = elementInfos[i].labeledDeclaration members[property.Name()] = property @@ -25368,7 +25369,7 @@ func (c *Checker) createTupleTargetType(elementInfos []TupleElementInfo, readonl } } fixedLength := len(members) - lengthSymbol := c.newSymbolEx(ast.SymbolFlagsProperty, "length", core.IfElse(readonly, ast.CheckFlagsReadonly, 0)) + lengthSymbol := c.newSymbolEx(ast.SymbolFlagsProperty, ast.SymbolNameLength, core.IfElse(readonly, ast.CheckFlagsReadonly, 0)) if combinedFlags&ElementFlagsVariable != 0 { c.valueSymbolLinks.Get(lengthSymbol).resolvedType = c.numberType } else { @@ -25623,7 +25624,7 @@ func (c *Checker) newLiteralType(flags TypeFlags, value any, regularType *Type) return t } -func (c *Checker) newUniqueESSymbolType(symbol *ast.Symbol, name string) *Type { +func (c *Checker) newUniqueESSymbolType(symbol *ast.Symbol, name ast.SymbolName) *Type { data := &UniqueESSymbolType{} data.name = name t := c.newType(TypeFlagsUniqueESSymbol, ObjectFlagsNone, data.AsType(), typeKindUniqueESSymbol) @@ -27360,7 +27361,7 @@ func (c *Checker) getLiteralTypeFromProperty(prop *ast.Symbol, include TypeFlags t = c.getLiteralTypeFromPropertyName(name) } if t == nil && !IsKnownSymbol(prop) { - t = c.getStringLiteralType(ast.SymbolName(prop)) + t = c.getStringLiteralType(ast.SymbolNameText(prop)) } } } @@ -27383,7 +27384,7 @@ func (c *Checker) getLiteralTypeFromPropertyName(name *ast.Node) *Type { } propertyName := ast.GetPropertyNameForPropertyNameNode(name) if propertyName != ast.InternalSymbolNameMissing { - return c.getStringLiteralType(propertyName) + return c.getStringLiteralType(propertyName.Value()) } if ast.IsExpression(name) { return c.getRegularTypeOfLiteralType(c.checkExpression(name)) @@ -27608,7 +27609,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy if accessNode != nil && ast.IsElementAccessExpression(accessNode) { accessExpression = accessNode } - var propName string + var propName ast.SymbolName var hasPropName bool if !(accessNode != nil && ast.IsPrivateIdentifier(accessNode)) { propName = c.getPropertyNameFromIndex(indexType, accessNode) @@ -27633,7 +27634,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy } else { deprecatedNode = accessNode } - c.addDeprecatedSuggestion(deprecatedNode, prop.Declarations(), propName) + c.addDeprecatedSuggestion(deprecatedNode, prop.Declarations(), propName.Value()) } if accessExpression != nil { c.markPropertyAsReferenced(prop, accessExpression, c.isSelfTypeAccess(accessExpression.Expression(), objectType.symbol)) @@ -27663,8 +27664,8 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy return propType } } - if everyType(objectType, isTupleType) && isNumericLiteralName(propName) { - index := jsnum.FromString(propName) + if everyType(objectType, isTupleType) && isNumericLiteralName(propName.Value()) { + index := jsnum.FromString(propName.Value()) if accessNode != nil && everyType(objectType, func(t *Type) bool { return t.TargetTupleType().combinedFlags&ElementFlagsVariable == 0 }) && accessFlags&AccessFlagsAllowMissing == 0 { @@ -27674,9 +27675,9 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy c.error(indexNode, diagnostics.A_tuple_type_cannot_be_indexed_with_a_negative_value) return c.undefinedType } - c.error(indexNode, diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2, c.TypeToString(objectType), c.getTypeReferenceArity(objectType), propName) + c.error(indexNode, diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2, c.TypeToString(objectType), c.getTypeReferenceArity(objectType), propName.Value()) } else { - c.error(indexNode, diagnostics.Property_0_does_not_exist_on_type_1, propName, c.TypeToString(objectType)) + c.error(indexNode, diagnostics.Property_0_does_not_exist_on_type_1, propName.Value(), c.TypeToString(objectType)) } } if index >= 0 { @@ -27748,11 +27749,11 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy } } if objectType.symbol == c.globalThisSymbol && hasPropName && c.globalThisSymbol.Exports()[propName] != nil && c.globalThisSymbol.Exports()[propName].Flags()&ast.SymbolFlagsBlockScoped != 0 { - c.error(accessExpression, diagnostics.Property_0_does_not_exist_on_type_1, propName, c.TypeToString(objectType)) + c.error(accessExpression, diagnostics.Property_0_does_not_exist_on_type_1, propName.Value(), c.TypeToString(objectType)) } else if c.noImplicitAny && accessFlags&AccessFlagsSuppressNoImplicitAnyError == 0 { if hasPropName && c.typeHasStaticProperty(propName, objectType) { typeName := c.TypeToString(objectType) - c.error(accessExpression, diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName /* as string */, typeName, typeName+"["+scanner.GetTextOfNode(accessExpression.AsElementAccessExpression().ArgumentExpression)+"]") + c.error(accessExpression, diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_to_access_the_static_member_2_instead, propName.Value() /* as string */, typeName, typeName+"["+scanner.GetTextOfNode(accessExpression.AsElementAccessExpression().ArgumentExpression)+"]") } else if c.getIndexTypeOfType(objectType, c.numberType) != nil { c.error(accessExpression.AsElementAccessExpression().ArgumentExpression, diagnostics.Element_implicitly_has_an_any_type_because_index_expression_is_not_of_type_number) } else { @@ -27761,7 +27762,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy suggestion = c.getSuggestionForNonexistentProperty(propName, objectType) } if suggestion != "" { - c.error(accessExpression.AsElementAccessExpression().ArgumentExpression, diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName /* as string */, c.TypeToString(objectType), suggestion) + c.error(accessExpression.AsElementAccessExpression().ArgumentExpression, diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName.Value() /* as string */, c.TypeToString(objectType), suggestion) } else { suggestion = c.getSuggestionForNonexistentIndexSignature(objectType, accessExpression, indexType) if suggestion != "" { @@ -27817,7 +27818,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy return nil } -func (c *Checker) typeHasStaticProperty(propName string, containingType *Type) bool { +func (c *Checker) typeHasStaticProperty(propName ast.SymbolName, containingType *Type) bool { if containingType.symbol != nil { prop := c.getPropertyOfType(c.getTypeOfSymbol(containingType.symbol), propName) return prop != nil && prop.ValueDeclaration() != nil && ast.IsStatic(prop.ValueDeclaration()) @@ -27825,10 +27826,10 @@ func (c *Checker) typeHasStaticProperty(propName string, containingType *Type) b return false } -func (c *Checker) getSuggestionForNonexistentProperty(name string, containingType *Type) string { +func (c *Checker) getSuggestionForNonexistentProperty(name ast.SymbolName, containingType *Type) string { symbol := c.getSpellingSuggestionForName(name, slices.Values(c.getPropertiesOfType(containingType)), ast.SymbolFlagsValue) if symbol != nil { - return symbol.Name() + return symbol.Name().Value() } return "" } @@ -27836,7 +27837,7 @@ func (c *Checker) getSuggestionForNonexistentProperty(name string, containingTyp func (c *Checker) getSuggestionForNonexistentIndexSignature(objectType *Type, expr *ast.Node, keyedType *Type) string { // check if object type has setter or getter hasProp := func(name string) bool { - prop := c.getPropertyOfObjectType(objectType, name) + prop := c.getPropertyOfObjectType(objectType, ast.MakeSymbolName(name)) if prop != nil { s := c.getSingleCallSignature(c.getTypeOfSymbol(prop)) return s != nil && c.getMinArgumentCount(s) >= 1 && c.isTypeAssignableTo(keyedType, c.getTypeAtPosition(s, 0)) @@ -27957,7 +27958,7 @@ func (c *Checker) getDeclaringConstructor(symbol *ast.Symbol) *ast.Node { return nil } -func (c *Checker) getPropertyNameFromIndex(indexType *Type, accessNode *ast.Node) string { +func (c *Checker) getPropertyNameFromIndex(indexType *Type, accessNode *ast.Node) ast.SymbolName { if isTypeUsableAsPropertyName(indexType) { return getPropertyNameFromType(indexType) } @@ -27987,8 +27988,8 @@ func indexTypeLessThan(indexType *Type, limit int) bool { return everyType(indexType, func(t *Type) bool { if t.flags&TypeFlagsStringOrNumberLiteral != 0 { propName := getPropertyNameFromType(t) - if isNumericLiteralName(propName) { - index := jsnum.FromString(propName) + if isNumericLiteralName(propName.Value()) { + index := jsnum.FromString(propName.Value()) return index >= 0 && index < jsnum.Number(limit) } } @@ -28360,10 +28361,10 @@ func (c *Checker) expandSignatureParametersWithTupleMembers(signature *Signature return expanded } -func (c *Checker) getUniqAssociatedNamesFromTupleType(t *TypeReference, restSymbol *ast.Symbol) []string { +func (c *Checker) getUniqAssociatedNamesFromTupleType(t *TypeReference, restSymbol *ast.Symbol) []ast.SymbolName { elementInfos := t.TargetTupleType().elementInfos - names := make([]string, len(elementInfos)) - counters := make(map[string]int) + names := make([]ast.SymbolName, len(elementInfos)) + counters := make(map[ast.SymbolName]int) for i, info := range elementInfos { names[i] = c.getTupleElementLabel(info, restSymbol, i) // count duplicates using negative values @@ -28379,7 +28380,7 @@ func (c *Checker) getUniqAssociatedNamesFromTupleType(t *TypeReference, restSymb counters[name] = 0 } counters[name]++ - candidateName := name + "_" + strconv.Itoa(counters[name]) + candidateName := ast.MakeSymbolName(name.Value() + "_" + strconv.Itoa(counters[name])) if counters[candidateName] == 0 { names[i] = candidateName break @@ -29074,7 +29075,7 @@ func (c *Checker) markPropertyAliasReferenced(location *ast.Node /*PropertyAcces } var lexicallyScopedSymbol *ast.Symbol if ast.IsPrivateIdentifier(right) { - lexicallyScopedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(right.Text(), right) + lexicallyScopedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(right.TextSymbolName(), right) } assignmentKind := getAssignmentTargetKind(location) var apparentType *Type @@ -29088,7 +29089,7 @@ func (c *Checker) markPropertyAliasReferenced(location *ast.Node /*PropertyAcces prop = c.getPrivateIdentifierPropertyOfType(apparentType, lexicallyScopedSymbol) } } else { - prop = c.getPropertyOfType(apparentType, right.Text()) + prop = c.getPropertyOfType(apparentType, right.TextSymbolName()) } } if !(prop != nil && (isConstEnumOrConstEnumOnlyModule(prop) || prop.Flags()&ast.SymbolFlagsEnumMember != 0 && location.Parent.Kind == ast.KindEnumMember)) { @@ -29139,7 +29140,7 @@ func (c *Checker) markJsxAliasReferenced(node *ast.Node /*JsxOpeningLikeElement if !shouldFactoryRefErr { flags &^= ast.SymbolFlagsEnum } - jsxFactorySym = c.resolveName(jsxFactoryLocation, jsxFactoryNamespace, flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) + jsxFactorySym = c.resolveName(jsxFactoryLocation, ast.MakeSymbolName(jsxFactoryNamespace), flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) } if jsxFactorySym != nil { // Mark local symbol as referenced here because it might not have been marked @@ -29160,7 +29161,7 @@ func (c *Checker) markJsxAliasReferenced(node *ast.Node /*JsxOpeningLikeElement if !shouldFactoryRefErr { flags &^= ast.SymbolFlagsEnum } - c.resolveName(jsxFactoryLocation, localJsxNamespace, flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) + c.resolveName(jsxFactoryLocation, ast.MakeSymbolName(localJsxNamespace), flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) } } } @@ -29177,7 +29178,7 @@ func (c *Checker) markExportSpecifierAliasReferenced(location *ast.ExportSpecifi if exportedName.Kind == ast.KindStringLiteral { return // Skip for invalid syntax like this: export { "x" } } - symbol := c.resolveName(exportedName, exportedName.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + symbol := c.resolveName(exportedName, exportedName.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if symbol != nil && (symbol == c.undefinedSymbol || symbol == c.globalThisSymbol || symbol.Declarations() != nil && ast.IsGlobalSourceFile(ast.GetDeclarationContainer(symbol.Declarations()[0]))) { // Do nothing, non-local symbol } else { @@ -29213,7 +29214,7 @@ func (c *Checker) checkExternalEmitHelpers(location *ast.Node, helpers ExternalE continue } for _, name := range c.getHelperNames(helper) { - symbol := c.resolveSymbol(c.getSymbol(c.getExportsOfModule(helpersModule), name, ast.SymbolFlagsValue)) + symbol := c.resolveSymbol(c.getSymbol(c.getExportsOfModule(helpersModule), ast.MakeSymbolName(name), ast.SymbolFlagsValue)) if symbol == nil { c.error(location, diagnostics.This_syntax_requires_an_imported_helper_named_1_which_does_not_exist_in_0_Consider_upgrading_your_version_of_0, externalHelpersModuleNameText, name) } else if helper&ExternalEmitHelpersClassPrivateFieldGet != 0 { @@ -29485,7 +29486,7 @@ func (c *Checker) markEntityNameOrEntityExpressionAsReference(typeName *ast.Node rootName := ast.GetFirstIdentifier(typeName) meaning := core.IfElse(typeName.Kind == ast.KindIdentifier, ast.SymbolFlagsType, ast.SymbolFlagsNamespace) | ast.SymbolFlagsAlias - rootSymbol := c.resolveName(rootName, rootName.Text(), meaning, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + rootSymbol := c.resolveName(rootName, rootName.TextSymbolName(), meaning, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if rootSymbol != nil && rootSymbol.Flags()&ast.SymbolFlagsAlias != 0 { if c.canCollectSymbolAliasAccessibilityData && @@ -29571,7 +29572,7 @@ func (c *Checker) getPromisedTypeOfPromiseEx(t *Type, errorNode *ast.Node, thisT if c.allTypesAssignableToKind(c.getBaseConstraintOrType(t), TypeFlagsPrimitive|TypeFlagsNever) { return nil } - thenFunction := c.getTypeOfPropertyOfType(t, "then") + thenFunction := c.getTypeOfPropertyOfType(t, ast.SymbolNameThen) // TODO: GH#18217 if IsTypeAny(thenFunction) { return nil @@ -29954,7 +29955,7 @@ func (c *Checker) couldAccessOptionalProperty(objectType *Type, indexType *Type) }) } -func (c *Checker) getTypeOfPropertyOrIndexSignatureOfType(t *Type, name string) *Type { +func (c *Checker) getTypeOfPropertyOrIndexSignatureOfType(t *Type, name ast.SymbolName) *Type { propType := c.getTypeOfPropertyOfType(t, name) if propType != nil { return propType @@ -30503,7 +30504,7 @@ func (c *Checker) getContextualTypeForAssignmentExpression(binary *ast.BinaryExp if symbol.ValueDeclaration() != nil && ast.IsVariableDeclaration(symbol.ValueDeclaration()) { if typeNode := symbol.ValueDeclaration().Type(); typeNode != nil { if ast.IsPropertyAccessExpression(left) { - return c.getTypeOfPropertyOfContextualType(c.getTypeFromTypeNode(typeNode), left.Name().Text()) + return c.getTypeOfPropertyOfContextualType(c.getTypeFromTypeNode(typeNode), left.Name().TextSymbolName()) } nameType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) if isTypeUsableAsPropertyName(nameType) { @@ -30528,7 +30529,7 @@ func (c *Checker) getContextualTypeForAssignmentExpression(binary *ast.BinaryExp symbol = c.getPropertyOfType(thisType, binder.GetSymbolNameForPrivateIdentifier(thisType.symbol, name.Text())) } } else { - symbol = c.getPropertyOfType(thisType, name.Text()) + symbol = c.getPropertyOfType(thisType, name.TextSymbolName()) } } else { propType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) @@ -30653,7 +30654,7 @@ func (c *Checker) getContextualTypeForElementExpression(t *Type, index int, leng // If element index is known and a contextual property with that name exists, return it. Otherwise return the // iterated or element type of the contextual type. if firstSpreadIndex < 0 || index < firstSpreadIndex { - propType := c.getTypeOfPropertyOfContextualType(t, strconv.Itoa(index)) + propType := c.getTypeOfPropertyOfContextualType(t, ast.MakeSymbolName(strconv.Itoa(index))) if propType != nil { return propType } @@ -30679,7 +30680,7 @@ func (c *Checker) getContextualTypeForSubstitutionExpression(template *ast.Node, } func (c *Checker) getContextualImportAttributeType(node *ast.Node) *Type { - return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), node.Name().Text()) + return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), node.Name().TextSymbolName()) } // Returns the effective arguments for an expression that works like a function invocation. @@ -30813,7 +30814,7 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur // For a class decorator, the `target` is the type of the class (e.g. the // "static" or "constructor" side of the class). targetType := c.getTypeOfSymbol(c.getSymbolOfDeclaration(node)) - targetParam := c.newParameter("target", targetType) + targetParam := c.newParameter(ast.SymbolNameTarget, targetType) links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam}, c.getUnionType([]*Type{targetType, c.voidType})) case ast.KindParameter: if !ast.IsConstructorDeclaration(node.Parent) && !(ast.IsMethodDeclaration(node.Parent) || ast.IsSetAccessorDeclaration(node.Parent) && ast.IsClassLike(node.Parent.Parent)) { @@ -30836,9 +30837,9 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur keyType = c.getClassElementPropertyKeyType(node.Parent) } indexType := c.getNumberLiteralType(jsnum.Number(index)) - targetParam := c.newParameter("target", targetType) - keyParam := c.newParameter("propertyKey", keyType) - indexParam := c.newParameter("parameterIndex", indexType) + targetParam := c.newParameter(ast.SymbolNameTarget, targetType) + keyParam := c.newParameter(ast.SymbolNamePropertyKey, keyType) + indexParam := c.newParameter(ast.SymbolNameParameterIndex, indexType) links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam, indexParam}, c.voidType) case ast.KindMethodDeclaration, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindPropertyDeclaration: if !ast.IsClassLike(node.Parent) { @@ -30847,9 +30848,9 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur // A method or accessor declaration decorator will have either two or three arguments (see // `PropertyDecorator` and `MethodDecorator` in core.d.ts). targetType := c.getParentTypeOfClassElement(node) - targetParam := c.newParameter("target", targetType) + targetParam := c.newParameter(ast.SymbolNameTarget, targetType) keyType := c.getClassElementPropertyKeyType(node) - keyParam := c.newParameter("propertyKey", keyType) + keyParam := c.newParameter(ast.SymbolNamePropertyKey, keyType) returnType := c.voidType if !ast.IsPropertyDeclaration(node) { returnType = c.newTypedPropertyDescriptorType(c.getTypeOfNode(node)) @@ -30857,7 +30858,7 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur hasPropDesc := !ast.IsPropertyDeclaration(node) || ast.HasAccessorModifier(node) if hasPropDesc { descriptorType := c.newTypedPropertyDescriptorType(c.getTypeOfNode(node)) - descriptorParam := c.newParameter("descriptor", descriptorType) + descriptorParam := c.newParameter(ast.SymbolNameDescriptor, descriptorType) links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam, descriptorParam}, c.getUnionType([]*Type{returnType, c.voidType})) } else { links.decoratorSignature = c.newCallSignature(nil, nil, []*ast.Symbol{targetParam, keyParam}, c.getUnionType([]*Type{returnType, c.voidType})) @@ -31085,9 +31086,9 @@ func (c *Checker) getClassMemberDecoratorContextOverrideType(nameType *Type, isP return overrideType } members := make(ast.SymbolTable) - members["name"] = c.newProperty("name", nameType) - members["private"] = c.newProperty("private", core.IfElse(isPrivate, c.trueType, c.falseType)) - members["static"] = c.newProperty("static", core.IfElse(isStatic, c.trueType, c.falseType)) + members[ast.SymbolNameName] = c.newProperty(ast.SymbolNameName, nameType) + members[ast.SymbolNamePrivate] = c.newProperty(ast.SymbolNamePrivate, core.IfElse(isPrivate, c.trueType, c.falseType)) + members[ast.SymbolNameStatic] = c.newProperty(ast.SymbolNameStatic, core.IfElse(isStatic, c.trueType, c.falseType)) overrideType := c.newAnonymousType(nil, members, nil, nil, nil) c.cachedTypes[key] = overrideType return overrideType @@ -31130,16 +31131,16 @@ func (c *Checker) newClassAccessorDecoratorResultType(thisType *Type, valueType } func (c *Checker) newClassFieldDecoratorInitializerMutatorType(thisType *Type, valueType *Type) *Type { - thisParam := c.newParameter("this", thisType) - valueParam := c.newParameter("value", valueType) + thisParam := c.newParameter(ast.InternalSymbolNameThis, thisType) + valueParam := c.newParameter(ast.SymbolNameValue, valueType) return c.newFunctionType(nil, thisParam, []*ast.Symbol{valueParam}, valueType) } // Creates a call signature for an ES Decorator. This method is used by the semantics of // `getESDecoratorCallSignature`, which you should probably be using instead. func (c *Checker) newESDecoratorCallSignature(targetType *Type, contextType *Type, nonOptionalReturnType *Type) *Signature { - targetParam := c.newParameter("target", targetType) - contextParam := c.newParameter("context", contextType) + targetParam := c.newParameter(ast.SymbolNameTarget, targetType) + contextParam := c.newParameter(ast.SymbolNameContext, contextType) returnType := c.getUnionType([]*Type{nonOptionalReturnType, c.voidType}) return c.newCallSignature(nil, nil /*thisParameter*/, []*ast.Symbol{targetParam, contextParam}, returnType) } @@ -31155,7 +31156,7 @@ func (c *Checker) newGetterFunctionType(t *Type) *Type { } func (c *Checker) newSetterFunctionType(t *Type) *Type { - valueParam := c.newParameter("value", t) + valueParam := c.newParameter(ast.SymbolNameValue, t) return c.newFunctionType(nil, nil /*thisParameter*/, []*ast.Symbol{valueParam}, c.voidType) } @@ -31192,11 +31193,11 @@ func (c *Checker) getClassElementPropertyKeyType(element *ast.Node) *Type { return c.errorType } -func (c *Checker) getTypeOfPropertyOfContextualType(t *Type, name string) *Type { +func (c *Checker) getTypeOfPropertyOfContextualType(t *Type, name ast.SymbolName) *Type { return c.getTypeOfPropertyOfContextualTypeEx(t, name, nil) } -func (c *Checker) getTypeOfPropertyOfContextualTypeEx(t *Type, name string, nameType *Type) *Type { +func (c *Checker) getTypeOfPropertyOfContextualTypeEx(t *Type, name ast.SymbolName, nameType *Type) *Type { return c.mapTypeEx(t, func(t *Type) *Type { if t.flags&TypeFlagsIntersection != 0 { var types []*Type @@ -31248,10 +31249,10 @@ func (c *Checker) getTypeOfPropertyOfContextualTypeEx(t *Type, name string, name }, true /*noReductions*/) } -func (c *Checker) getIndexedMappedTypeSubstitutedTypeOfContextualType(t *Type, name string, nameType *Type) *Type { +func (c *Checker) getIndexedMappedTypeSubstitutedTypeOfContextualType(t *Type, name ast.SymbolName, nameType *Type) *Type { propertyNameType := nameType if propertyNameType == nil { - propertyNameType = c.getStringLiteralType(name) + propertyNameType = c.getStringLiteralType(name.Value()) } constraint := c.getConstraintTypeFromMappedType(t) // special case for conditional types pretending to be negated types @@ -31279,7 +31280,7 @@ func (c *Checker) isExcludedMappedPropertyName(t *Type, propertyNameType *Type) return false } -func (c *Checker) getTypeOfConcretePropertyOfContextualType(t *Type, name string) *Type { +func (c *Checker) getTypeOfConcretePropertyOfContextualType(t *Type, name ast.SymbolName) *Type { prop := c.getPropertyOfType(t, name) if prop == nil || c.isCircularMappedProperty(prop) { return nil @@ -31287,15 +31288,15 @@ func (c *Checker) getTypeOfConcretePropertyOfContextualType(t *Type, name string return c.removeMissingType(c.getTypeOfSymbol(prop), prop.Flags()&ast.SymbolFlagsOptional != 0) } -func (c *Checker) getTypeFromIndexInfosOfContextualType(t *Type, name string, nameType *Type) *Type { - if isTupleType(t) && isNumericLiteralName(name) && jsnum.FromString(name) >= 0 { +func (c *Checker) getTypeFromIndexInfosOfContextualType(t *Type, name ast.SymbolName, nameType *Type) *Type { + if isTupleType(t) && isNumericLiteralName(name.Value()) && jsnum.FromString(name.Value()) >= 0 { restType := c.getElementTypeOfSliceOfTupleType(t, t.TargetTupleType().fixedLength, 0 /*endSkipCount*/, false /*writing*/, true /*noReductions*/) if restType != nil { return restType } } if nameType == nil { - nameType = c.getStringLiteralType(name) + nameType = c.getStringLiteralType(name.Value()) } indexInfo := c.findApplicableIndexInfo(c.getIndexInfosOfStructuredType(t), nameType) if indexInfo == nil { @@ -31364,7 +31365,7 @@ func (d *ObjectLiteralDiscriminator) len() int { return len(d.props) + len(d.members) } -func (d *ObjectLiteralDiscriminator) name(index int) string { +func (d *ObjectLiteralDiscriminator) name(index int) ast.SymbolName { if index < len(d.props) { return d.props[index].Symbol().Name() } @@ -31428,7 +31429,7 @@ func (c *Checker) discriminateContextualTypeByObjectMembers(node *ast.Node, cont func (c *Checker) getMatchingUnionConstituentForObjectLiteral(unionType *Type, node *ast.Node) *Type { keyPropertyName := c.getKeyPropertyName(unionType) - if keyPropertyName != "" { + if keyPropertyName != ast.EmptySymbolName { propNode := core.Find(node.Properties(), func(p *ast.Node) bool { return p.Symbol() != nil && ast.IsPropertyAssignment(p) && p.Symbol().Name() == keyPropertyName && c.isPossiblyDiscriminantValue(p.Initializer()) }) @@ -31788,7 +31789,7 @@ func (c *Checker) isFunctionObjectType(t *Type) bool { // We do a quick check for a "bind" property before performing the more expensive subtype // check. This gives us a quicker out in the common case where an object type is not a function. resolved := c.resolveStructuredTypeMembers(t) - return len(resolved.getSignatures()) != 0 || resolved.members["bind"] != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) + return len(resolved.getSignatures()) != 0 || resolved.members[ast.SymbolNameBind] != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) } func (c *Checker) getTypeWithFacts(t *Type, include TypeFacts) *Type { @@ -32095,7 +32096,7 @@ func (c *Checker) isThenableType(t *Type) bool { // primitive types cannot be considered "thenable" since they are not objects. return false } - thenFunction := c.getTypeOfPropertyOfType(t, "then") + thenFunction := c.getTypeOfPropertyOfType(t, ast.SymbolNameThen) return thenFunction != nil && len(c.getSignaturesOfType(c.getTypeWithFacts(thenFunction, TypeFactsNEUndefinedOrNull), SignatureKindCall)) != 0 } @@ -32270,7 +32271,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy return c.getSymbolOfNameOrPropertyAccessExpression(node) } else if ast.IsBindingElement(parent) && ast.IsObjectBindingPattern(grandParent) && node == parent.PropertyName() { typeOfPattern := c.getTypeOfNode(grandParent) - if propertyDeclaration := c.getPropertyOfType(typeOfPattern, node.Text()); propertyDeclaration != nil { + if propertyDeclaration := c.getPropertyOfType(typeOfPattern, node.TextSymbolName()); propertyDeclaration != nil { return propertyDeclaration } } else if ast.IsMetaProperty(parent) && parent.Name() == node { @@ -32284,7 +32285,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy // member should more exactly be the kind of (declarationless) symbol we want. // (See #44364 and #45031 for relevant implementation PRs) if metaProp.KeywordToken == ast.KindImportKeyword && node.Text() == "meta" { - return c.getGlobalImportMetaExpressionType().AsObjectType().members["meta"] + return c.getGlobalImportMetaExpressionType().AsObjectType().members[ast.SymbolNameMeta] } // no other meta properties are valid syntax, thus no others should have symbols return nil @@ -32355,7 +32356,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy } if objectType != nil { - return c.getPropertyOfType(objectType, node.Text()) + return c.getPropertyOfType(objectType, node.TextSymbolName()) } return nil case ast.KindDefaultKeyword, ast.KindFunctionKeyword, ast.KindEqualsGreaterThanToken, ast.KindClassKeyword: @@ -32507,8 +32508,8 @@ func (c *Checker) getSymbolOfNameOrPropertyAccessExpression(name *ast.Node) *ast if container := ast.FindAncestor(name, ast.IsClassOrInterfaceLike); container != nil { symbol := c.getSymbolOfDeclaration(container) // Handle unqualified references to class static members and class or interface instance members - if result = c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(symbol), name.Text(), meaning)); result == nil { - result = c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), name.Text()) + if result = c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(symbol), name.TextSymbolName(), meaning)); result == nil { + result = c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), name.TextSymbolName()) } } } @@ -32783,7 +32784,7 @@ func (c *Checker) containsArgumentsReference(node *ast.Node) bool { } switch node.Kind { case ast.KindIdentifier: - return node.Text() == c.argumentsSymbol.Name() && c.IsArgumentsSymbol(c.getResolvedSymbol(node)) + return node.TextSymbolName() == c.argumentsSymbol.Name() && c.IsArgumentsSymbol(c.getResolvedSymbol(node)) case ast.KindPropertyDeclaration, ast.KindMethodDeclaration, ast.KindGetAccessor, ast.KindSetAccessor: if ast.IsComputedPropertyName(node.Name()) { return visit(node.Name()) diff --git a/tsc/internal/checker/emitresolver.go b/tsc/internal/checker/emitresolver.go index f0058eb2b28e3..7a189d7c9ef30 100644 --- a/tsc/internal/checker/emitresolver.go +++ b/tsc/internal/checker/emitresolver.go @@ -172,7 +172,7 @@ func (r *EmitResolver) aliasMarkingVisitorWorker(node *ast.Node) bool { func (r *EmitResolver) markLinkedAliases(node *ast.Node) { var exportSymbol *ast.Symbol if node.Kind != ast.KindStringLiteral && node.Parent != nil && (ast.IsExportAssignment(node.Parent) || isCommonJSModuleExports(node.Parent)) { - exportSymbol = r.checker.resolveName(node, node.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) + exportSymbol = r.checker.resolveName(node, node.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) } else if node.Parent.Kind == ast.KindExportSpecifier { exportSymbol = r.checker.getTargetOfExportSpecifier(node.Parent, ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, false) } @@ -193,7 +193,7 @@ func (r *EmitResolver) markLinkedAliases(node *ast.Node) { // Add the referenced top container visible internalModuleReference := declaration.AsImportEqualsDeclaration().ModuleReference firstIdentifier := ast.GetFirstIdentifier(internalModuleReference) - importSymbol := r.checker.resolveName(declaration, firstIdentifier.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) + importSymbol := r.checker.resolveName(declaration, firstIdentifier.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) nextSymbol = importSymbol } } @@ -298,7 +298,7 @@ func (r *EmitResolver) IsDefinitelyReferenceToGlobalSymbolObject(node *ast.Node) r.checkerMu.Lock() defer r.checkerMu.Unlock() // Exactly `Symbol.something` and `Symbol` either does not resolve or definitely resolves to the global Symbol - return r.checker.getResolvedSymbol(node.Expression()) == r.checker.getGlobalSymbol("Symbol", ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*diagnostic*/) + return r.checker.getResolvedSymbol(node.Expression()) == r.checker.getGlobalSymbol(ast.SymbolNameSymbol, ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*diagnostic*/) } if node.Expression().Expression().Kind != ast.KindIdentifier || node.Expression().Expression().Text() != "globalThis" || node.Expression().Name().Text() != "Symbol" { return false @@ -603,7 +603,7 @@ func (r *EmitResolver) GetReferencedValueDeclarations(node *ast.IdentifierNode) } // IsNameResolvable returns `true` if the given `name` resolves to any symbol at `location` -func (r *EmitResolver) IsNameResolvable(location *ast.Node, name string) bool { +func (r *EmitResolver) IsNameResolvable(location *ast.Node, name ast.SymbolName) bool { r.checkerMu.Lock() defer r.checkerMu.Unlock() @@ -611,9 +611,9 @@ func (r *EmitResolver) IsNameResolvable(location *ast.Node, name string) bool { return symbol != nil } -func (r *EmitResolver) GetElementAccessExpressionName(expression *ast.ElementAccessExpression) string { +func (r *EmitResolver) GetElementAccessExpressionName(expression *ast.ElementAccessExpression) ast.SymbolName { if !ast.IsParseTreeNode(expression.AsNode()) { - return "" + return ast.EmptySymbolName } r.checkerMu.Lock() @@ -791,7 +791,7 @@ func (r *EmitResolver) CreateLateBoundIndexSignatures(container *ast.Node, enclo } firstIdentifier := ast.GetFirstIdentifier(c.Name().Expression()) - name := r.checker.resolveName(firstIdentifier, firstIdentifier.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + name := r.checker.resolveName(firstIdentifier, firstIdentifier.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if name != nil { tracker.TrackSymbol(name, enclosingDeclaration, ast.SymbolFlagsValue) } diff --git a/tsc/internal/checker/emitsupport.go b/tsc/internal/checker/emitsupport.go index 3da782c9ab4c4..fc8df66619736 100644 --- a/tsc/internal/checker/emitsupport.go +++ b/tsc/internal/checker/emitsupport.go @@ -164,7 +164,7 @@ func (c *Checker) isEntityNameVisible(entityName *ast.Node, enclosingDeclaration meaning := getMeaningOfEntityNameReference(entityName) firstIdentifier := ast.GetFirstIdentifier(entityName) - symbol := c.resolveName(enclosingDeclaration, firstIdentifier.Text(), meaning, nil, false, false) + symbol := c.resolveName(enclosingDeclaration, firstIdentifier.TextSymbolName(), meaning, nil, false, false) if symbol != nil && symbol.Flags()&ast.SymbolFlagsTypeParameter != 0 && meaning&ast.SymbolFlagsType != 0 { return printer.SymbolAccessibilityResult{Accessibility: printer.SymbolAccessibilityAccessible} diff --git a/tsc/internal/checker/exports.go b/tsc/internal/checker/exports.go index 1a7afc78e9acb..1cd36e38f5ccc 100644 --- a/tsc/internal/checker/exports.go +++ b/tsc/internal/checker/exports.go @@ -92,11 +92,11 @@ func IsTypeUsableAsPropertyName(t *Type) bool { return isTypeUsableAsPropertyName(t) } -func GetPropertyNameFromType(t *Type) string { +func GetPropertyNameFromType(t *Type) ast.SymbolName { return getPropertyNameFromType(t) } -func (c *Checker) GetGlobalSymbol(name string, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { +func (c *Checker) GetGlobalSymbol(name ast.SymbolName, meaning ast.SymbolFlags, diagnostic *diagnostics.Message) *ast.Symbol { return c.getGlobalSymbol(name, meaning, diagnostic) } @@ -152,7 +152,7 @@ func (c *Checker) GetPropertiesOfType(t *Type) []*ast.Symbol { return c.getPropertiesOfType(t) } -func (c *Checker) GetPropertyOfType(t *Type, name string) *ast.Symbol { +func (c *Checker) GetPropertyOfType(t *Type, name ast.SymbolName) *ast.Symbol { return c.getPropertyOfType(t, name) } @@ -172,7 +172,7 @@ func (c *Checker) IsPropertyAccessible(node *ast.Node, isSuper bool, isWrite boo return c.isPropertyAccessible(node, isSuper, isWrite, containingType, property) } -func (c *Checker) GetTypeOfPropertyOfContextualType(t *Type, name string) *Type { +func (c *Checker) GetTypeOfPropertyOfContextualType(t *Type, name ast.SymbolName) *Type { return c.getTypeOfPropertyOfContextualType(t, name) } @@ -273,7 +273,7 @@ func (c *Checker) GetResolvedSignature(node *ast.Node) *Signature { } // Return the type of the given property in the given type, or nil if no such property exists -func (c *Checker) GetTypeOfPropertyOfType(t *Type, name string) *Type { +func (c *Checker) GetTypeOfPropertyOfType(t *Type, name ast.SymbolName) *Type { return c.getTypeOfPropertyOfType(t, name) } @@ -305,7 +305,7 @@ func (c *Checker) GetJsxFragmentFactory(location *ast.Node) string { return "" } -func (c *Checker) ResolveName(name string, location *ast.Node, meaning ast.SymbolFlags, excludeGlobals bool) *ast.Symbol { +func (c *Checker) ResolveName(name ast.SymbolName, location *ast.Node, meaning ast.SymbolFlags, excludeGlobals bool) *ast.Symbol { return c.resolveName(location, name, meaning, nil, true, excludeGlobals) } diff --git a/tsc/internal/checker/flow.go b/tsc/internal/checker/flow.go index d2831231772fe..2654024805ac4 100644 --- a/tsc/internal/checker/flow.go +++ b/tsc/internal/checker/flow.go @@ -458,7 +458,7 @@ func (c *Checker) narrowTypeByCallExpression(f *FlowState, t *Type, callExpressi callAccess := callExpression.Expression() if c.isMatchingReference(f.reference.Expression(), c.getReferenceCandidate(callAccess.Expression())) && ast.IsIdentifier(callAccess.Name()) && callAccess.Name().Text() == "hasOwnProperty" && len(callExpression.Arguments()) == 1 { argument := callExpression.Arguments()[0] - if accessedName, ok := c.getAccessedPropertyName(f.reference); ok && ast.IsStringLiteralLike(argument) && accessedName == argument.Text() { + if accessedName, ok := c.getAccessedPropertyName(f.reference); ok && ast.IsStringLiteralLike(argument) && accessedName == argument.TextSymbolName() { return c.getTypeWithFacts(t, core.IfElse(assumeTrue, TypeFactsNEUndefined, TypeFactsEQUndefined)) } } @@ -702,7 +702,7 @@ func (c *Checker) narrowTypeByTypeFacts(t *Type, impliedType *Type, facts TypeFa func (c *Checker) narrowTypeByDiscriminantProperty(t *Type, access *ast.Node, operator ast.Kind, value *ast.Node, assumeTrue bool) *Type { if (operator == ast.KindEqualsEqualsEqualsToken || operator == ast.KindExclamationEqualsEqualsToken) && t.flags&TypeFlagsUnion != 0 { keyPropertyName := c.getKeyPropertyName(t) - if keyPropertyName != "" { + if keyPropertyName != ast.EmptySymbolName { if accessedName, ok := c.getAccessedPropertyName(access); ok && keyPropertyName == accessedName { candidate := c.getConstituentTypeForKeyType(t, c.getTypeOfExpression(value)) if candidate != nil { @@ -768,7 +768,7 @@ func (c *Checker) narrowTypeByConstructor(t *Type, operator ast.Kind, identifier return t } // Get the prototype property of the type identifier so we can find out its type. - prototypeProperty := c.getPropertyOfType(identifierType, "prototype") + prototypeProperty := c.getPropertyOfType(identifierType, ast.SymbolNamePrototype) if prototypeProperty == nil { return t } @@ -882,14 +882,14 @@ func (c *Checker) getNarrowedTypeWorker(t *Type, candidate *Type, assumeTrue boo } // We first attempt to filter the current type, narrowing constituents as appropriate and removing // constituents that are unrelated to the candidate. - var keyPropertyName string + keyPropertyName := ast.EmptySymbolName if t.flags&TypeFlagsUnion != 0 { keyPropertyName = c.getKeyPropertyName(t) } narrowedType := c.mapType(candidate, func(n *Type) *Type { // If a discriminant property is available, use that to reduce the type. matching := t - if keyPropertyName != "" { + if keyPropertyName != ast.EmptySymbolName { if discriminant := c.getTypeOfPropertyOfType(n, keyPropertyName); discriminant != nil { if constituent := c.getConstituentTypeForKeyType(t, discriminant); constituent != nil { matching = constituent @@ -964,7 +964,7 @@ func (c *Checker) getNarrowedTypeWorker(t *Type, candidate *Type, assumeTrue boo } func (c *Checker) getInstanceType(constructorType *Type) *Type { - prototypePropertyType := c.getTypeOfPropertyOfType(constructorType, "prototype") + prototypePropertyType := c.getTypeOfPropertyOfType(constructorType, ast.SymbolNamePrototype) if prototypePropertyType != nil && !IsTypeAny(prototypePropertyType) { return prototypePropertyType } @@ -1021,7 +1021,7 @@ func (c *Checker) narrowTypeByInKeyword(f *FlowState, t *Type, nameType *Type, a return t } -func (c *Checker) isTypePresencePossible(t *Type, propName string, assumeTrue bool) bool { +func (c *Checker) isTypePresencePossible(t *Type, propName ast.SymbolName, assumeTrue bool) bool { prop := c.getPropertyOfType(t, propName) if prop != nil { return prop.Flags()&ast.SymbolFlagsOptional != 0 || prop.CheckFlags()&ast.CheckFlagsPartial != 0 || assumeTrue @@ -1231,7 +1231,7 @@ func (c *Checker) narrowTypeBySwitchOptionalChainContainment(t *Type, data *ast. func (c *Checker) narrowTypeBySwitchOnDiscriminantProperty(t *Type, access *ast.Node, data *ast.FlowSwitchClauseData) *Type { if data.ClauseStart < data.ClauseEnd && t.flags&TypeFlagsUnion != 0 { accessedName, _ := c.getAccessedPropertyName(access) - if accessedName != "" && c.getKeyPropertyName(t) == accessedName { + if accessedName != ast.EmptySymbolName && c.getKeyPropertyName(t) == accessedName { clauseTypes := c.getSwitchClauseTypes(data.SwitchStatement)[data.ClauseStart:data.ClauseEnd] candidate := c.getUnionType(core.Map(clauseTypes, func(s *Type) *Type { result := c.getConstituentTypeForKeyType(t, s) @@ -1639,7 +1639,7 @@ func (c *Checker) isMatchingReference(source *ast.Node, target *ast.Node) bool { case ast.KindQualifiedName: if ast.IsAccessExpression(target) { if targetPropertyName, ok := c.getAccessedPropertyName(target); ok { - return source.AsQualifiedName().Right.Text() == targetPropertyName && c.isMatchingReference(source.AsQualifiedName().Left, target.Expression()) + return source.AsQualifiedName().Right.TextSymbolName() == targetPropertyName && c.isMatchingReference(source.AsQualifiedName().Left, target.Expression()) } } case ast.KindBinaryExpression: @@ -1700,7 +1700,7 @@ func (c *Checker) writeFlowCacheKey(b *keyBuilder, node *ast.Node, declaredType return false } b.writeByte('.') - b.writeString(propName) + b.writeString(propName.Value()) return true } if ast.IsElementAccessExpression(node) && ast.IsIdentifier(node.AsElementAccessExpression().ArgumentExpression) { @@ -1724,9 +1724,9 @@ func (c *Checker) writeFlowCacheKey(b *keyBuilder, node *ast.Node, declaredType return false } -func (c *Checker) getAccessedPropertyName(access *ast.Node) (string, bool) { +func (c *Checker) getAccessedPropertyName(access *ast.Node) (ast.SymbolName, bool) { if ast.IsPropertyAccessExpression(access) { - return access.Name().Text(), true + return access.Name().TextSymbolName(), true } if ast.IsElementAccessExpression(access) { return c.tryGetElementAccessExpressionName(access.AsElementAccessExpression()) @@ -1735,29 +1735,29 @@ func (c *Checker) getAccessedPropertyName(access *ast.Node) (string, bool) { return c.getDestructuringPropertyName(access) } if ast.IsParameterDeclaration(access) { - return strconv.Itoa(slices.Index(access.Parent.Parameters(), access)), true + return ast.MakeSymbolName(strconv.Itoa(slices.Index(access.Parent.Parameters(), access))), true } - return "", false + return ast.EmptySymbolName, false } -func (c *Checker) tryGetElementAccessExpressionName(node *ast.ElementAccessExpression) (string, bool) { +func (c *Checker) tryGetElementAccessExpressionName(node *ast.ElementAccessExpression) (ast.SymbolName, bool) { switch { case ast.IsStringOrNumericLiteralLike(node.ArgumentExpression): - return node.ArgumentExpression.Text(), true + return node.ArgumentExpression.TextSymbolName(), true case ast.IsEntityNameExpression(node.ArgumentExpression): return c.tryGetNameFromEntityNameExpression(node.ArgumentExpression) } - return "", false + return ast.EmptySymbolName, false } -func (c *Checker) tryGetNameFromEntityNameExpression(node *ast.Node) (string, bool) { +func (c *Checker) tryGetNameFromEntityNameExpression(node *ast.Node) (ast.SymbolName, bool) { symbol := c.resolveEntityName(node, ast.SymbolFlagsValue, true /*ignoreErrors*/, false, nil) if symbol == nil || !(c.isConstantVariable(symbol) || (symbol.Flags()&ast.SymbolFlagsEnumMember != 0)) { - return "", false + return ast.EmptySymbolName, false } declaration := symbol.ValueDeclaration() if declaration == nil { - return "", false + return ast.EmptySymbolName, false } t := c.tryGetTypeFromTypeNode(declaration) if t != nil { @@ -1773,23 +1773,24 @@ func (c *Checker) tryGetNameFromEntityNameExpression(node *ast.Node) (string, bo return tryGetNameFromType(initializerType) } } else if ast.IsEnumMember(declaration) { - return ast.TryGetTextOfPropertyName(declaration.Name()) + name, ok := ast.TryGetTextOfPropertyName(declaration.Name()) + return ast.MakeSymbolName(name), ok } } - return "", false + return ast.EmptySymbolName, false } -func tryGetNameFromType(t *Type) (string, bool) { +func tryGetNameFromType(t *Type) (ast.SymbolName, bool) { switch { case t.flags&TypeFlagsUniqueESSymbol != 0: return t.AsUniqueESSymbolType().name, true case t.flags&TypeFlagsStringOrNumberLiteral != 0: - return evaluator.AnyToString(t.AsLiteralType().value), true + return ast.MakeSymbolName(evaluator.AnyToString(t.AsLiteralType().value)), true } - return "", false + return ast.EmptySymbolName, false } -func (c *Checker) getDestructuringPropertyName(node *ast.Node) (string, bool) { +func (c *Checker) getDestructuringPropertyName(node *ast.Node) (ast.SymbolName, bool) { parent := node.Parent if ast.IsBindingElement(node) && ast.IsObjectBindingPattern(parent) { return c.getLiteralPropertyNameText(getBindingElementPropertyName(node)) @@ -1798,17 +1799,17 @@ func (c *Checker) getDestructuringPropertyName(node *ast.Node) (string, bool) { return c.getLiteralPropertyNameText(node.Name()) } if ast.IsArrayLiteralExpression(parent) || ast.IsArrayBindingPattern(parent) { - return strconv.Itoa(slices.Index(parent.Elements(), node)), true + return ast.MakeSymbolName(strconv.Itoa(slices.Index(parent.Elements(), node))), true } - return "", false + return ast.EmptySymbolName, false } -func (c *Checker) getLiteralPropertyNameText(name *ast.Node) (string, bool) { +func (c *Checker) getLiteralPropertyNameText(name *ast.Node) (ast.SymbolName, bool) { t := c.getLiteralTypeFromPropertyName(name) if t.flags&(TypeFlagsStringLiteral|TypeFlagsNumberLiteral) != 0 { - return evaluator.AnyToString(t.AsLiteralType().value), true + return ast.MakeSymbolName(evaluator.AnyToString(t.AsLiteralType().value)), true } - return "", false + return ast.EmptySymbolName, false } func (c *Checker) isConstantReference(node *ast.Node) bool { @@ -2091,7 +2092,7 @@ func (c *Checker) getEffectsSignature(node *ast.Node) *Signature { * Get the type of the `[Symbol.hasInstance]` method of an object type. */ func (c *Checker) getSymbolHasInstanceMethodOfObjectType(t *Type) *Type { - hasInstancePropertyName := c.getPropertyNameForKnownSymbolName("hasInstance") + hasInstancePropertyName := c.getPropertyNameForKnownSymbolName(ast.SymbolNameHasInstance) if c.allTypesAssignableToKind(t, TypeFlagsNonPrimitive) { hasInstanceProperty := c.getPropertyOfType(t, hasInstancePropertyName) if hasInstanceProperty != nil { @@ -2104,7 +2105,7 @@ func (c *Checker) getSymbolHasInstanceMethodOfObjectType(t *Type) *Type { return nil } -func (c *Checker) getPropertyNameForKnownSymbolName(symbolName string) string { +func (c *Checker) getPropertyNameForKnownSymbolName(symbolName ast.SymbolName) ast.SymbolName { ctorType := c.getGlobalESSymbolConstructorSymbolOrNil() if ctorType != nil { uniqueType := c.getTypeOfPropertyOfType(c.getTypeOfSymbol(ctorType), symbolName) @@ -2112,7 +2113,7 @@ func (c *Checker) getPropertyNameForKnownSymbolName(symbolName string) string { return getPropertyNameFromType(uniqueType) } } - return ast.InternalSymbolNamePrefix + "@" + symbolName + return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "@" + symbolName.Value()) } // We require the dotted function name in an assertion expression to be comprised of identifiers @@ -2139,7 +2140,7 @@ func (c *Checker) getTypeOfDottedName(node *ast.Node, diagnostic *ast.Diagnostic prop = c.getPropertyOfType(t, binder.GetSymbolNameForPrivateIdentifier(t.symbol, name.Text())) } } else { - prop = c.getPropertyOfType(t, name.Text()) + prop = c.getPropertyOfType(t, name.TextSymbolName()) } if prop != nil { return c.getExplicitTypeOfSymbol(prop, diagnostic) @@ -2465,10 +2466,11 @@ func (c *Checker) getTypePredicateArgument(predicate *TypePredicate, callExpress func (c *Checker) getFlowTypeInConstructor(symbol *ast.Symbol, constructor *ast.Node) *Type { var accessName *ast.Node - if strings.HasPrefix(symbol.Name(), ast.InternalSymbolNamePrefix+"#") { - accessName = c.factory.NewPrivateIdentifier(symbol.Name()[strings.Index(symbol.Name(), "@")+1:]) + if strings.HasPrefix(symbol.Name().Value(), ast.InternalSymbolNamePrefix+"#") { + name := symbol.Name().Value() + accessName = c.factory.NewPrivateIdentifier(name[strings.Index(name, "@")+1:]) } else { - accessName = c.factory.NewIdentifier(symbol.Name()) + accessName = c.factory.NewIdentifier(symbol.Name().Value()) } reference := c.factory.NewPropertyAccessExpression(c.factory.NewKeywordExpression(ast.KindThisKeyword), nil, accessName, ast.NodeFlagsNone) reference.Expression().Parent = reference @@ -2487,10 +2489,11 @@ func (c *Checker) getFlowTypeInConstructor(symbol *ast.Symbol, constructor *ast. func (c *Checker) getFlowTypeInStaticBlocks(symbol *ast.Symbol, staticBlocks []*ast.Node) *Type { var accessName *ast.Node - if strings.HasPrefix(symbol.Name(), ast.InternalSymbolNamePrefix+"#") { - accessName = c.factory.NewPrivateIdentifier(symbol.Name()[strings.Index(symbol.Name(), "@")+1:]) + if strings.HasPrefix(symbol.Name().Value(), ast.InternalSymbolNamePrefix+"#") { + name := symbol.Name().Value() + accessName = c.factory.NewPrivateIdentifier(name[strings.Index(name, "@")+1:]) } else { - accessName = c.factory.NewIdentifier(symbol.Name()) + accessName = c.factory.NewIdentifier(symbol.Name().Value()) } for _, staticBlock := range staticBlocks { reference := c.factory.NewPropertyAccessExpression(c.factory.NewKeywordExpression(ast.KindThisKeyword), nil, accessName, ast.NodeFlagsNone) diff --git a/tsc/internal/checker/grammarchecks.go b/tsc/internal/checker/grammarchecks.go index 93bed4b355296..ba5544aaf0887 100644 --- a/tsc/internal/checker/grammarchecks.go +++ b/tsc/internal/checker/grammarchecks.go @@ -996,7 +996,7 @@ func (c *Checker) checkGrammarForInvalidExclamationToken(postfixToken *ast.Token } func (c *Checker) checkGrammarObjectLiteralExpression(node *ast.ObjectLiteralExpression, inDestructuring bool) bool { - seen := make(map[string]DeclarationMeaning) + seen := make(map[ast.SymbolName]DeclarationMeaning) var properties []*ast.Node if node.Properties != nil { diff --git a/tsc/internal/checker/inference.go b/tsc/internal/checker/inference.go index 02c7d009b9ec5..39344d1967784 100644 --- a/tsc/internal/checker/inference.go +++ b/tsc/internal/checker/inference.go @@ -1244,13 +1244,13 @@ func (c *Checker) createEmptyObjectTypeFromStringLiteral(t *Type) *Type { continue } name := getStringLiteralValue(t) - literalProp := c.newSymbol(ast.SymbolFlagsProperty, name) + literalProp := c.newSymbol(ast.SymbolFlagsProperty, ast.MakeSymbolName(name)) c.valueSymbolLinks.Get(literalProp).resolvedType = c.anyType if t.symbol != nil { literalProp.SetDeclarations(t.symbol.Declarations()) literalProp.SetValueDeclaration(t.symbol.ValueDeclaration()) } - members[name] = literalProp + members[ast.MakeSymbolName(name)] = literalProp } var indexInfos []*IndexInfo if t.flags&TypeFlagsString != 0 { diff --git a/tsc/internal/checker/jsx.go b/tsc/internal/checker/jsx.go index 7f35f796957cf..ce6b5b7a04ad1 100644 --- a/tsc/internal/checker/jsx.go +++ b/tsc/internal/checker/jsx.go @@ -40,27 +40,27 @@ type JsxElementLinks struct { } var JsxNames = struct { - JSX string - IntrinsicElements string - ElementClass string - ElementAttributesPropertyNameContainer string - ElementChildrenAttributeNameContainer string - Element string - ElementType string - IntrinsicAttributes string - IntrinsicClassAttributes string - LibraryManagedAttributes string + JSX ast.SymbolName + IntrinsicElements ast.SymbolName + ElementClass ast.SymbolName + ElementAttributesPropertyNameContainer ast.SymbolName + ElementChildrenAttributeNameContainer ast.SymbolName + Element ast.SymbolName + ElementType ast.SymbolName + IntrinsicAttributes ast.SymbolName + IntrinsicClassAttributes ast.SymbolName + LibraryManagedAttributes ast.SymbolName }{ - JSX: "JSX", - IntrinsicElements: "IntrinsicElements", - ElementClass: "ElementClass", - ElementAttributesPropertyNameContainer: "ElementAttributesProperty", - ElementChildrenAttributeNameContainer: "ElementChildrenAttribute", - Element: "Element", - ElementType: "ElementType", - IntrinsicAttributes: "IntrinsicAttributes", - IntrinsicClassAttributes: "IntrinsicClassAttributes", - LibraryManagedAttributes: "LibraryManagedAttributes", + JSX: ast.SymbolNameJSX, + IntrinsicElements: ast.SymbolNameIntrinsicElements, + ElementClass: ast.SymbolNameElementClass, + ElementAttributesPropertyNameContainer: ast.SymbolNameElementAttributesProperty, + ElementChildrenAttributeNameContainer: ast.SymbolNameElementChildrenAttribute, + Element: ast.SymbolNameElement, + ElementType: ast.SymbolNameElementType, + IntrinsicAttributes: ast.SymbolNameIntrinsicAttributes, + IntrinsicClassAttributes: ast.SymbolNameIntrinsicClassAttributes, + LibraryManagedAttributes: ast.SymbolNameLibraryManagedAttributes, } var ReactNames = struct { @@ -221,7 +221,7 @@ func (c *Checker) getContextualTypeForJsxAttribute(attribute *ast.Node, contextF if attributesType == nil || IsTypeAny(attributesType) { return nil } - return c.getTypeOfPropertyOfContextualType(attributesType, attribute.Name().Text()) + return c.getTypeOfPropertyOfContextualType(attributesType, attribute.Name().TextSymbolName()) } return c.getContextualType(attribute.Parent, contextFlags) } @@ -243,7 +243,7 @@ func (c *Checker) getContextualTypeForChildJsxExpression(node *ast.Node, child * attributesType := c.getApparentTypeOfContextualType(node.AsJsxElement().OpeningElement.Attributes(), contextFlags) // JSX expression is in children of JSX Element, we will look for an "children" attribute (we get the name from JSX.ElementAttributesProperty) jsxChildrenPropertyName := c.getJsxElementChildrenPropertyName(c.getJsxNamespaceAt(node)) - if !(attributesType != nil && !IsTypeAny(attributesType) && jsxChildrenPropertyName != ast.InternalSymbolNameMissing && jsxChildrenPropertyName != "") { + if !(attributesType != nil && !IsTypeAny(attributesType) && jsxChildrenPropertyName != ast.InternalSymbolNameMissing && jsxChildrenPropertyName != ast.EmptySymbolName) { return nil } realChildren := ast.GetSemanticJsxChildren(node.Children().Nodes) @@ -307,9 +307,9 @@ func (c *Checker) elaborateJsxComponents(node *ast.Node, source *Type, target *T containingElement := node.Parent.Parent // Containing JSXElement childrenPropName := c.getJsxElementChildrenPropertyName(c.getJsxNamespaceAt(node)) if childrenPropName == ast.InternalSymbolNameMissing { - childrenPropName = "children" + childrenPropName = ast.SymbolNameChildren } - childrenNameType := c.getStringLiteralType(childrenPropName) + childrenNameType := c.getStringLiteralType(childrenPropName.Value()) childrenTargetType := c.getIndexedAccessType(target, childrenNameType) validChildren := ast.GetSemanticJsxChildren(containingElement.Children().Nodes) if len(validChildren) == 0 { @@ -333,7 +333,7 @@ func (c *Checker) elaborateJsxComponents(node *ast.Node, source *Type, target *T if invalidTextDiagnostic == nil { tagNameText := scanner.GetTextOfNode(node.Parent.TagName()) invalidTextDiagnostic = diagnostics.X_0_components_don_t_accept_text_as_child_elements_Text_in_JSX_has_the_type_string_but_the_expected_type_of_1_is_2 - invalidTextDiagnosticArgs = []any{tagNameText, childrenPropName, c.TypeToString(childrenTargetType)} + invalidTextDiagnosticArgs = []any{tagNameText, childrenPropName.Value(), c.TypeToString(childrenTargetType)} } return invalidTextDiagnostic, invalidTextDiagnosticArgs } @@ -344,7 +344,7 @@ func (c *Checker) elaborateJsxComponents(node *ast.Node, source *Type, target *T reportedError = c.elaborateIterableOrArrayLikeTargetElementwise(children, realSource, arrayLikeTargetParts, relation, diagnosticOutput) || reportedError } else if !c.isTypeRelatedTo(c.getIndexedAccessType(source, childrenNameType), childrenTargetType, relation) { // arity mismatch - diag := c.error(containingElement.AsJsxElement().OpeningElement.TagName(), diagnostics.This_JSX_tag_s_0_prop_expects_a_single_child_of_type_1_but_multiple_children_were_provided, childrenPropName, c.TypeToString(childrenTargetType)) + diag := c.error(containingElement.AsJsxElement().OpeningElement.TagName(), diagnostics.This_JSX_tag_s_0_prop_expects_a_single_child_of_type_1_but_multiple_children_were_provided, childrenPropName.Value(), c.TypeToString(childrenTargetType)) c.reportDiagnostic(diag, diagnosticOutput) reportedError = true } @@ -357,7 +357,7 @@ func (c *Checker) elaborateJsxComponents(node *ast.Node, source *Type, target *T } } else if !c.isTypeRelatedTo(c.getIndexedAccessType(source, childrenNameType), childrenTargetType, relation) { // arity mismatch - diag := c.error(containingElement.AsJsxElement().OpeningElement.TagName(), diagnostics.This_JSX_tag_s_0_prop_expects_type_1_which_requires_multiple_children_but_only_a_single_child_was_provided, childrenPropName, c.TypeToString(childrenTargetType)) + diag := c.error(containingElement.AsJsxElement().OpeningElement.TagName(), diagnostics.This_JSX_tag_s_0_prop_expects_type_1_which_requires_multiple_children_but_only_a_single_child_was_provided, childrenPropName.Value(), c.TypeToString(childrenTargetType)) c.reportDiagnostic(diag, diagnosticOutput) reportedError = true } @@ -482,14 +482,14 @@ func (c *Checker) elaborateIterableOrArrayLikeTargetElementwise(iterator iter.Se return reportedError } -func (c *Checker) getSuggestedSymbolForNonexistentJSXAttribute(name string, containingType *Type) *ast.Symbol { +func (c *Checker) getSuggestedSymbolForNonexistentJSXAttribute(name ast.SymbolName, containingType *Type) *ast.Symbol { properties := c.getPropertiesOfType(containingType) var jsxSpecific *ast.Symbol switch name { - case "for": - jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return ast.SymbolName(x) == "htmlFor" }) - case "class": - jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return ast.SymbolName(x) == "className" }) + case ast.SymbolNameFor: + jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return x.Name() == ast.SymbolNameHtmlFor }) + case ast.SymbolNameClass: + jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return x.Name() == ast.SymbolNameClassName }) } if jsxSpecific != nil { return jsxSpecific @@ -517,13 +517,13 @@ func (c *Checker) getJSXFragmentType(node *ast.Node) *Type { if !shouldModuleRefErr { flags &^= ast.SymbolFlagsEnum } - jsxFactorySymbol = c.resolveName(node, jsxFragmentFactoryName, flags, diagnostics.Using_JSX_fragments_requires_fragment_factory_0_to_be_in_scope_but_it_could_not_be_found, true /*isUse*/, false /*excludeGlobals*/) + jsxFactorySymbol = c.resolveName(node, ast.MakeSymbolName(jsxFragmentFactoryName), flags, diagnostics.Using_JSX_fragments_requires_fragment_factory_0_to_be_in_scope_but_it_could_not_be_found, true /*isUse*/, false /*excludeGlobals*/) } if jsxFactorySymbol == nil { links.jsxFragmentType = c.errorType return links.jsxFragmentType } - if jsxFactorySymbol.Name() == ReactNames.Fragment { + if jsxFactorySymbol.Name() == ast.MakeSymbolName(ReactNames.Fragment) { links.jsxFragmentType = c.getTypeOfSymbol(jsxFactorySymbol) return links.jsxFragmentType } @@ -533,7 +533,7 @@ func (c *Checker) getJSXFragmentType(node *ast.Node) *Type { } reactExports := c.getExportsOfSymbol(resolvedAlias) - typeSymbol := c.getSymbol(reactExports, ReactNames.Fragment, ast.SymbolFlagsBlockScopedVariable) + typeSymbol := c.getSymbol(reactExports, ast.MakeSymbolName(ReactNames.Fragment), ast.SymbolFlagsBlockScopedVariable) if typeSymbol != nil { links.jsxFragmentType = c.getTypeOfSymbol(typeSymbol) } else { @@ -754,7 +754,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme if allAttributesTable != nil { allAttributesTable[attributeSymbol.Name()] = attributeSymbol } - if attributeDecl.Name().Text() == jsxChildrenPropertyName { + if attributeDecl.Name().TextSymbolName() == jsxChildrenPropertyName { explicitlySpecifyChildrenAttribute = true } if contextualType != nil && checkMode&CheckModeInferential != 0 && checkMode&CheckModeSkipContextSensitive == 0 && c.isContextSensitive(attributeDecl) { @@ -818,12 +818,12 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme } if parentHasSemanticJsxChildren(openingLikeElement) { var childTypes []*Type = c.checkJsxChildren(openingLikeElement.Parent, checkMode) - if !hasSpreadAnyType && jsxChildrenPropertyName != ast.InternalSymbolNameMissing && jsxChildrenPropertyName != "" { + if !hasSpreadAnyType && jsxChildrenPropertyName != ast.InternalSymbolNameMissing && jsxChildrenPropertyName != ast.EmptySymbolName { // Error if there is a attribute named "children" explicitly specified and children element. // This is because children element will overwrite the value from attributes. // Note: we will not warn "children" attribute overwritten if "children" attribute is specified in object spread. if explicitlySpecifyChildrenAttribute { - c.error(attributeParent, diagnostics.X_0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName) + c.error(attributeParent, diagnostics.X_0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName.Value()) } var childrenContextualType *Type if ast.IsJsxOpeningElement(openingLikeElement) { @@ -843,7 +843,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme links.resolvedType = c.createArrayType(c.getUnionType(childTypes)) } // Fake up a property declaration for the children - childrenPropSymbol.SetValueDeclaration(c.factory.NewPropertySignatureDeclaration(nil, c.factory.NewIdentifier(jsxChildrenPropertyName), nil /*postfixToken*/, nil /*type*/, nil /*initializer*/)) + childrenPropSymbol.SetValueDeclaration(c.factory.NewPropertySignatureDeclaration(nil, c.factory.NewIdentifier(jsxChildrenPropertyName.Value()), nil /*postfixToken*/, nil /*type*/, nil /*initializer*/)) childrenPropSymbol.ValueDeclaration().Parent = attributeParent childrenPropSymbol.ValueDeclaration().AsPropertySignatureDeclaration().Symbol = childrenPropSymbol childPropMap := make(ast.SymbolTable) @@ -900,7 +900,7 @@ func (c *Checker) getUninstantiatedJsxSignaturesOfType(elementType *Type, caller if elementType.flags&TypeFlagsStringLiteral != 0 { intrinsicType := c.getIntrinsicAttributesTypeFromStringLiteralType(elementType, caller) if intrinsicType == nil { - c.error(caller, diagnostics.Property_0_does_not_exist_on_type_1, getStringLiteralValue(elementType), "JSX."+JsxNames.IntrinsicElements) + c.error(caller, diagnostics.Property_0_does_not_exist_on_type_1, getStringLiteralValue(elementType), "JSX."+JsxNames.IntrinsicElements.Value()) return nil } fakeSignature := c.createSignatureForJSXIntrinsic(caller, intrinsicType) @@ -946,13 +946,13 @@ func (c *Checker) getJsxPropsTypeFromClassType(sig *Signature, context *ast.Node switch forcedLookupLocation { case ast.InternalSymbolNameMissing: attributesType = c.getTypeOfFirstParameterOfSignatureWithFallback(sig, c.unknownType) - case "": + case ast.EmptySymbolName: attributesType = c.getReturnTypeOfSignature(sig) default: attributesType = c.getJsxPropsTypeForSignatureFromMember(sig, forcedLookupLocation) if attributesType == nil && len(context.Attributes().Properties()) != 0 { // There is no property named 'props' on this instance type - c.error(context, diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, forcedLookupLocation) + c.error(context, diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, forcedLookupLocation.Value()) } } if attributesType == nil { @@ -986,7 +986,7 @@ func (c *Checker) getJsxPropsTypeFromClassType(sig *Signature, context *ast.Node return apparentAttributesType } -func (c *Checker) getJsxPropsTypeForSignatureFromMember(sig *Signature, forcedLookupLocation string) *Type { +func (c *Checker) getJsxPropsTypeForSignatureFromMember(sig *Signature, forcedLookupLocation ast.SymbolName) *Type { if sig.getComposite() != nil { // JSX Elements using the legacy `props`-field based lookup (eg, react class components) need to treat the `props` member as an input // instead of an output position when resolving the signature. We need to go back to the input signatures of the composite signature, @@ -1070,14 +1070,14 @@ func (c *Checker) getJsxElementTypeSymbol(jsxNamespace *ast.Symbol) *ast.Symbol // or "" if it has 0 properties (which means every // // non-intrinsic elements' attributes type is the element instance type) -func (c *Checker) getJsxElementPropertiesName(jsxNamespace *ast.Symbol) string { +func (c *Checker) getJsxElementPropertiesName(jsxNamespace *ast.Symbol) ast.SymbolName { return c.getNameFromJsxElementAttributesContainer(JsxNames.ElementAttributesPropertyNameContainer, jsxNamespace) } -func (c *Checker) getJsxElementChildrenPropertyName(jsxNamespace *ast.Symbol) string { +func (c *Checker) getJsxElementChildrenPropertyName(jsxNamespace *ast.Symbol) ast.SymbolName { if c.compilerOptions.Jsx == core.JsxEmitReactJSX || c.compilerOptions.Jsx == core.JsxEmitReactJSXDev { // In these JsxEmit modes the children property is fixed to 'children' - return "children" + return ast.SymbolNameChildren } return c.getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace) } @@ -1088,7 +1088,7 @@ func (c *Checker) getJsxElementChildrenPropertyName(jsxNamespace *ast.Symbol) st // @param nameOfAttribPropContainer a string of value JsxNames.ElementAttributesPropertyNameContainer or JsxNames.ElementChildrenAttributeNameContainer // // if other string is given or the container doesn't exist, return undefined. -func (c *Checker) getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer string, jsxNamespace *ast.Symbol) string { +func (c *Checker) getNameFromJsxElementAttributesContainer(nameOfAttribPropContainer ast.SymbolName, jsxNamespace *ast.Symbol) ast.SymbolName { // JSX.ElementAttributesProperty | JSX.ElementChildrenAttribute [symbol] if jsxNamespace != nil { jsxElementAttribPropInterfaceSym := c.getSymbol(jsxNamespace.Exports(), nameOfAttribPropContainer, ast.SymbolFlagsType) @@ -1097,14 +1097,14 @@ func (c *Checker) getNameFromJsxElementAttributesContainer(nameOfAttribPropConta propertiesOfJsxElementAttribPropInterface := c.getPropertiesOfType(jsxElementAttribPropInterfaceType) // Element Attributes has zero properties, so the element attributes type will be the class instance type if len(propertiesOfJsxElementAttribPropInterface) == 0 { - return "" + return ast.EmptySymbolName } if len(propertiesOfJsxElementAttribPropInterface) == 1 { return propertiesOfJsxElementAttribPropInterface[0].Name() } if len(propertiesOfJsxElementAttribPropInterface) > 1 && len(jsxElementAttribPropInterfaceSym.Declarations()) != 0 { // More than one property on ElementAttributesProperty is an error - c.error(jsxElementAttribPropInterfaceSym.Declarations()[0], diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, nameOfAttribPropContainer) + c.error(jsxElementAttribPropInterfaceSym.Declarations()[0], diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, nameOfAttribPropContainer.Value()) } } } @@ -1140,7 +1140,7 @@ func (c *Checker) getIntrinsicAttributesTypeFromStringLiteralType(t *Type, locat intrinsicElementsType := c.getJsxType(JsxNames.IntrinsicElements, location) if !c.isErrorType(intrinsicElementsType) { stringLiteralTypeName := getStringLiteralValue(t) - intrinsicProp := c.getPropertyOfType(intrinsicElementsType, stringLiteralTypeName) + intrinsicProp := c.getPropertyOfType(intrinsicElementsType, ast.MakeSymbolName(stringLiteralTypeName)) if intrinsicProp != nil { return c.getTypeOfSymbol(intrinsicProp) } @@ -1177,7 +1177,7 @@ func (c *Checker) createSignatureForJSXIntrinsic(node *ast.Node, result *Type) * } // returnNode := typeSymbol && c.nodeBuilder.symbolToEntityName(typeSymbol, ast.SymbolFlagsType, node) // declaration := factory.createFunctionTypeNode(nil, []ParameterDeclaration{factory.createParameterDeclaration(nil, nil /*dotDotDotToken*/, "props", nil /*questionToken*/, c.nodeBuilder.typeToTypeNode(result, node))}, ifElse(returnNode != nil, factory.createTypeReferenceNode(returnNode, nil /*typeArguments*/), factory.createKeywordTypeNode(ast.KindAnyKeyword))) - parameterSymbol := c.newSymbol(ast.SymbolFlagsFunctionScopedVariable, "props") + parameterSymbol := c.newSymbol(ast.SymbolFlagsFunctionScopedVariable, ast.SymbolNameProps) c.valueSymbolLinks.Get(parameterSymbol).resolvedType = result return c.newSignature(SignatureFlagsNone, nil, nil, nil, []*ast.Symbol{parameterSymbol}, elementType, nil, 1) } @@ -1197,7 +1197,7 @@ func (c *Checker) getIntrinsicAttributesTypeFromJsxOpeningLikeElement(node *ast. return links.resolvedJsxElementAttributesType } if links.jsxFlags&JsxFlagsIntrinsicIndexedElement != 0 { - indexInfo := c.getApplicableIndexInfoForName(c.getJsxType(JsxNames.IntrinsicElements, node), node.TagName().Text()) + indexInfo := c.getApplicableIndexInfoForName(c.getJsxType(JsxNames.IntrinsicElements, node), node.TagName().TextSymbolName()) if indexInfo != nil { links.resolvedJsxElementAttributesType = indexInfo.valueType return links.resolvedJsxElementAttributesType @@ -1224,7 +1224,7 @@ func (c *Checker) getIntrinsicTagSymbol(node *ast.Node) *ast.Symbol { panic("Invalid tag name") } propName := tagName.Text() - intrinsicProp := c.getPropertyOfType(intrinsicElementsType, propName) + intrinsicProp := c.getPropertyOfType(intrinsicElementsType, ast.MakeSymbolName(propName)) if intrinsicProp != nil { c.jsxElementLinks.Get(node).jsxFlags |= JsxFlagsIntrinsicNamedElement links.resolvedSymbol = intrinsicProp @@ -1237,18 +1237,18 @@ func (c *Checker) getIntrinsicTagSymbol(node *ast.Node) *ast.Symbol { links.resolvedSymbol = indexSymbol return links.resolvedSymbol } - if c.getTypeOfPropertyOrIndexSignatureOfType(intrinsicElementsType, propName) != nil { + if c.getTypeOfPropertyOrIndexSignatureOfType(intrinsicElementsType, ast.MakeSymbolName(propName)) != nil { c.jsxElementLinks.Get(node).jsxFlags |= JsxFlagsIntrinsicIndexedElement links.resolvedSymbol = intrinsicElementsType.symbol return links.resolvedSymbol } // Wasn't found - c.error(node, diagnostics.Property_0_does_not_exist_on_type_1, tagName.Text(), "JSX."+JsxNames.IntrinsicElements) + c.error(node, diagnostics.Property_0_does_not_exist_on_type_1, tagName.Text(), "JSX."+JsxNames.IntrinsicElements.Value()) links.resolvedSymbol = c.unknownSymbol return links.resolvedSymbol } if c.noImplicitAny { - c.error(node, diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements) + c.error(node, diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements.Value()) } links.resolvedSymbol = c.unknownSymbol return links.resolvedSymbol @@ -1290,7 +1290,7 @@ func (c *Checker) getJsxElementTypeTypeAt(location *ast.Node) *Type { return t } -func (c *Checker) getJsxType(name string, location *ast.Node) *Type { +func (c *Checker) getJsxType(name ast.SymbolName, location *ast.Node) *Type { if namespace := c.getJsxNamespaceAt(location); namespace != nil { if exports := c.getExportsOfSymbol(namespace); exports != nil { if typeSymbol := c.getSymbol(exports, name, ast.SymbolFlagsType); typeSymbol != nil { @@ -1313,7 +1313,7 @@ func (c *Checker) getJsxNamespaceAt(location *ast.Node) *ast.Symbol { resolvedNamespace := c.getJsxNamespaceContainerForImplicitImport(location) if resolvedNamespace == nil || resolvedNamespace == c.unknownSymbol { namespaceName := c.getJsxNamespace(location) - resolvedNamespace = c.resolveName(location, namespaceName, ast.SymbolFlagsNamespace, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) + resolvedNamespace = c.resolveName(location, ast.MakeSymbolName(namespaceName), ast.SymbolFlagsNamespace, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } if resolvedNamespace != nil { candidate := c.resolveSymbol(c.getSymbol(c.getExportsOfSymbol(c.resolveSymbol(resolvedNamespace)), JsxNames.JSX, ast.SymbolFlagsNamespace)) diff --git a/tsc/internal/checker/nodebuilder_hover.go b/tsc/internal/checker/nodebuilder_hover.go index b048c5d1618c6..0a19b8c1ba1c1 100644 --- a/tsc/internal/checker/nodebuilder_hover.go +++ b/tsc/internal/checker/nodebuilder_hover.go @@ -50,7 +50,7 @@ func (b *NodeBuilderImpl) expandSymbolForHover(symbol *ast.Symbol) []*ast.Node { // expandEnumDecl produces an EnumDeclaration node with all members. func (b *NodeBuilderImpl) expandEnumDecl(symbol *ast.Symbol) *ast.Node { - name := ast.SymbolName(symbol) + name := ast.SymbolNameText(symbol) b.ctx.approximateLength += 9 + len(name) memberProps := core.Filter(b.ch.getPropertiesOfType(b.ch.getTypeOfSymbol(symbol)), func(p *ast.Symbol) bool { return p.Flags()&ast.SymbolFlagsEnumMember != 0 @@ -61,7 +61,7 @@ func (b *NodeBuilderImpl) expandEnumDecl(symbol *ast.Symbol) *ast.Node { b.ctx.expansionTruncated = true members = append(members, b.f.NewEnumMember(b.f.NewStringLiteral(fmt.Sprintf(" ... %d more ... ", len(memberProps)-i-1), 0), nil)) last := memberProps[len(memberProps)-1] - members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(last.Name()), b.enumMemberInitializer(last))) + members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(last.Name().Value()), b.enumMemberInitializer(last))) break } memberDecl := core.Find(p.Declarations(), ast.IsEnumMember) @@ -71,11 +71,11 @@ func (b *NodeBuilderImpl) expandEnumDecl(symbol *ast.Symbol) *ast.Node { } else { initializer = b.enumMemberInitializer(p) } - b.ctx.approximateLength += 4 + len(p.Name()) + b.ctx.approximateLength += 4 + len(p.Name().Value()) if initializer != nil { b.ctx.approximateLength += 5 // " = " + value estimate } - members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(p.Name()), initializer)) + members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(p.Name().Value()), initializer)) } constModifier := ast.ModifierFlagsNone @@ -109,7 +109,7 @@ func (b *NodeBuilderImpl) enumMemberInitializer(p *ast.Symbol) *ast.Node { // expandClassDecl produces a ClassDeclaration node with heritage clauses and members. func (b *NodeBuilderImpl) expandClassDecl(symbol *ast.Symbol) *ast.Node { - name := ast.SymbolName(symbol) + name := ast.SymbolNameText(symbol) b.ctx.approximateLength += 9 + len(name) classLikeDeclarations := core.Filter(symbol.Declarations(), ast.IsClassLike) @@ -152,7 +152,7 @@ func (b *NodeBuilderImpl) expandClassDecl(symbol *ast.Symbol) *ast.Node { // Static members staticProps := core.Filter(b.ch.getPropertiesOfType(staticType), func(p *ast.Symbol) bool { - return p.Flags()&ast.SymbolFlagsPrototype == 0 && p.Name() != "prototype" && !b.isNamespaceMember(p) + return p.Flags()&ast.SymbolFlagsPrototype == 0 && p.Name() != ast.SymbolNamePrototype && !b.isNamespaceMember(p) }) var staticMembers []*ast.Node staticMembers = b.serializePropertiesWithTruncation(staticProps, staticMembers) @@ -232,7 +232,7 @@ func typeElementsToClassElements(f *ast.NodeFactory, members []*ast.Node) []*ast // Reuses addPropertyToElementList for property serialization and // signatureToSignatureDeclarationHelper for signatures. func (b *NodeBuilderImpl) expandInterfaceDecl(symbol *ast.Symbol) *ast.Node { - name := ast.SymbolName(symbol) + name := ast.SymbolNameText(symbol) b.ctx.approximateLength += 14 + len(name) interfaceType := b.ch.getDeclaredTypeOfClassOrInterface(symbol) @@ -418,7 +418,7 @@ func (b *NodeBuilderImpl) expandModuleDecl(symbol *ast.Symbol) *ast.Node { if !b.isNamespaceMember(sym) { continue } - if !scanner.IsIdentifierText(sym.Name(), core.LanguageVariantStandard) { + if !scanner.IsIdentifierText(sym.Name().Value(), core.LanguageVariantStandard) { continue } members = append(members, sym) @@ -457,24 +457,24 @@ func (b *NodeBuilderImpl) expandModuleDecl(symbol *ast.Symbol) *ast.Node { if target.Flags()&(ast.SymbolFlagsBlockScopedVariable|ast.SymbolFlagsFunctionScopedVariable|ast.SymbolFlagsProperty) != 0 { if emittedLocals.AddIfAbsent(target) { localType := b.ch.getWidenedType(b.ch.getTypeOfSymbol(target)) - b.ctx.approximateLength += len(target.Name()) + 5 + b.ctx.approximateLength += len(target.Name().Value()) + 5 localStmt := b.f.NewVariableStatement(nil, b.f.NewVariableDeclarationList(b.f.NewNodeList([]*ast.Node{ - b.f.NewVariableDeclaration(b.f.NewIdentifier(target.Name()), nil, b.serializeTypeForDeclaration(nil, localType, target, true), nil), + b.f.NewVariableDeclaration(b.f.NewIdentifier(target.Name().Value()), nil, b.serializeTypeForDeclaration(nil, localType, target, true), nil), }), ast.NodeFlagsLet)) bodyStmts = append(bodyStmts, hoverStatement{node: localStmt, isLocal: true}) } } targetName := target.Name() - b.ctx.approximateLength += 16 + len(m.Name()) + b.ctx.approximateLength += 16 + len(m.Name().Value()) var propertyName *ast.Node if m.Name() != targetName { - propertyName = b.f.NewIdentifier(targetName) + propertyName = b.f.NewIdentifier(targetName.Value()) } stmt := b.f.NewExportDeclaration( nil, false, b.f.NewNamedExports(b.f.NewNodeList([]*ast.Node{ - b.f.NewExportSpecifier(false, propertyName, b.f.NewIdentifier(m.Name())), + b.f.NewExportSpecifier(false, propertyName, b.f.NewIdentifier(m.Name().Value())), })), nil, nil, ) @@ -492,7 +492,7 @@ func (b *NodeBuilderImpl) expandModuleDecl(symbol *ast.Symbol) *ast.Node { for _, sig := range sigs { b.ctx.approximateLength++ decl := b.signatureToSignatureDeclarationHelper(sig, ast.KindFunctionDeclaration, &SignatureToSignatureDeclarationOptions{ - name: b.f.NewIdentifier(m.Name()), + name: b.f.NewIdentifier(m.Name().Value()), }) bodyStmts = append(bodyStmts, hoverStatement{node: decl}) } @@ -500,13 +500,13 @@ func (b *NodeBuilderImpl) expandModuleDecl(symbol *ast.Symbol) *ast.Node { merged := b.ch.getMergedSymbol(resolved) hasModuleExports := merged.Flags()&(ast.SymbolFlagsValueModule|ast.SymbolFlagsNamespaceModule) != 0 && merged.Exports() != nil && len(merged.Exports()) != 0 if !hasModuleExports { - bodyStmts = append(bodyStmts, hoverStatement{node: b.f.NewModuleDeclaration(nil, ast.KindNamespaceKeyword, b.f.NewIdentifier(m.Name()), nil /*attributes*/, b.f.NewModuleBlock(b.f.NewNodeList(nil)))}) + bodyStmts = append(bodyStmts, hoverStatement{node: b.f.NewModuleDeclaration(nil, ast.KindNamespaceKeyword, b.f.NewIdentifier(m.Name().Value()), nil /*attributes*/, b.f.NewModuleBlock(b.f.NewNodeList(nil)))}) } continue } // Handle remaining member kinds (type alias, enum, class, interface, namespace, variable) - if node := b.serializeNamespaceMember(resolved, m.Name()); node != nil { + if node := b.serializeNamespaceMember(resolved, m.Name().Value()); node != nil { bodyStmts = append(bodyStmts, hoverStatement{node: node}) } } @@ -573,12 +573,12 @@ func (b *NodeBuilderImpl) filterInheritedProperties(t *Type, baseTypes []*Type, return properties } // Build a lookup from property name to symbol for parent-identity comparison. - propsByName := make(map[string]*ast.Symbol, len(properties)) + propsByName := make(ast.SymbolTable, len(properties)) for _, p := range properties { propsByName[p.Name()] = p } // Collect names of properties inherited unchanged from base types. - var inherited collections.Set[string] + var inherited collections.Set[ast.SymbolName] for _, base := range baseTypes { baseWithThis := b.ch.getTypeWithThisArgument(base, b.ch.getTargetType(t).AsInterfaceType().thisType, false) for _, prop := range b.ch.getPropertiesOfType(baseWithThis) { @@ -597,7 +597,7 @@ func (b *NodeBuilderImpl) filterInheritedProperties(t *Type, baseTypes []*Type, func (b *NodeBuilderImpl) isNamespaceMember(p *ast.Symbol) bool { return p.Flags()&(ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias) != 0 || - !(p.Flags()&ast.SymbolFlagsPrototype != 0 || p.Name() == "prototype" || (p.ValueDeclaration() != nil && ast.HasStaticModifier(p.ValueDeclaration()) && ast.IsClassLike(p.ValueDeclaration().Parent))) + !(p.Flags()&ast.SymbolFlagsPrototype != 0 || p.Name() == ast.SymbolNamePrototype || (p.ValueDeclaration() != nil && ast.HasStaticModifier(p.ValueDeclaration()) && ast.IsClassLike(p.ValueDeclaration().Parent))) } func isHashPrivate(s *ast.Symbol) bool { diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 3d84ff3bd4094..96a2ecc27d5f6 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -90,8 +90,8 @@ type NodeBuilderContext struct { // per signature scope state typeParameterNames collections.CopyOnWriteMap[TypeId, *ast.Identifier] - typeParameterNamesByText collections.CopyOnWriteSet[string] - typeParameterNamesByTextNextNameCount collections.CopyOnWriteMap[string, int] + typeParameterNamesByText collections.CopyOnWriteSet[ast.SymbolName] + typeParameterNamesByTextNextNameCount collections.CopyOnWriteMap[ast.SymbolName, int] typeParameterSymbolList collections.CopyOnWriteSet[ast.SymbolId] } @@ -383,9 +383,9 @@ func (b *NodeBuilderImpl) mapToTypeNodes(list []*Type, isBareList bool) *ast.Nod t *Type i int } - var seenNames *collections.MultiMap[string, seenName] + var seenNames *collections.MultiMap[ast.SymbolName, seenName] if mayHaveNameCollisions { - seenNames = &collections.MultiMap[string, seenName]{} + seenNames = &collections.MultiMap[ast.SymbolName, seenName]{} } result := make([]*ast.Node, 0, len(list)) @@ -410,7 +410,7 @@ func (b *NodeBuilderImpl) mapToTypeNodes(list []*Type, isBareList bool) *ast.Nod if typeNode != nil { result = append(result, typeNode) if seenNames != nil && isIdentifierTypeReference(typeNode) { - seenNames.Add(typeNode.AsTypeReferenceNode().TypeName.Text(), seenName{t, len(result) - 1}) + seenNames.Add(typeNode.AsTypeReferenceNode().TypeName.TextSymbolName(), seenName{t, len(result) - 1}) } } } @@ -641,7 +641,7 @@ func (b *NodeBuilderImpl) createEntityNameFromSymbolChain(chain []*ast.Symbol, i // TODO: Audit usages of symbolToEntityNameNode - they should probably all be symbolToName func (b *NodeBuilderImpl) symbolToEntityNameNode(symbol *ast.Symbol) *ast.EntityName { - identifier := b.newIdentifier(symbol.Name(), symbol) + identifier := b.newIdentifier(symbol.Name().Value(), symbol) if symbol.Parent() != nil { return b.f.NewQualifiedName(b.symbolToEntityNameNode(symbol.Parent()), identifier) } @@ -701,7 +701,7 @@ func (b *NodeBuilderImpl) symbolToTypeNode(symbol *ast.Symbol, mask ast.SymbolFl // If ultimately we can only name the symbol with a reference that dives into a `node_modules` folder, we should error // since declaration files with these kinds of references are liable to fail when published :( b.ctx.encounteredError = true - b.ctx.tracker.ReportLikelyUnsafeImportRequiredError(oldSpecifierResult.specifier.AsString(), symbol.Name()) + b.ctx.tracker.ReportLikelyUnsafeImportRequiredError(oldSpecifierResult.specifier.AsString(), symbol.Name().Value()) } } @@ -775,9 +775,9 @@ func (b *NodeBuilderImpl) createAccessFromSymbolChain(chain []*ast.Symbol, index // avoid exhaustive iteration in the common case res, ok := exports[symbol.Name()] if symbol.Name() != ast.InternalSymbolNameExportEquals && !isLateBoundName(symbol.Name()) && ok && res != nil && b.ch.getSymbolIfSameReference(res, symbol) != nil { - symbolName = symbol.Name() + symbolName = symbol.Name().Value() } else { - results := make(map[*ast.Symbol]string, 1) + results := make(map[*ast.Symbol]ast.SymbolName, 1) for name, ex := range exports { if b.ch.getSymbolIfSameReference(ex, symbol) != nil && !isLateBoundName(name) && name != ast.InternalSymbolNameExportEquals { results[ex] = name @@ -787,7 +787,7 @@ func (b *NodeBuilderImpl) createAccessFromSymbolChain(chain []*ast.Symbol, index resultSymbols := slices.Collect(maps.Keys(results)) if len(resultSymbols) > 0 { b.ch.sortSymbols(resultSymbols) - symbolName = results[resultSymbols[0]] + symbolName = results[resultSymbols[0]].Value() } } } @@ -1380,7 +1380,7 @@ func (b *NodeBuilderImpl) createImportAttributesForModuleSpecifier(result module if !isEmptyAttributesType { properties = slices.Clone(b.ch.getPropertiesOfType(result.importAttributesType)) } - slices.SortFunc(properties, func(a, b *ast.Symbol) int { return strings.Compare(a.Name(), b.Name()) }) + slices.SortFunc(properties, func(a, b *ast.Symbol) int { return strings.Compare(a.Name().Value(), b.Name().Value()) }) attributes := make([]*ast.Node, 0, len(properties)+1) resolutionMode := "" if importModeOverride != core.ResolutionModeNone { @@ -1396,14 +1396,14 @@ func (b *NodeBuilderImpl) createImportAttributesForModuleSpecifier(result module } value := getStringLiteralValue(propertyType) var nameNode *ast.Node - if scanner.IsIdentifierText(name, core.LanguageVariantStandard) { - nameNode = b.f.NewIdentifier(name) + if scanner.IsIdentifierText(name.Value(), core.LanguageVariantStandard) { + nameNode = b.f.NewIdentifier(name.Value()) } else { - nameNode = b.newStringLiteral(name) + nameNode = b.newStringLiteral(name.Value()) b.ctx.approximateLength += 2 } attributes = append(attributes, b.f.NewImportAttribute(nameNode, b.newStringLiteral(value))) - b.ctx.approximateLength += len(name) + len(value) + 4 // `name: "value"` + b.ctx.approximateLength += len(name.Value()) + len(value) + 4 // `name: "value"` } if len(attributes) == 0 { return nil @@ -1479,7 +1479,7 @@ func (b *NodeBuilderImpl) setTextRange(range_ *ast.Node, location *ast.Node) *as return range_ } -func (b *NodeBuilderImpl) typeParameterShadowsOtherTypeParameterInScope(name string, typeParameter *Type) bool { +func (b *NodeBuilderImpl) typeParameterShadowsOtherTypeParameterInScope(name ast.SymbolName, typeParameter *Type) bool { result := b.ch.resolveName(b.ctx.enclosingDeclaration, name, ast.SymbolFlagsType, nil, false, false) if result != nil && result.Flags()&ast.SymbolFlagsTypeParameter != 0 { return result != typeParameter.symbol @@ -1504,30 +1504,30 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi } } if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 { - rawText := result.Text() - i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(rawText) - text := rawText + rawName := result.TextSymbolName() + i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(rawName) + name := rawName for true { - if !b.ctx.typeParameterNamesByText.Has(text) && !b.typeParameterShadowsOtherTypeParameterInScope(text, typeParameter) { + if !b.ctx.typeParameterNamesByText.Has(name) && !b.typeParameterShadowsOtherTypeParameterInScope(name, typeParameter) { break } i++ - text = fmt.Sprintf("%s_%d", rawText, i) + name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", rawName.Value(), i)) } - if text != rawText { + if name != rawName { // !!! TODO: smuggle type arguments out // const typeArguments = getIdentifierTypeArguments(result); - result = b.newIdentifier(text, typeParameter.symbol) + result = b.newIdentifier(name.Value(), typeParameter.symbol) // 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 - b.ctx.typeParameterNamesByTextNextNameCount.Set(rawText, i) + b.ctx.typeParameterNamesByTextNextNameCount.Set(rawName, i) b.ctx.typeParameterNames.Set(typeParameter.id, result.AsIdentifier()) - b.ctx.typeParameterNamesByText.Add(text) + b.ctx.typeParameterNamesByText.Add(name) } return result.AsIdentifier() @@ -1568,7 +1568,7 @@ func (b *NodeBuilderImpl) createMappedTypeNodeFromType(t *Type) *ast.TypeNode { // We do this to ensure we retain the toplevel keyof-ness of the type which may be lost due to keyof distribution during `getConstraintTypeFromMappedType` if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 && b.isHomomorphicMappedTypeWithNonHomomorphicInstantiation(mapped) { newConstraintParam := b.ch.newTypeParameter( - b.ch.newSymbol(ast.SymbolFlagsTypeParameter, "T"), + b.ch.newSymbol(ast.SymbolFlagsTypeParameter, ast.SymbolNameT), ) name := b.typeParameterToName(newConstraintParam) target := t.Target() @@ -1583,7 +1583,7 @@ func (b *NodeBuilderImpl) createMappedTypeNodeFromType(t *Type) *ast.TypeNode { } else if needsModifierPreservingWrapper { // So, step 1: new type variable newParam := b.ch.newTypeParameter( - b.ch.newSymbol(ast.SymbolFlagsTypeParameter, "T"), + b.ch.newSymbol(ast.SymbolFlagsTypeParameter, ast.SymbolNameT), ) name := b.typeParameterToName(newParam) newTypeVariable = b.f.NewTypeReferenceNode(name.AsNode(), nil) @@ -1664,7 +1664,7 @@ func (b *NodeBuilderImpl) typePredicateToTypePredicateNode(predicate *TypePredic } var parameterName *ast.Node if predicate.kind == TypePredicateKindIdentifier || predicate.kind == TypePredicateKindAssertsIdentifier { - parameterName = b.f.NewIdentifier(predicate.parameterName) + parameterName = b.f.NewIdentifier(predicate.parameterName.Value()) b.e.AddEmitFlags(parameterName, printer.EFNoAsciiEscaping) } else { parameterName = b.f.NewThisTypeNode() @@ -1770,13 +1770,13 @@ func (b *NodeBuilderImpl) symbolToParameterDeclaration(parameterSymbol *ast.Symb parameterTypeNode, /*initializer*/ nil, ) - b.ctx.approximateLength += len(parameterSymbol.Name()) + 3 + b.ctx.approximateLength += len(parameterSymbol.Name().Value()) + 3 return parameterNode } func (b *NodeBuilderImpl) parameterToParameterDeclarationName(parameterSymbol *ast.Symbol, parameterDeclaration *ast.Node) *ast.Node { if parameterDeclaration == nil || parameterDeclaration.Name() == nil { - return b.newIdentifier(parameterSymbol.Name(), parameterSymbol) + return b.newIdentifier(parameterSymbol.Name().Value(), parameterSymbol) } name := parameterDeclaration.Name() @@ -1857,7 +1857,7 @@ func (b *NodeBuilderImpl) typePredicateToTypePredicateNodeHelper(typePredicate * } var parameterName *ast.Node if typePredicate.kind == TypePredicateKindIdentifier || typePredicate.kind == TypePredicateKindAssertsIdentifier { - parameterName = b.newIdentifier(typePredicate.parameterName, nil /*symbol*/) + parameterName = b.newIdentifier(typePredicate.parameterName.Value(), nil /*symbol*/) b.e.SetEmitFlags(parameterName, printer.EFNoAsciiEscaping) } else { parameterName = b.f.NewThisTypeNode() @@ -2000,13 +2000,13 @@ func (c *Checker) getExpandedParameters(sig *Signature, skipUnionExpanding bool) restIndex := len(sig.parameters) - 1 restSymbol := sig.parameters[restIndex] restType := c.getTypeOfSymbol(restSymbol) - getUniqAssociatedNamesFromTupleType := func(t *Type, restSymbol *ast.Symbol) []string { - names := core.MapIndex(t.Target().AsTupleType().elementInfos, func(info TupleElementInfo, i int) string { + getUniqAssociatedNamesFromTupleType := func(t *Type, restSymbol *ast.Symbol) []ast.SymbolName { + names := core.MapIndex(t.Target().AsTupleType().elementInfos, func(info TupleElementInfo, i int) ast.SymbolName { return c.getTupleElementLabel(info, restSymbol, i) }) if len(names) > 0 { duplicates := []int{} - uniqueNames := make(map[string]bool) + uniqueNames := make(map[ast.SymbolName]bool) for i, name := range names { _, ok := uniqueNames[name] if ok { @@ -2015,15 +2015,15 @@ func (c *Checker) getExpandedParameters(sig *Signature, skipUnionExpanding bool) uniqueNames[name] = true } } - counters := make(map[string]int) + counters := make(map[ast.SymbolName]int) for _, i := range duplicates { counter, ok := counters[names[i]] if !ok { counter = 1 } - var name string + var name ast.SymbolName for true { - name = fmt.Sprintf("%s_%d", names[i], counter) + name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", names[i].Value(), counter)) _, ok := uniqueNames[name] if ok { counter++ @@ -2449,12 +2449,12 @@ func (b *NodeBuilderImpl) shouldUsePlaceholderForProperty(propertySymbol *ast.Sy func (b *NodeBuilderImpl) trackComputedName(accessExpression *ast.Node, enclosingDeclaration *ast.Node) { // get symbol of the first identifier of the entityName firstIdentifier := ast.GetFirstIdentifier(accessExpression) - name := b.ch.resolveName(enclosingDeclaration, firstIdentifier.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) + name := b.ch.resolveName(enclosingDeclaration, firstIdentifier.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) if name != nil { b.ctx.tracker.TrackSymbol(name, enclosingDeclaration, ast.SymbolFlagsValue) } else { // Name does not resolve at target location, track symbol at dest location (should be inaccessible) - fallback := b.ch.resolveName(firstIdentifier, firstIdentifier.Text(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) + fallback := b.ch.resolveName(firstIdentifier, firstIdentifier.TextSymbolName(), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) if fallback != nil { b.ctx.tracker.TrackSymbol(fallback, enclosingDeclaration, ast.SymbolFlagsValue) } @@ -2527,7 +2527,7 @@ func (b *NodeBuilderImpl) getPropertyNameNodeForSymbol(symbol *ast.Symbol, enclo return fromNameType } - name := symbol.Name() + name := symbol.Name().Value() const privateNamePrefix = ast.InternalSymbolNamePrefix + "#" if strings.HasPrefix(name, privateNamePrefix) { // symbol IDs are unstable - replace #nnn# with #private# @@ -2627,7 +2627,7 @@ func (b *NodeBuilderImpl) addPropertyToElementList(propertySymbol *ast.Symbol, t } propertyName := b.getPropertyNameNodeForSymbol(propertySymbol, saveEnclosingDeclaration) b.ctx.enclosingDeclaration = saveEnclosingDeclaration - b.ctx.approximateLength += len(ast.SymbolName(propertySymbol)) + 1 + b.ctx.approximateLength += len(ast.SymbolNameText(propertySymbol)) + 1 if propertySymbol.Flags()&ast.SymbolFlagsAccessor != 0 { writeType := b.ch.getWriteTypeOfSymbol(propertySymbol) @@ -2668,7 +2668,7 @@ func (b *NodeBuilderImpl) addPropertyToElementList(propertySymbol *ast.Symbol, t b.setCommentRange(fakeGetterDeclaration, propDeclaration) typeElements = append(typeElements, fakeGetterDeclaration) - setterParam := b.ch.newSymbol(ast.SymbolFlagsFunctionScopedVariable, "arg") + setterParam := b.ch.newSymbol(ast.SymbolFlagsFunctionScopedVariable, ast.SymbolNameArg) b.ch.valueSymbolLinks.Get(setterParam).resolvedType = writeType fakeSetterSignature := b.ch.newSignature(SignatureFlagsNone, nil, nil, nil, []*ast.Symbol{setterParam}, b.ch.voidType, nil, 0) fakeSetterDeclaration := b.signatureToSignatureDeclarationHelper(fakeSetterSignature, ast.KindSetAccessor, &SignatureToSignatureDeclarationOptions{ @@ -2774,10 +2774,10 @@ func (b *NodeBuilderImpl) createTypeNodesFromResolvedType(resolvedType *Structur continue } if getDeclarationModifierFlagsFromSymbol(propertySymbol)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { - b.ctx.tracker.ReportPrivateInBaseOfClassExpression(propertySymbol.Name()) + b.ctx.tracker.ReportPrivateInBaseOfClassExpression(propertySymbol.Name().Value()) } if IsPrivateIdentifierSymbol(propertySymbol) { - b.ctx.tracker.ReportPrivateInBaseOfClassExpression(ast.SymbolName(propertySymbol)) + b.ctx.tracker.ReportPrivateInBaseOfClassExpression(ast.SymbolNameText(propertySymbol)) } } if b.checkTruncationLength() && (i+2 < len(properties)-1) { @@ -2871,7 +2871,7 @@ func getTypeAliasForTypeLiteral(c *Checker, t *Type) *ast.Symbol { func (b *NodeBuilderImpl) shouldWriteTypeOfFunctionSymbol(symbol *ast.Symbol, typeId TypeId) (bool, *ast.Symbol) { // `typeof C.name` can only be written when the member name is a valid identifier - isStaticMethodSymbol := symbol.Flags()&ast.SymbolFlagsMethod != 0 && scanner.IsIdentifierText(symbol.Name(), core.LanguageVariantStandard) && core.Some(symbol.Declarations(), func(declaration *ast.Node) bool { + isStaticMethodSymbol := symbol.Flags()&ast.SymbolFlagsMethod != 0 && scanner.IsIdentifierText(symbol.Name().Value(), core.LanguageVariantStandard) && core.Some(symbol.Declarations(), func(declaration *ast.Node) bool { return ast.IsStatic(declaration) && !b.ch.isLateBindableIndexSignature(ast.GetNameOfDeclaration(declaration)) }) isNonLocalFunctionSymbol := false @@ -3043,7 +3043,7 @@ func (b *NodeBuilderImpl) conditionalTypeToTypeNode(_t *Type) *ast.TypeNode { checkTypeNode := b.typeToTypeNode(t.checkType) b.ctx.approximateLength += 15 if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 && t.root.isDistributive && t.checkType.flags&TypeFlagsTypeParameter == 0 { - newParam := b.ch.newTypeParameter(b.ch.newSymbol(ast.SymbolFlagsTypeParameter, "T" /* as __String */)) + newParam := b.ch.newTypeParameter(b.ch.newSymbol(ast.SymbolFlagsTypeParameter, ast.SymbolNameT /* as __String */)) name := b.typeParameterToName(newParam) newTypeVariable := b.f.NewTypeReferenceNode(name.AsNode(), nil) b.ctx.approximateLength += 37 @@ -3133,7 +3133,7 @@ func (b *NodeBuilderImpl) arrayOrTupleTypeToNode(t *Type) *ast.TypeNode { if labeledElementDeclaration != nil { tupleConstituentNodes.Nodes[i] = b.f.NewNamedTupleMember( core.IfElse(flags&ElementFlagsVariable != 0, b.f.NewToken(ast.KindDotDotDotToken), nil), - b.newIdentifier(b.ch.getTupleElementLabel(t.Target().AsTupleType().elementInfos[i], nil, i), nil /*symbol*/), + b.newIdentifier(b.ch.getTupleElementLabel(t.Target().AsTupleType().elementInfos[i], nil, i).Value(), nil /*symbol*/), core.IfElse(flags&ElementFlagsOptional != 0, b.f.NewToken(ast.KindQuestionToken), nil), core.IfElse(flags&ElementFlagsRest != 0, b.f.NewArrayTypeNode(tupleConstituentNodes.Nodes[i]), tupleConstituentNodes.Nodes[i]), ) @@ -3433,7 +3433,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { if b.ch.getDeclaredTypeOfSymbol(parentSymbol) == t { return parentName } - memberName := ast.SymbolName(t.symbol) + memberName := ast.SymbolNameText(t.symbol) if scanner.IsIdentifierText(memberName, core.LanguageVariantStandard) { return b.appendReferenceToType(parentName /* as TypeReference | ImportTypeNode */, b.f.NewTypeReferenceNode(b.f.NewIdentifier(memberName), nil /*typeArguments*/)) } @@ -3572,7 +3572,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { return result } if t.flags&TypeFlagsTypeParameter != 0 && slices.Contains(b.ctx.inferTypeParameters, t) { - b.ctx.approximateLength += len(ast.SymbolName(t.symbol)) + 6 + b.ctx.approximateLength += len(ast.SymbolNameText(t.symbol)) + 6 var constraintNode *ast.TypeNode constraint := b.ch.getConstraintOfTypeParameter(t) if constraint != nil { @@ -3590,8 +3590,8 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { } if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 && t.flags&TypeFlagsTypeParameter != 0 { name := b.typeParameterToName(t) - b.ctx.approximateLength += len(name.Text) - return b.f.NewTypeReferenceNode(b.newIdentifier(name.Text, t.symbol), nil /*typeArguments*/) + b.ctx.approximateLength += len(name.Text.Value()) + return b.f.NewTypeReferenceNode(b.newIdentifier(name.Text.Value(), t.symbol), nil /*typeArguments*/) } // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. if t.symbol != nil { @@ -3599,7 +3599,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { } var name string if (t == b.ch.markerSuperTypeForCheck || t == b.ch.markerSubTypeForCheck) && b.ch.varianceTypeParameter != nil && b.ch.varianceTypeParameter.symbol != nil { - name = core.IfElse(t == b.ch.markerSubTypeForCheck, "sub-", "super-") + ast.SymbolName(b.ch.varianceTypeParameter.symbol) + name = core.IfElse(t == b.ch.markerSubTypeForCheck, "sub-", "super-") + ast.SymbolNameText(b.ch.varianceTypeParameter.symbol) } else { name = "?" } @@ -3680,7 +3680,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { if !b.ch.isNoInferType(t) { return typeNode } - noInferSymbol := b.ch.getGlobalTypeAliasSymbol("NoInfer", 1, false) + noInferSymbol := b.ch.getGlobalTypeAliasSymbol(ast.SymbolNameNoInfer, 1, false) if noInferSymbol != nil { return b.symbolToTypeNode(noInferSymbol, ast.SymbolFlagsType, b.f.NewNodeList([]*ast.Node{typeNode})) } else { diff --git a/tsc/internal/checker/nodebuilderscopes.go b/tsc/internal/checker/nodebuilderscopes.go index 05f033bf05b7d..9e918c97713e5 100644 --- a/tsc/internal/checker/nodebuilderscopes.go +++ b/tsc/internal/checker/nodebuilderscopes.go @@ -33,7 +33,7 @@ func cloneNodeBuilderContext(context *NodeBuilderContext) func() { } type localsRecord struct { - name string + name ast.SymbolName oldSymbol *ast.Symbol } @@ -94,7 +94,7 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] // Note that we only check the most immediate enclosingDeclaration; the only place we // could potentially add another fake scope into the chain is right here, so we don't // traverse all ancestors. - pushFakeScope := func(kind string, addAll func(addSymbol func(name string, symbol *ast.Symbol))) func() { + pushFakeScope := func(kind string, addAll func(addSymbol func(name ast.SymbolName, symbol *ast.Symbol))) func() { // We only ever need to look two declarations upward. debug.Assert(b.ctx.enclosingDeclaration != nil) var existingFakeScope *ast.Node @@ -121,9 +121,9 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] if locals == nil { locals = make(ast.SymbolTable) } - newLocals := []string{} + newLocals := []ast.SymbolName{} oldLocals := []localsRecord{} - addAll(func(name string, symbol *ast.Symbol) { + addAll(func(name ast.SymbolName, symbol *ast.Symbol) { // Add cleanup information only if we don't own the fake scope if existingFakeScope != nil { oldSymbol, ok := locals[name] @@ -163,7 +163,7 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] if expandedParams == nil || !core.Some(expandedParams, func(p *ast.Symbol) bool { return p != nil }) { cleanupParams = nil } else { - cleanupParams = pushFakeScope("params", func(add func(name string, symbol *ast.Symbol)) { + cleanupParams = pushFakeScope("params", func(add func(name ast.SymbolName, symbol *ast.Symbol)) { if expandedParams == nil { return } @@ -221,7 +221,7 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] } if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 && typeParameters != nil && core.Some(typeParameters, func(p *Type) bool { return p != nil }) { - cleanupTypeParams = pushFakeScope("typeParams", func(add func(name string, symbol *ast.Symbol)) { + cleanupTypeParams = pushFakeScope("typeParams", func(add func(name ast.SymbolName, symbol *ast.Symbol)) { if typeParameters == nil { return } diff --git a/tsc/internal/checker/nodecopy.go b/tsc/internal/checker/nodecopy.go index 71ed761dcbdc8..6e94f9ecba83a 100644 --- a/tsc/internal/checker/nodecopy.go +++ b/tsc/internal/checker/nodecopy.go @@ -548,7 +548,7 @@ func getExistingNodeTreeVisitor(b *NodeBuilderImpl, bound *recoveryBoundary) *as // if node.Kind == ast.KindJSDocFunctionType {} // !!! no longer exists // End JSDoc handling - if ast.IsTypeReferenceNode(node) && ast.IsIdentifier(node.AsTypeReferenceNode().TypeName) && node.AsTypeReferenceNode().TypeName.AsIdentifier().Text == "" { + if ast.IsTypeReferenceNode(node) && ast.IsIdentifier(node.AsTypeReferenceNode().TypeName) && node.AsTypeReferenceNode().TypeName.AsIdentifier().Text == ast.EmptySymbolName { replacement := factory.NewKeywordTypeNode(ast.KindAnyKeyword) b.e.SetOriginal(replacement, node) return replacement diff --git a/tsc/internal/checker/pseudotypenodebuilder.go b/tsc/internal/checker/pseudotypenodebuilder.go index 8f1e2bf1700e1..89bda3dc33943 100644 --- a/tsc/internal/checker/pseudotypenodebuilder.go +++ b/tsc/internal/checker/pseudotypenodebuilder.go @@ -665,7 +665,7 @@ func (b *NodeBuilderImpl) pseudoReturnTypeMatchesPredicate(rt *pseudochecker.Pse } // For identifier predicates, check parameter name matches if !isThis { - if tp.ParameterName.Text() != predicate.parameterName { + if tp.ParameterName.TextSymbolName() != predicate.parameterName { return false } } diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index d3b6c86014498..c27326a2aee44 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -531,7 +531,7 @@ func (c *Checker) elaborateArrayLiteral(node *ast.Node, source *Type, target *Ty } reportedError := false for i, element := range node.Elements() { - if ast.IsOmittedExpression(element) || c.isTupleLikeType(target) && c.getPropertyOfType(target, jsnum.Number(i).String()) == nil { + if ast.IsOmittedExpression(element) || c.isTupleLikeType(target) && c.getPropertyOfType(target, ast.MakeSymbolName(jsnum.Number(i).String())) == nil { continue } nameType := c.getNumberLiteralType(jsnum.Number(i)) @@ -583,7 +583,7 @@ func (c *Checker) elaborateElement(source *Type, target *Type, relation *Relatio return false } diagnostic := diags[0] - var propertyName string + propertyName := ast.EmptySymbolName var targetProp *ast.Symbol if isTypeUsableAsPropertyName(nameType) { propertyName = getPropertyNameFromType(nameType) @@ -604,11 +604,12 @@ func (c *Checker) elaborateElement(source *Type, target *Type, relation *Relatio } else { targetNode = target.symbol.Declarations()[0] } - if propertyName == "" || nameType.flags&TypeFlagsUniqueESSymbol != 0 { - propertyName = c.TypeToString(nameType) + propertyNameText := propertyName.Value() + if propertyName == ast.EmptySymbolName || nameType.flags&TypeFlagsUniqueESSymbol != 0 { + propertyNameText = c.TypeToString(nameType) } if !c.program.IsSourceFileDefaultLibrary(ast.GetSourceFileOfNode(targetNode).PathKey()) { - diagnostic.AddRelatedInfo(createDiagnosticForNode(targetNode, diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, propertyName, c.TypeToString(target))) + diagnostic.AddRelatedInfo(createDiagnosticForNode(targetNode, diagnostics.The_expected_type_comes_from_property_0_which_is_declared_here_on_type_1, propertyNameText, c.TypeToString(target))) } } c.reportDiagnostic(diagnostic, diagnosticOutput) @@ -665,7 +666,7 @@ func (c *Checker) elaborateArrowFunction(node *ast.Node, source *Type, target *T if target.symbol != nil && len(target.symbol.Declarations()) != 0 { diagnostic.AddRelatedInfo(createDiagnosticForNode(target.symbol.Declarations()[0], diagnostics.The_expected_type_comes_from_the_return_type_of_this_signature)) } - if ast.GetFunctionFlags(node)&ast.FunctionFlagsAsync == 0 && c.getTypeOfPropertyOfType(sourceReturn, "then") == nil && c.checkTypeRelatedTo(c.createPromiseType(sourceReturn), targetReturn, relation, nil /*errorNode*/) { + if ast.GetFunctionFlags(node)&ast.FunctionFlagsAsync == 0 && c.getTypeOfPropertyOfType(sourceReturn, ast.SymbolNameThen) == nil && c.checkTypeRelatedTo(c.createPromiseType(sourceReturn), targetReturn, relation, nil /*errorNode*/) { diagnostic.AddRelatedInfo(createDiagnosticForNode(node, diagnostics.Did_you_mean_to_mark_this_function_as_async)) } c.reportDiagnostic(diagnostic, diagnosticOutput) @@ -714,7 +715,7 @@ func (c *Checker) hasCommonProperties(source *Type, target *Type, isComparingJsx * @param name a property name to search * @param isComparingJsxAttributes a boolean flag indicating whether we are searching in JsxAttributesType */ -func (c *Checker) isKnownProperty(targetType *Type, name string, isComparingJsxAttributes bool) bool { +func (c *Checker) isKnownProperty(targetType *Type, name ast.SymbolName, isComparingJsxAttributes bool) bool { if targetType.flags&TypeFlagsObject != 0 { // For backwards compatibility a symbol-named property is satisfied by a string index signature. This // is incorrect and inconsistent with element access expressions, where it is an error, so eventually @@ -722,7 +723,7 @@ func (c *Checker) isKnownProperty(targetType *Type, name string, isComparingJsxA if c.getPropertyOfObjectType(targetType, name) != nil || c.getApplicableIndexInfoForName(targetType, name) != nil || isLateBoundName(name) && c.getIndexInfoOfType(targetType, c.stringType) != nil || - isComparingJsxAttributes && isHyphenatedJsxName(name) { + isComparingJsxAttributes && isHyphenatedJsxName(name.Value()) { // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true } @@ -1005,7 +1006,7 @@ func (c *Checker) getUnmatchedPropertiesWorker(source *Type, target *Type, requi return nil } -func excludeProperties(properties []*ast.Symbol, excludedProperties collections.Set[string]) []*ast.Symbol { +func excludeProperties(properties []*ast.Symbol, excludedProperties collections.Set[ast.SymbolName]) []*ast.Symbol { if excludedProperties.Len() == 0 || len(properties) == 0 { return properties } @@ -1037,7 +1038,7 @@ func (d *TypeDiscriminator) len() int { return len(d.props) } -func (d *TypeDiscriminator) name(index int) string { +func (d *TypeDiscriminator) name(index int) ast.SymbolName { return d.props[index].Name() } @@ -1077,7 +1078,7 @@ func (c *Checker) findDiscriminantProperties(sourceProperties []*ast.Symbol, tar return result } -func (c *Checker) isDiscriminantProperty(t *Type, name string) bool { +func (c *Checker) isDiscriminantProperty(t *Type, name ast.SymbolName) bool { if t != nil && t.flags&TypeFlagsUnion != 0 { prop := c.getUnionOrIntersectionProperty(t, name, false /*skipObjectFunctionPropertyAugment*/) if prop != nil && prop.CheckFlags()&ast.CheckFlagsSyntheticProperty != 0 { @@ -1095,7 +1096,7 @@ func (c *Checker) isDiscriminantProperty(t *Type, name string) bool { func (c *Checker) getMatchingUnionConstituentForType(unionType *Type, t *Type) *Type { keyPropertyName := c.getKeyPropertyName(unionType) - if keyPropertyName == "" { + if keyPropertyName == ast.EmptySymbolName { return nil } propType := c.getTypeOfPropertyOfType(t, keyPropertyName) @@ -1107,19 +1108,19 @@ func (c *Checker) getMatchingUnionConstituentForType(unionType *Type, t *Type) * // Return the name of a discriminant property for which it was possible and feasible to construct a map of // constituent types keyed by the literal types of the property by that name in each constituent type. Return -// an empty string if no such discriminant property exists. -func (c *Checker) getKeyPropertyName(t *Type) string { +// an empty name if no such discriminant property exists. +func (c *Checker) getKeyPropertyName(t *Type) ast.SymbolName { u := t.AsUnionType() - if u.keyPropertyName == "" { + if u.keyPropertyName.IsZero() { u.keyPropertyName, u.constituentMap = c.computeKeyPropertyNameAndMap(t) } if u.keyPropertyName == ast.InternalSymbolNameMissing { - return "" + return ast.EmptySymbolName } return u.keyPropertyName } -// Given a union type for which getKeyPropertyName returned a non-empty string, return the constituent +// Given a union type for which getKeyPropertyName returned a non-empty name, return the constituent // that corresponds to the given key type for that property name. func (c *Checker) getConstituentTypeForKeyType(t *Type, keyType *Type) *Type { result := t.AsUnionType().constituentMap[c.getRegularTypeOfLiteralType(keyType)] @@ -1129,13 +1130,13 @@ func (c *Checker) getConstituentTypeForKeyType(t *Type, keyType *Type) *Type { return nil } -func (c *Checker) computeKeyPropertyNameAndMap(t *Type) (string, map[*Type]*Type) { +func (c *Checker) computeKeyPropertyNameAndMap(t *Type) (ast.SymbolName, map[*Type]*Type) { types := t.Types() if len(types) < 10 || t.objectFlags&ObjectFlagsPrimitiveUnion != 0 || core.CountWhere(types, isObjectOrInstantiableNonPrimitive) < 10 { return ast.InternalSymbolNameMissing, nil } keyPropertyName := c.getKeyPropertyCandidateName(types) - if keyPropertyName == "" { + if keyPropertyName == ast.EmptySymbolName { return ast.InternalSymbolNameMissing, nil } mapByKeyProperty := c.mapTypesByKeyProperty(types, keyPropertyName) @@ -1149,7 +1150,7 @@ func isObjectOrInstantiableNonPrimitive(t *Type) bool { return t.flags&(TypeFlagsObject|TypeFlagsInstantiableNonPrimitive) != 0 } -func (c *Checker) getKeyPropertyCandidateName(types []*Type) string { +func (c *Checker) getKeyPropertyCandidateName(types []*Type) ast.SymbolName { for _, t := range types { if t.flags&(TypeFlagsObject|TypeFlagsInstantiableNonPrimitive) != 0 { for _, p := range c.getPropertiesOfType(t) { @@ -1159,14 +1160,14 @@ func (c *Checker) getKeyPropertyCandidateName(types []*Type) string { } } } - return "" + return ast.EmptySymbolName } // Given a set of constituent types and a property name, create and return a map keyed by the literal // types of the property by that name in each constituent type. No map is returned if some key property // has a non-literal type or if less than 10 or less than 50% of the constituents have a unique key. // Entries with duplicate keys have unknownType as the value. -func (c *Checker) mapTypesByKeyProperty(types []*Type, keyPropertyName string) map[*Type]*Type { +func (c *Checker) mapTypesByKeyProperty(types []*Type, keyPropertyName ast.SymbolName) map[*Type]*Type { typesByKey := make(map[*Type]*Type) count := 0 for _, t := range types { @@ -1198,7 +1199,7 @@ func (c *Checker) mapTypesByKeyProperty(types []*Type, keyPropertyName string) m type Discriminator interface { len() int // Number of discriminant properties - name(index int) string // Property name of index-th discriminator + name(index int) ast.SymbolName // Property name of index-th discriminator matches(index int, t *Type) bool // True if index-th discriminator matches the given type } @@ -1613,7 +1614,7 @@ func (c *Checker) compareSignaturesRelated(source *Signature, target *Signature, } if related == TernaryFalse { if reportErrors { - errorReporter(diagnostics.Types_of_parameters_0_and_1_are_incompatible, c.getParameterNameAtPosition(source, i), c.getParameterNameAtPosition(target, i)) + errorReporter(diagnostics.Types_of_parameters_0_and_1_are_incompatible, c.getParameterNameAtPosition(source, i).Value(), c.getParameterNameAtPosition(target, i).Value()) } return TernaryFalse } @@ -1683,7 +1684,7 @@ func (c *Checker) compareTypePredicateRelatedTo(source *TypePredicate, target *T if source.kind == TypePredicateKindIdentifier || source.kind == TypePredicateKindAssertsIdentifier { if source.parameterIndex != target.parameterIndex { if reportErrors { - errorReporter(diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName, target.parameterName) + errorReporter(diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName.Value(), target.parameterName.Value()) errorReporter(diagnostics.Type_predicate_0_is_not_assignable_to_1, c.typePredicateToString(source), c.typePredicateToString(target)) } return TernaryFalse @@ -1959,7 +1960,7 @@ func (c *Checker) isInstantiatedGenericParameter(signature *Signature, pos int) return t != nil && c.isGenericType(t) } -func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) string { +func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) ast.SymbolName { paramCount := len(signature.parameters) - core.IfElse(signatureHasRestParameter(signature), 1, 0) if pos < paramCount { return signature.parameters[pos].Name() @@ -1973,23 +1974,21 @@ func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) stri return restParameter.Name() } -func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol *ast.Symbol, index int) string { +func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol *ast.Symbol, index int) ast.SymbolName { if elementInfo.labeledDeclaration != nil { - return elementInfo.labeledDeclaration.Name().Text() + return elementInfo.labeledDeclaration.Name().TextSymbolName() } if restSymbol != nil && restSymbol.ValueDeclaration() != nil && ast.IsParameterDeclaration(restSymbol.ValueDeclaration()) { return c.getTupleElementLabelFromBindingElement(restSymbol.ValueDeclaration(), index, elementInfo.flags) } - var rootName string + rootName := ast.SymbolNameArg if restSymbol != nil { rootName = restSymbol.Name() - } else { - rootName = "arg" } - return rootName + "_" + strconv.Itoa(index) + return ast.MakeSymbolName(rootName.Value() + "_" + strconv.Itoa(index)) } -func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index int, elementFlags ElementFlags) string { +func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index int, elementFlags ElementFlags) ast.SymbolName { if node.Name() != nil { switch node.Name().Kind { case ast.KindIdentifier: @@ -2007,9 +2006,9 @@ func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index i // (x: number, y: number, ...z: number[], z_1: number) => ... // which preserves rest elements of z but gives distinct numbers to fixed elements of 'z' if elementFlags&ElementFlagsVariable != 0 { - return name + return ast.MakeSymbolName(name) } - return name + "_" + strconv.Itoa(index) + return ast.MakeSymbolName(name + "_" + strconv.Itoa(index)) } // given // (...[x]: [number]) => ... @@ -2023,9 +2022,9 @@ func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index i // (x_0: number) => ... // which which numbers fixed elements of 'x' whose tuple element type is variable if elementFlags&ElementFlagsFixed != 0 { - return name + return ast.MakeSymbolName(name) } - return name + "_n" + return ast.MakeSymbolName(name + "_n") case ast.KindArrayBindingPattern: if hasDotDotDotToken(node) { elements := node.Name().Elements() @@ -2043,7 +2042,7 @@ func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index i } } } - return "arg_" + strconv.Itoa(index) + return ast.MakeSymbolName("arg_" + strconv.Itoa(index)) } func (c *Checker) getTypePredicateOfSignature(sig *Signature) *TypePredicate { @@ -2123,12 +2122,12 @@ func (c *Checker) createTypePredicateFromTypePredicateNode(node *ast.Node, signa } if ast.IsThisTypeNode(predicateNode.ParameterName) { kind := core.IfElse(predicateNode.AssertsModifier != nil, TypePredicateKindAssertsThis, TypePredicateKindThis) - return c.newTypePredicate(kind, "" /*parameterName*/, 0 /*parameterIndex*/, t) + return c.newTypePredicate(kind, ast.EmptySymbolName /*parameterName*/, 0 /*parameterIndex*/, t) } kind := core.IfElse(predicateNode.AssertsModifier != nil, TypePredicateKindAssertsIdentifier, TypePredicateKindIdentifier) name := predicateNode.ParameterName.Text() - index := core.FindIndex(signature.parameters, func(p *ast.Symbol) bool { return p.Name() == name }) - return c.newTypePredicate(kind, name, int32(index), t) + index := core.FindIndex(signature.parameters, func(p *ast.Symbol) bool { return p.Name() == ast.MakeSymbolName(name) }) + return c.newTypePredicate(kind, ast.MakeSymbolName(name), int32(index), t) } func (c *Checker) instantiateTypePredicate(predicate *TypePredicate, mapper *TypeMapper) *TypePredicate { @@ -2139,7 +2138,7 @@ func (c *Checker) instantiateTypePredicate(predicate *TypePredicate, mapper *Typ return c.newTypePredicate(predicate.kind, predicate.parameterName, predicate.parameterIndex, t) } -func (c *Checker) newTypePredicate(kind TypePredicateKind, parameterName string, parameterIndex int32, t *Type) *TypePredicate { +func (c *Checker) newTypePredicate(kind TypePredicateKind, parameterName ast.SymbolName, parameterIndex int32, t *Type) *TypePredicate { return &TypePredicate{kind: kind, parameterIndex: parameterIndex, parameterName: parameterName, t: t} } @@ -2785,7 +2784,7 @@ func (r *Relater) hasExcessProperties(source *Type, target *Type, reportErrors b r.errorNode = prop.ValueDeclaration().Name() } propName := r.c.symbolToString(prop) - suggestionSymbol := r.c.getSuggestedSymbolForNonexistentJSXAttribute(propName, errorTarget) + suggestionSymbol := r.c.getSuggestedSymbolForNonexistentJSXAttribute(ast.MakeSymbolName(propName), errorTarget) if suggestionSymbol != nil { r.reportError(diagnostics.Property_0_does_not_exist_on_type_1_Did_you_mean_2, propName, r.c.TypeToString(errorTarget), r.c.symbolToString(suggestionSymbol)) } else { @@ -2804,7 +2803,7 @@ func (r *Relater) hasExcessProperties(source *Type, target *Type, reportErrors b name := prop.ValueDeclaration().Name() r.errorNode = name if ast.IsIdentifier(name) { - suggestion = r.c.getSuggestionForNonexistentProperty(name.Text(), errorTarget) + suggestion = r.c.getSuggestionForNonexistentProperty(name.TextSymbolName(), errorTarget) } } if suggestion != "" { @@ -2827,7 +2826,7 @@ func (r *Relater) hasExcessProperties(source *Type, target *Type, reportErrors b return false } -func (c *Checker) getTypeOfPropertyInTypes(types []*Type, name string) *Type { +func (c *Checker) getTypeOfPropertyInTypes(types []*Type, name ast.SymbolName) *Type { var propTypes []*Type for _, t := range types { propTypes = append(propTypes, c.getTypeOfPropertyInType(t, name)) @@ -2835,7 +2834,7 @@ func (c *Checker) getTypeOfPropertyInTypes(types []*Type, name string) *Type { return c.getUnionType(propTypes) } -func (c *Checker) getTypeOfPropertyInType(t *Type, name string) *Type { +func (c *Checker) getTypeOfPropertyInType(t *Type, name ast.SymbolName) *Type { t = c.getApparentType(t) var prop *ast.Symbol if t.flags&TypeFlagsUnionOrIntersection != 0 { @@ -2858,7 +2857,7 @@ func shouldCheckAsExcessProperty(prop *ast.Symbol, container *ast.Symbol) bool { } func isIgnoredJsxProperty(source *Type, sourceProp *ast.Symbol) bool { - return source.objectFlags&ObjectFlagsJsxAttributes != 0 && isHyphenatedJsxName(sourceProp.Name()) + return source.objectFlags&ObjectFlagsJsxAttributes != 0 && isHyphenatedJsxName(sourceProp.Name().Value()) } func (c *Checker) isTypeSubsetOf(source *Type, target *Type) bool { @@ -3263,7 +3262,7 @@ func (r *Relater) structuredTypeRelatedTo(source *Type, target *Type, reportErro // let weak: { a?: { x?: number } } & { c?: string } = wrong; // Nested weak object type // case result != TernaryFalse && intersectionState&IntersectionStateTarget == 0 && target.flags&TypeFlagsIntersection != 0 && !r.c.isGenericObjectType(target) && source.flags&(TypeFlagsObject|TypeFlagsIntersection) != 0: - result &= r.propertiesRelatedTo(source, target, reportErrors, collections.Set[string]{} /*excludedProperties*/, false /*optionalsOnly*/, IntersectionStateNone) + result &= r.propertiesRelatedTo(source, target, reportErrors, collections.Set[ast.SymbolName]{} /*excludedProperties*/, false /*optionalsOnly*/, IntersectionStateNone) if result != 0 && isObjectLiteralType(source) && source.objectFlags&ObjectFlagsFreshLiteral != 0 { result &= r.indexSignaturesRelatedTo(source, target, false /*sourceIsPrimitive*/, reportErrors, IntersectionStateNone) } @@ -3275,7 +3274,7 @@ func (r *Relater) structuredTypeRelatedTo(source *Type, target *Type, reportErro // } // case result != 0 && r.c.isNonGenericObjectType(target) && !r.c.isArrayOrTupleType(target) && r.isSourceIntersectionNeedingExtraCheck(source, target): - result &= r.propertiesRelatedTo(source, target, reportErrors, collections.Set[string]{} /*excludedProperties*/, true /*optionalsOnly*/, intersectionState) + result &= r.propertiesRelatedTo(source, target, reportErrors, collections.Set[ast.SymbolName]{} /*excludedProperties*/, true /*optionalsOnly*/, intersectionState) } } if result != TernaryFalse { @@ -3894,7 +3893,7 @@ func (r *Relater) structuredTypeRelatedToWorker(source *Type, target *Type, repo if source.flags&(TypeFlagsObject|TypeFlagsIntersection) != 0 && target.flags&TypeFlagsObject != 0 { // Report structural errors only if we haven't reported any errors yet reportStructuralErrors := reportErrors && r.errorChain == saveErrorState.errorChain && !sourceIsPrimitive - result = r.propertiesRelatedTo(source, target, reportStructuralErrors, collections.Set[string]{} /*excludedProperties*/, false /*optionalsOnly*/, intersectionState) + result = r.propertiesRelatedTo(source, target, reportStructuralErrors, collections.Set[ast.SymbolName]{} /*excludedProperties*/, false /*optionalsOnly*/, intersectionState) if result != TernaryFalse { result &= r.signaturesRelatedTo(source, target, SignatureKindCall, reportStructuralErrors, intersectionState) if result != TernaryFalse { @@ -4054,7 +4053,7 @@ func (r *Relater) typeRelatedToDiscriminatedType(source *Type, target *Type) Ter } // Compute the set of types for each discriminant property. sourceDiscriminantTypes := make([][]*Type, len(sourcePropertiesFiltered)) - var excludedProperties collections.Set[string] + var excludedProperties collections.Set[ast.SymbolName] for i, sourceProperty := range sourcePropertiesFiltered { sourcePropertyType := r.c.getNonMissingTypeOfSymbol(sourceProperty) sourceDiscriminantTypes[i] = sourcePropertyType.Distributed() @@ -4130,7 +4129,7 @@ func (r *Relater) typeRelatedToDiscriminatedType(source *Type, target *Type) Ter return result } -func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors bool, excludedProperties collections.Set[string], optionalsOnly bool, intersectionState IntersectionState) Ternary { +func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors bool, excludedProperties collections.Set[ast.SymbolName], optionalsOnly bool, intersectionState IntersectionState) Ternary { if r.relation == r.c.identityRelation { return r.propertiesIdenticalTo(source, target, excludedProperties) } @@ -4231,7 +4230,7 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b if sourceFlags&ElementFlagsVariable != 0 || targetFlags&ElementFlagsVariable != 0 { canExcludeDiscriminants = false } - if canExcludeDiscriminants && excludedProperties.Has(strconv.Itoa(sourcePosition)) { + if canExcludeDiscriminants && excludedProperties.Has(ast.MakeSymbolName(strconv.Itoa(sourcePosition))) { continue } } @@ -4286,7 +4285,7 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b numericNamesOnly := isTupleType(source) && isTupleType(target) for _, targetProp := range excludeProperties(properties, excludedProperties) { name := targetProp.Name() - if targetProp.Flags()&ast.SymbolFlagsPrototype == 0 && (!numericNamesOnly || isNumericLiteralName(name) || name == "length") && (!optionalsOnly || targetProp.Flags()&ast.SymbolFlagsOptional != 0) { + if targetProp.Flags()&ast.SymbolFlagsPrototype == 0 && (!numericNamesOnly || isNumericLiteralName(name.Value()) || name == ast.SymbolNameLength) && (!optionalsOnly || targetProp.Flags()&ast.SymbolFlagsOptional != 0) { sourceProp := r.c.getPropertyOfType(source, name) if sourceProp != nil && sourceProp != targetProp { related := r.propertyRelatedTo(source, target, sourceProp, targetProp, r.c.getNonMissingTypeOfSymbol, reportErrors, intersectionState, r.relation == r.c.comparableRelation) @@ -4447,7 +4446,7 @@ func (r *Relater) tryElaborateErrorsForPrimitivesAndObjects(source *Type, target } } -func (r *Relater) propertiesIdenticalTo(source *Type, target *Type, excludedProperties collections.Set[string]) Ternary { +func (r *Relater) propertiesIdenticalTo(source *Type, target *Type, excludedProperties collections.Set[ast.SymbolName]) Ternary { if source.flags&TypeFlagsObject == 0 || target.flags&TypeFlagsObject == 0 { return TernaryFalse } diff --git a/tsc/internal/checker/services.go b/tsc/internal/checker/services.go index 90f3f2f901844..2cd7e3247ff42 100644 --- a/tsc/internal/checker/services.go +++ b/tsc/internal/checker/services.go @@ -132,7 +132,7 @@ func (c *Checker) GetExportsOfModule(symbol *ast.Symbol) []*ast.Symbol { return symbolsToArray(c.getExportsOfModule(symbol)) } -func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb func(*ast.Symbol, string)) { +func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb func(*ast.Symbol, ast.SymbolName)) { for key, exportedSymbol := range c.getExportsOfModule(moduleSymbol) { if !isReservedMemberName(key) { cb(exportedSymbol, key) @@ -161,11 +161,11 @@ func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb } } -func (c *Checker) IsValidPropertyAccess(node *ast.Node, propertyName string) bool { +func (c *Checker) IsValidPropertyAccess(node *ast.Node, propertyName ast.SymbolName) bool { return c.isValidPropertyAccess(node, propertyName) } -func (c *Checker) isValidPropertyAccess(node *ast.Node, propertyName string) bool { +func (c *Checker) isValidPropertyAccess(node *ast.Node, propertyName ast.SymbolName) bool { switch node.Kind { case ast.KindPropertyAccessExpression: return c.isValidPropertyAccessWithType(node, node.Expression().Kind == ast.KindSuperKeyword, propertyName, c.getWidenedType(c.checkExpression(node.Expression()))) @@ -177,7 +177,7 @@ func (c *Checker) isValidPropertyAccess(node *ast.Node, propertyName string) boo panic("Unexpected node kind in isValidPropertyAccess: " + node.Kind.String()) } -func (c *Checker) isValidPropertyAccessWithType(node *ast.Node, isSuper bool, propertyName string, t *Type) bool { +func (c *Checker) isValidPropertyAccessWithType(node *ast.Node, isSuper bool, propertyName ast.SymbolName, t *Type) bool { // Short-circuiting for improved performance. if IsTypeAny(t) { return true @@ -292,7 +292,7 @@ func (c *Checker) getAugmentedPropertiesOfType(t *Type) []*ast.Symbol { return c.getNamedMembers(propsByName, nil) } -func (c *Checker) TryGetMemberInModuleExportsAndProperties(memberName string, moduleSymbol *ast.Symbol) *ast.Symbol { +func (c *Checker) TryGetMemberInModuleExportsAndProperties(memberName ast.SymbolName, moduleSymbol *ast.Symbol) *ast.Symbol { symbol := c.TryGetMemberInModuleExports(memberName, moduleSymbol) if symbol != nil { return symbol @@ -310,7 +310,7 @@ func (c *Checker) TryGetMemberInModuleExportsAndProperties(memberName string, mo return nil } -func (c *Checker) TryGetMemberInModuleExports(memberName string, moduleSymbol *ast.Symbol) *ast.Symbol { +func (c *Checker) TryGetMemberInModuleExports(memberName ast.SymbolName, moduleSymbol *ast.Symbol) *ast.Symbol { symbolTable := c.getExportsOfModule(moduleSymbol) return symbolTable[memberName] } @@ -504,7 +504,7 @@ func (c *Checker) GetShorthandAssignmentValueSymbol(location *ast.Node) *ast.Sym * @param parameterName a name of the parameter to get the symbols for. * @return a tuple of two symbols */ -func (c *Checker) GetSymbolsOfParameterPropertyDeclaration(parameter *ast.Node /*ParameterPropertyDeclaration*/, parameterName string) (*ast.Symbol, *ast.Symbol) { +func (c *Checker) GetSymbolsOfParameterPropertyDeclaration(parameter *ast.Node /*ParameterPropertyDeclaration*/, parameterName ast.SymbolName) (*ast.Symbol, *ast.Symbol) { constructorDeclaration := parameter.Parent classDeclaration := parameter.Parent.Parent @@ -529,7 +529,7 @@ func (c *Checker) IsDeclarationUsed( if jsxElementsPresent && jsxModeNeedsExplicitImport { jsxNamespace := c.getJsxNamespace(sourceFile.AsNode()) jsxFragmentFactory := c.GetJsxFragmentFactory(sourceFile.AsNode()) - identifierText := identifier.Text + identifierText := identifier.Text.Value() if identifierText == jsxNamespace { return true } @@ -554,7 +554,7 @@ func (c *Checker) IsSymbolReferencedInFile( symbol *ast.Symbol, ) bool { identifierText := definition.Text - for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText, sourceFile.AsNode()) { + for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText.Value(), sourceFile.AsNode()) { if !ast.IsIdentifier(token) { continue } @@ -589,7 +589,7 @@ func (c *Checker) GetReferencesToSymbolInFile( ) []*ast.Node { identifierText := symbol.Name() var result []*ast.Node - for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText, sourceFile.AsNode()) { + for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText.Value(), sourceFile.AsNode()) { if !ast.IsIdentifier(token) { continue } @@ -824,12 +824,12 @@ func (c *Checker) IsTypeInvalidDueToUnionDiscriminant(contextualType *Type, obj nameType = c.getLiteralTypeFromPropertyName(propertyName) } } - var name string + name := ast.EmptySymbolName if nameType != nil && isTypeUsableAsPropertyName(nameType) { name = getPropertyNameFromType(nameType) } var expected *Type - if name != "" { + if name != ast.EmptySymbolName { expected = c.getTypeOfPropertyOfType(contextualType, name) } return expected != nil && isLiteralType(expected) && !c.isTypeAssignableTo(c.getTypeOfNode(property), expected) @@ -976,30 +976,30 @@ func (c *Checker) GetContextualTypeForArrayLiteralAtPosition(contextualArrayType ) } -var knownGenericTypeNames = map[string]struct{}{ - "Array": {}, - "ArrayLike": {}, - "ReadonlyArray": {}, - "Promise": {}, - "PromiseLike": {}, - "Iterable": {}, - "IterableIterator": {}, - "AsyncIterable": {}, - "Set": {}, - "WeakSet": {}, - "ReadonlySet": {}, - "Map": {}, - "WeakMap": {}, - "ReadonlyMap": {}, - "Partial": {}, - "Required": {}, - "Readonly": {}, - "Pick": {}, - "Omit": {}, - "NonNullable": {}, -} - -func isKnownGenericTypeName(name string) bool { +var knownGenericTypeNames = map[ast.SymbolName]struct{}{ + ast.SymbolNameArray: {}, + ast.SymbolNameArrayLike: {}, + ast.SymbolNameReadonlyArray: {}, + ast.SymbolNamePromise: {}, + ast.SymbolNamePromiseLike: {}, + ast.SymbolNameIterable: {}, + ast.SymbolNameIterableIterator: {}, + ast.SymbolNameAsyncIterable: {}, + ast.SymbolNameSet: {}, + ast.SymbolNameWeakSet: {}, + ast.SymbolNameReadonlySet: {}, + ast.SymbolNameMap: {}, + ast.SymbolNameWeakMap: {}, + ast.SymbolNameReadonlyMap: {}, + ast.SymbolNamePartial: {}, + ast.SymbolNameRequired: {}, + ast.SymbolNameReadonly: {}, + ast.SymbolNamePick: {}, + ast.SymbolNameOmit: {}, + ast.SymbolNameNonNullable: {}, +} + +func isKnownGenericTypeName(name ast.SymbolName) bool { _, exists := knownGenericTypeNames[name] return exists } @@ -1027,7 +1027,7 @@ func (c *Checker) GetPropertySymbolsFromContextualType(node *ast.Node, contextua return nil } if contextualType.flags&TypeFlagsUnion == 0 { - if symbol := c.getPropertyOfType(contextualType, name); symbol != nil { + if symbol := c.getPropertyOfType(contextualType, ast.MakeSymbolName(name)); symbol != nil { return []*ast.Symbol{symbol} } return nil @@ -1039,17 +1039,17 @@ func (c *Checker) GetPropertySymbolsFromContextualType(node *ast.Node, contextua }) } discriminatedPropertySymbols := core.MapNonNil(filteredTypes, func(t *Type) *ast.Symbol { - return c.getPropertyOfType(t, name) + return c.getPropertyOfType(t, ast.MakeSymbolName(name)) }) if unionSymbolOk && (len(discriminatedPropertySymbols) == 0 || len(discriminatedPropertySymbols) == len(contextualType.Types())) { - if symbol := c.getPropertyOfType(contextualType, name); symbol != nil { + if symbol := c.getPropertyOfType(contextualType, ast.MakeSymbolName(name)); symbol != nil { return []*ast.Symbol{symbol} } } if len(filteredTypes) == 0 && len(discriminatedPropertySymbols) == 0 { // Bad discriminant -- do again without discriminating return core.MapNonNil(contextualType.Types(), func(t *Type) *ast.Symbol { - return c.getPropertyOfType(t, name) + return c.getPropertyOfType(t, ast.MakeSymbolName(name)) }) } // by eliminating duplicates we might even end up with a single symbol @@ -1070,7 +1070,7 @@ func (c *Checker) GetPropertySymbolOfDestructuringAssignment(location *ast.Node) if ast.IsArrayLiteralOrObjectLiteralDestructuringPattern(location.Parent.Parent) { // Get the type of the object or array literal and then look for property of given name in the type if typeOfObjectLiteral := c.getTypeOfAssignmentPattern(location.Parent.Parent); typeOfObjectLiteral != nil { - return c.getPropertyOfType(typeOfObjectLiteral, location.Text()) + return c.getPropertyOfType(typeOfObjectLiteral, location.TextSymbolName()) } } return nil diff --git a/tsc/internal/checker/symbolaccessibility.go b/tsc/internal/checker/symbolaccessibility.go index 389980a60ff64..3cb3176d5aaeb 100644 --- a/tsc/internal/checker/symbolaccessibility.go +++ b/tsc/internal/checker/symbolaccessibility.go @@ -892,7 +892,7 @@ func (c *Checker) getClassExpressionNameTable(location *ast.Node) ast.SymbolTabl if len(nameText) == 0 || classSymbol == nil { return nil } - table := ast.SymbolTable{nameText: classSymbol} + table := ast.SymbolTable{ast.MakeSymbolName(nameText): classSymbol} if c.classExpressionNameTables == nil { c.classExpressionNameTables = make(map[ast.NodeId]ast.SymbolTable) } diff --git a/tsc/internal/checker/types.go b/tsc/internal/checker/types.go index a3cfe28c2e735..7d0a1974640d7 100644 --- a/tsc/internal/checker/types.go +++ b/tsc/internal/checker/types.go @@ -271,8 +271,8 @@ type AliasSymbolLinks struct { // Links for module symbols type ModuleSymbolLinks struct { - resolvedExports ast.SymbolTable // Resolved exports of module or combined early- and late-bound static members of a class. - typeOnlyExportStarMap map[string]*ast.Node // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration + resolvedExports ast.SymbolTable // Resolved exports of module or combined early- and late-bound static members of a class. + typeOnlyExportStarMap map[ast.SymbolName]*ast.Node // Set on a module symbol when some of its exports were resolved through a 'export type * from "mod"' declaration exportsChecked bool } @@ -461,8 +461,8 @@ func (links *TypeNodeLinks) setOuterTypeParameters(c *Checker, types []*Type) { } type ComputedNameNodeLinks struct { - hasName *bool // If the node has a computable name - name string // Resolved name associated with the type of the node + hasName *bool // If the node has a computable name + name ast.SymbolName // Resolved name associated with the type of the node } // Links for enum members @@ -1098,7 +1098,7 @@ func (t *LiteralType) String() string { type UniqueESSymbolType struct { TypeBase - name string + name ast.SymbolName } // ConstrainedType (type with computed base constraint) @@ -1380,7 +1380,7 @@ type UnionType struct { resolvedReducedType *Type regularType *Type origin *Type // Denormalized union, intersection, or index type in which union originates - keyPropertyName string // Property with unique unit type that exists in every object/intersection in union type + keyPropertyName ast.SymbolName // Property with unique unit type that exists in every object/intersection in union type constituentMap map[*Type]*Type // Constituents keyed by unit type discriminants } @@ -1660,7 +1660,7 @@ const ( type TypePredicate struct { kind TypePredicateKind parameterIndex int32 - parameterName string + parameterName ast.SymbolName t *Type } @@ -1676,7 +1676,7 @@ func (typePredicate *TypePredicate) ParameterIndex() int32 { return typePredicate.parameterIndex } -func (typePredicate *TypePredicate) ParameterName() string { +func (typePredicate *TypePredicate) ParameterName() ast.SymbolName { return typePredicate.parameterName } diff --git a/tsc/internal/checker/types_test.go b/tsc/internal/checker/types_test.go index 86de2b089e06e..7fff276d4ca10 100644 --- a/tsc/internal/checker/types_test.go +++ b/tsc/internal/checker/types_test.go @@ -293,7 +293,7 @@ func TestIntersectionReductionAllocations(t *testing.T) { //nolint:paralleltest c, _ := newCompositeTestChecker() members := make(ast.SymbolTable) for i := range 128 { - name := strconv.Itoa(i) + name := ast.MakeSymbolName(strconv.Itoa(i)) members[name] = c.newSymbol(ast.SymbolFlagsProperty, name) } object := c.newAnonymousType(nil, members, nil, nil, nil) @@ -308,32 +308,32 @@ func TestTemporaryPropertyCounts(t *testing.T) { t.Parallel() c := &Checker{} outer := c.getTemporaryPropertyCounts() - outer.Set("second", 1) - outer.Set("first", 1) - outer.Set("second", 2) - assert.Assert(t, slices.Equal(slices.Collect(outer.Keys()), []string{"second", "first"})) + outer.Set(ast.MakeSymbolName("second"), 1) + outer.Set(ast.MakeSymbolName("first"), 1) + outer.Set(ast.MakeSymbolName("second"), 2) + assert.Assert(t, slices.Equal(slices.Collect(outer.Keys()), []ast.SymbolName{ast.MakeSymbolName("second"), ast.MakeSymbolName("first")})) inner := c.getTemporaryPropertyCounts() assert.Assert(t, inner != outer) - inner.Set("first", 4) - assert.Equal(t, outer.GetOrZero("first"), 1) - assert.Equal(t, outer.GetOrZero("second"), 2) + inner.Set(ast.MakeSymbolName("first"), 4) + assert.Equal(t, outer.GetOrZero(ast.MakeSymbolName("first")), 1) + assert.Equal(t, outer.GetOrZero(ast.MakeSymbolName("second")), 2) c.releaseTemporaryPropertyCounts(inner) assert.Equal(t, inner.Size(), 0) - assert.Assert(t, !inner.Has("first")) + assert.Assert(t, !inner.Has(ast.MakeSymbolName("first"))) reused := c.getTemporaryPropertyCounts() assert.Equal(t, reused, inner) - reused.Set("second", 3) - reused.Set("first", 5) - assert.Assert(t, slices.Equal(slices.Collect(reused.Keys()), []string{"second", "first"})) - assert.Equal(t, outer.GetOrZero("first"), 1) + reused.Set(ast.MakeSymbolName("second"), 3) + reused.Set(ast.MakeSymbolName("first"), 5) + assert.Assert(t, slices.Equal(slices.Collect(reused.Keys()), []ast.SymbolName{ast.MakeSymbolName("second"), ast.MakeSymbolName("first")})) + assert.Equal(t, outer.GetOrZero(ast.MakeSymbolName("first")), 1) c.releaseTemporaryPropertyCounts(reused) c.releaseTemporaryPropertyCounts(outer) runtime.GC() reused = c.getTemporaryPropertyCounts() assert.Equal(t, reused.Size(), 0) - assert.Assert(t, !reused.Has("second")) + assert.Assert(t, !reused.Has(ast.MakeSymbolName("second"))) for i := range 4097 { - reused.Set(strconv.Itoa(i), i) + reused.Set(ast.MakeSymbolName(strconv.Itoa(i)), i) } c.releaseTemporaryPropertyCounts(reused) for counts := c.freePropertyCounts; counts != nil; counts = counts.next { @@ -348,23 +348,23 @@ func TestTemporaryPropertyCounts(t *testing.T) { func TestIntersectionReductionReentrancy(t *testing.T) { t.Parallel() c, _ := newCompositeTestChecker() - property := c.newSymbol(ast.SymbolFlagsProperty, "value") - object := c.newAnonymousType(nil, ast.SymbolTable{"value": property}, nil, nil, nil) + property := c.newSymbol(ast.SymbolFlagsProperty, ast.MakeSymbolName("value")) + object := c.newAnonymousType(nil, ast.SymbolTable{ast.MakeSymbolName("value"): property}, nil, nil, nil) inner := c.newIntersectionType(ObjectFlagsNone, []*Type{object, object}) outer := c.newIntersectionType(ObjectFlagsNone, []*Type{inner, object}) assert.Equal(t, c.getReducedType(outer), outer) assert.Equal(t, c.getReducedType(inner), inner) - assert.Equal(t, c.getPropertyOfUnionOrIntersectionType(outer, "value", true), property) + assert.Equal(t, c.getPropertyOfUnionOrIntersectionType(outer, ast.MakeSymbolName("value"), true), property) assert.Assert(t, c.freePropertyCounts != nil) assert.Assert(t, c.freePropertyCounts.next != nil) workspace := c.freePropertyCounts - conflicting := c.newSymbolEx(ast.SymbolFlagsProperty, "value", ast.CheckFlagsContainsPrivate) - outer.AsUnionOrIntersectionType().propertyCacheWithoutFunctionPropertyAugment["value"] = conflicting + conflicting := c.newSymbolEx(ast.SymbolFlagsProperty, ast.MakeSymbolName("value"), ast.CheckFlagsContainsPrivate) + outer.AsUnionOrIntersectionType().propertyCacheWithoutFunctionPropertyAugment[ast.MakeSymbolName("value")] = conflicting assert.Assert(t, c.somePropertyReducesToNever(outer)) assert.Equal(t, c.freePropertyCounts, workspace) for counts := c.freePropertyCounts; counts != nil; counts = counts.next { assert.Equal(t, counts.Size(), 0) - assert.Assert(t, !counts.Has("value")) + assert.Assert(t, !counts.Has(ast.MakeSymbolName("value"))) } } @@ -628,7 +628,7 @@ func TestSignatureExtra(t *testing.T) { assert.Equal(t, sig.TypeParameters()[0], types[1]) parameter := &ast.Symbol{} sig.setThisParameter(c, parameter) - predicate := c.newTypePredicate(TypePredicateKindIdentifier, "p", 0, types[0]) + predicate := c.newTypePredicate(TypePredicateKindIdentifier, ast.MakeSymbolName("p"), 0, types[0]) sig.setResolvedTypePredicate(c, predicate) assert.Equal(t, c.getTypePredicateOfSignature(sig), predicate) composite := &CompositeSignature{isUnion: true, signatures: []*Signature{sig}} diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index 3a7e9993ba879..2326d8f6b5bad 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -382,7 +382,7 @@ func (c *Checker) compareSymbolsWorker(s1, s2 *ast.Symbol) int { } else if len(s2.Declarations()) != 0 { return 1 } - if r := strings.Compare(s1.Name(), s2.Name()); r != 0 { + if r := strings.Compare(s1.Name().Value(), s2.Name().Value()); r != 0 { return r } // Fall back to symbol IDs. This is a last resort that should happen only when symbols have @@ -645,7 +645,7 @@ func compareTypeNames(t1, t2 *Type) int { if s2 == nil { return -1 } - if c := strings.Compare(s1.Name(), s2.Name()); c != 0 { + if c := strings.Compare(s1.Name().Value(), s2.Name().Value()); c != 0 { return c } // Keep distinct same-named declarations together before comparing alias arguments or structure. @@ -934,7 +934,7 @@ func (c *Checker) releaseTemporaryTypeSet(set *temporaryTypeSet) { } type temporaryPropertyCounts struct { - collections.OrderedMap[string, int] + collections.OrderedMap[ast.SymbolName, int] next *temporaryPropertyCounts } @@ -1005,12 +1005,12 @@ func isTypeUsableAsPropertyName(t *Type) bool { /** * Gets the symbolic name for a member from its type. */ -func getPropertyNameFromType(t *Type) string { +func getPropertyNameFromType(t *Type) ast.SymbolName { switch { case t.flags&TypeFlagsStringLiteral != 0: - return t.AsLiteralType().value.(string) + return ast.MakeSymbolName(t.AsLiteralType().value.(string)) case t.flags&TypeFlagsNumberLiteral != 0: - return t.AsLiteralType().value.(jsnum.Number).String() + return ast.MakeSymbolName(t.AsLiteralType().value.(jsnum.Number).String()) case t.flags&TypeFlagsUniqueESSymbol != 0: return t.AsUniqueESSymbolType().name } @@ -1102,10 +1102,11 @@ func IsPrivateIdentifierSymbol(symbol *ast.Symbol) bool { if symbol == nil { return false } - return strings.HasPrefix(symbol.Name(), ast.InternalSymbolNamePrefix+"#") + return strings.HasPrefix(symbol.Name().Value(), ast.InternalSymbolNamePrefix+"#") } -func isLateBoundName(name string) bool { +func isLateBoundName(symbolName ast.SymbolName) bool { + name := symbolName.Value() return len(name) >= 2 && name[0] == '\xfe' && name[1] == '@' } @@ -1412,31 +1413,31 @@ type FeatureMapEntry struct { props []string } -var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { - return map[string][]FeatureMapEntry{ - "Array": { +var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { + return map[ast.SymbolName][]FeatureMapEntry{ + ast.SymbolNameArray: { {lib: "es2015", props: []string{"find", "findIndex", "fill", "copyWithin", "entries", "keys", "values"}}, {lib: "es2016", props: []string{"includes"}}, {lib: "es2019", props: []string{"flat", "flatMap"}}, {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Iterator": { + ast.SymbolNameIterator: { {lib: "es2015", props: []string{}}, }, - "IteratorConstructor": { + ast.SymbolNameIteratorConstructor: { {lib: "es2026", props: []string{"concat"}}, }, - "RawJSON": { + ast.SymbolNameRawJSON: { {lib: "es2026", props: []string{}}, }, - "JSON": { + ast.SymbolNameJSON: { {lib: "es2026", props: []string{"isRawJSON", "rawJSON"}}, }, - "AsyncIterator": { + ast.SymbolNameAsyncIterator: { {lib: "es2015", props: []string{}}, }, - "ArrayBuffer": { + ast.SymbolNameArrayBuffer: { {lib: "es2024", props: []string{ "maxByteLength", "resizable", @@ -1446,7 +1447,7 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "transferToFixedLength", }}, }, - "Atomics": { + ast.SymbolNameAtomics: { {lib: "es2017", props: []string{ "add", "and", @@ -1465,7 +1466,7 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "waitAsync", }}, }, - "SharedArrayBuffer": { + ast.SymbolNameSharedArrayBuffer: { {lib: "es2017", props: []string{ "byteLength", "slice", @@ -1476,59 +1477,59 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "grow", }}, }, - "AsyncIterable": { + ast.SymbolNameAsyncIterable: { {lib: "es2018", props: []string{}}, }, - "AsyncIterableIterator": { + ast.SymbolNameAsyncIterableIterator: { {lib: "es2018", props: []string{}}, }, - "AsyncGenerator": { + ast.SymbolNameAsyncGenerator: { {lib: "es2018", props: []string{}}, }, - "AsyncGeneratorFunction": { + ast.SymbolNameAsyncGeneratorFunction: { {lib: "es2018", props: []string{}}, }, - "RegExp": { + ast.SymbolNameRegExp: { {lib: "es2015", props: []string{"flags", "sticky", "unicode"}}, {lib: "es2018", props: []string{"dotAll"}}, {lib: "es2024", props: []string{"unicodeSets"}}, }, - "RegExpConstructor": { + ast.SymbolNameRegExpConstructor: { {lib: "es2025", props: []string{"escape"}}, }, - "Reflect": { + ast.SymbolNameReflect: { {lib: "es2015", props: []string{"apply", "construct", "defineProperty", "deleteProperty", "get", "getOwnPropertyDescriptor", "getPrototypeOf", "has", "isExtensible", "ownKeys", "preventExtensions", "set", "setPrototypeOf"}}, }, - "ArrayConstructor": { + ast.SymbolNameArrayConstructor: { {lib: "es2015", props: []string{"from", "of"}}, {lib: "es2026", props: []string{"fromAsync"}}, }, - "ObjectConstructor": { + ast.SymbolNameObjectConstructor: { {lib: "es2015", props: []string{"assign", "getOwnPropertySymbols", "keys", "is", "setPrototypeOf"}}, {lib: "es2017", props: []string{"values", "entries", "getOwnPropertyDescriptors"}}, {lib: "es2019", props: []string{"fromEntries"}}, {lib: "es2022", props: []string{"hasOwn"}}, {lib: "es2024", props: []string{"groupBy"}}, }, - "NumberConstructor": { + ast.SymbolNameNumberConstructor: { {lib: "es2015", props: []string{"isFinite", "isInteger", "isNaN", "isSafeInteger", "parseFloat", "parseInt"}}, }, - "Math": { + ast.SymbolNameMath: { {lib: "es2015", props: []string{"clz32", "imul", "sign", "log10", "log2", "log1p", "expm1", "cosh", "sinh", "tanh", "acosh", "asinh", "atanh", "hypot", "trunc", "fround", "cbrt"}}, {lib: "es2025", props: []string{"f16round"}}, {lib: "es2026", props: []string{"sumPrecise"}}, }, - "Map": { + ast.SymbolNameMap: { {lib: "es2015", props: []string{"entries", "keys", "values"}}, {lib: "es2026", props: []string{ "getOrInsert", "getOrInsertComputed", }}, }, - "MapConstructor": { + ast.SymbolNameMapConstructor: { {lib: "es2024", props: []string{"groupBy"}}, }, - "Set": { + ast.SymbolNameSet: { {lib: "es2015", props: []string{"entries", "keys", "values"}}, {lib: "es2025", props: []string{ "union", @@ -1540,28 +1541,28 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "isDisjointFrom", }}, }, - "PromiseConstructor": { + ast.SymbolNamePromiseConstructor: { {lib: "es2015", props: []string{"all", "race", "reject", "resolve"}}, {lib: "es2020", props: []string{"allSettled"}}, {lib: "es2021", props: []string{"any"}}, {lib: "es2024", props: []string{"withResolvers"}}, {lib: "es2025", props: []string{"try"}}, }, - "Symbol": { + ast.SymbolNameSymbol: { {lib: "es2015", props: []string{"for", "keyFor"}}, {lib: "es2019", props: []string{"description"}}, }, - "WeakMap": { + ast.SymbolNameWeakMap: { {lib: "es2015", props: []string{}}, {lib: "es2026", props: []string{ "getOrInsert", "getOrInsertComputed", }}, }, - "WeakSet": { + ast.SymbolNameWeakSet: { {lib: "es2015", props: []string{}}, }, - "String": { + ast.SymbolNameString: { {lib: "es2015", props: []string{"codePointAt", "includes", "endsWith", "normalize", "repeat", "startsWith", "anchor", "big", "blink", "bold", "fixed", "fontcolor", "fontsize", "italics", "link", "small", "strike", "sub", "sup"}}, {lib: "es2017", props: []string{"padStart", "padEnd"}}, {lib: "es2019", props: []string{"trimStart", "trimEnd", "trimLeft", "trimRight"}}, @@ -1570,33 +1571,33 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { {lib: "es2022", props: []string{"at"}}, {lib: "es2024", props: []string{"isWellFormed", "toWellFormed"}}, }, - "StringConstructor": { + ast.SymbolNameStringConstructor: { {lib: "es2015", props: []string{"fromCodePoint", "raw"}}, }, - "DateTimeFormat": { + ast.SymbolNameDateTimeFormat: { {lib: "es2017", props: []string{"formatToParts"}}, }, - "Promise": { + ast.SymbolNamePromise: { {lib: "es2015", props: []string{}}, {lib: "es2018", props: []string{"finally"}}, }, - "RegExpMatchArray": { + ast.SymbolNameRegExpMatchArray: { {lib: "es2018", props: []string{"groups"}}, }, - "RegExpExecArray": { + ast.SymbolNameRegExpExecArray: { {lib: "es2018", props: []string{"groups"}}, }, - "Intl": { + ast.SymbolNameIntl: { {lib: "es2018", props: []string{"PluralRules"}}, {lib: "es2020", props: []string{"RelativeTimeFormat", "Locale", "DisplayNames"}}, {lib: "es2021", props: []string{"ListFormat", "DateTimeFormat"}}, {lib: "es2022", props: []string{"Segmenter"}}, {lib: "es2025", props: []string{"DurationFormat"}}, }, - "NumberFormat": { + ast.SymbolNameNumberFormat: { {lib: "es2018", props: []string{"formatToParts"}}, }, - "SymbolConstructor": { + ast.SymbolNameSymbolConstructor: { {lib: "es2020", props: []string{"matchAll"}}, {lib: "esnext", props: []string{ "metadata", @@ -1604,82 +1605,82 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "asyncDispose", }}, }, - "DataView": { + ast.SymbolNameDataView: { {lib: "es2020", props: []string{"setBigInt64", "setBigUint64", "getBigInt64", "getBigUint64"}}, {lib: "es2025", props: []string{"setFloat16", "getFloat16"}}, }, - "BigInt": { + ast.SymbolNameBigInt: { {lib: "es2020", props: []string{}}, }, - "RelativeTimeFormat": { + ast.SymbolNameRelativeTimeFormat: { {lib: "es2020", props: []string{"format", "formatToParts", "resolvedOptions"}}, }, - "Int8Array": { + ast.SymbolNameInt8Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Uint8Array": { + ast.SymbolNameUint8Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, {lib: "es2026", props: []string{"toBase64", "setFromBase64", "toHex", "setFromHex"}}, }, - "Uint8ClampedArray": { + ast.SymbolNameUint8ClampedArray: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Int16Array": { + ast.SymbolNameInt16Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Uint16Array": { + ast.SymbolNameUint16Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Int32Array": { + ast.SymbolNameInt32Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Uint32Array": { + ast.SymbolNameUint32Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Float16Array": { + ast.SymbolNameFloat16Array: { {lib: "es2025", props: []string{}}, }, - "Float32Array": { + ast.SymbolNameFloat32Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Float64Array": { + ast.SymbolNameFloat64Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "BigInt64Array": { + ast.SymbolNameBigInt64Array: { {lib: "es2020", props: []string{}}, {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "BigUint64Array": { + ast.SymbolNameBigUint64Array: { {lib: "es2020", props: []string{}}, {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Error": { + ast.SymbolNameError: { {lib: "es2022", props: []string{"cause"}}, }, - "ErrorConstructor": { + ast.SymbolNameErrorConstructor: { {lib: "es2026", props: []string{"isError"}}, }, - "Uint8ArrayConstructor": { + ast.SymbolNameUint8ArrayConstructor: { {lib: "es2026", props: []string{"fromBase64", "fromHex"}}, }, - "DisposableStack": { + ast.SymbolNameDisposableStack: { {lib: "esnext", props: []string{}}, }, - "AsyncDisposableStack": { + ast.SymbolNameAsyncDisposableStack: { {lib: "esnext", props: []string{}}, }, - "Date": { + ast.SymbolNameDate: { {lib: "esnext", props: []string{"toTemporalInstant"}}, }, } @@ -1699,7 +1700,7 @@ func tryGetPropertyAccessOrIdentifierToString(expr *ast.Node) string { case ast.IsElementAccessExpression(expr): baseStr := tryGetPropertyAccessOrIdentifierToString(expr.Expression()) if baseStr != "" && ast.IsPropertyName(expr.AsElementAccessExpression().ArgumentExpression) { - return baseStr + "." + ast.GetPropertyNameForPropertyNameNode(expr.AsElementAccessExpression().ArgumentExpression) + return baseStr + "." + ast.GetPropertyNameForPropertyNameNode(expr.AsElementAccessExpression().ArgumentExpression).Value() } case ast.IsIdentifier(expr): return expr.Text() @@ -1753,7 +1754,8 @@ func getAnyImportSyntax(node *ast.Node) *ast.Node { // A reserved member name consists of the byte 0xFE (which is an invalid UTF-8 encoding) followed by one or more // characters where the first character is not '@' or '#'. The '@' character indicates that the name is denoted by // a well known ES Symbol instance and the '#' character indicates that the name is a PrivateIdentifier. -func isReservedMemberName(name string) bool { +func isReservedMemberName(symbolName ast.SymbolName) bool { + name := symbolName.Value() return len(name) >= 2 && name[0] == '\xFE' && name[1] != '@' && name[1] != '#' } diff --git a/tsc/internal/ls/autoimport/export.go b/tsc/internal/ls/autoimport/export.go index 4ed8512b05327..76739b4dd0cdd 100644 --- a/tsc/internal/ls/autoimport/export.go +++ b/tsc/internal/ls/autoimport/export.go @@ -64,7 +64,7 @@ func (m ModuleID) AsModuleSpecifier() (tspath.ModuleSpecifier, bool) { type ExportID struct { ModuleID ModuleID - ExportName string + ExportName ast.SymbolName } type ExportSyntax int @@ -97,10 +97,10 @@ type Export struct { UnresolvedModuleSpecifier tspath.ModuleSpecifier Syntax ExportSyntax Flags ast.SymbolFlags - localName string + localName ast.SymbolName // through is the name of the module symbol's export that this export was found on, - // either 'export=', InternalSymbolNameExportStar, or empty string. - through string + // either 'export=', InternalSymbolNameExportStar, or unset. + through ast.SymbolName // Checker-set fields @@ -115,8 +115,8 @@ type Export struct { PackageName string } -func (e *Export) Name() string { - if e.localName != "" { +func (e *Export) Name() ast.SymbolName { + if !e.localName.IsZero() && e.localName != ast.EmptySymbolName { return e.localName } if e.ExportName == ast.InternalSymbolNameExportEquals { @@ -172,7 +172,7 @@ func SymbolToExport(symbol *ast.Symbol, ch *checker.Checker) *Export { return tryGetModuleExport(symbol.Name(), target, moduleSymbol, ch, moduleID, moduleFileName, file) } -func tryGetModuleExport(exportName string, target *ast.Symbol, moduleSymbol *ast.Symbol, ch *checker.Checker, moduleID ModuleID, moduleFileName tspath.RootedFilePath, file *ast.SourceFile) *Export { +func tryGetModuleExport(exportName ast.SymbolName, target *ast.Symbol, moduleSymbol *ast.Symbol, ch *checker.Checker, moduleID ModuleID, moduleFileName tspath.RootedFilePath, file *ast.SourceFile) *Export { exported := ch.TryGetMemberInModuleExportsAndProperties(exportName, moduleSymbol) if exported != nil && ch.GetMergedSymbol(ch.SkipAlias(exported)) == target { return extractFirstExport(exported, ch, moduleID, moduleFileName, file) diff --git a/tsc/internal/ls/autoimport/extract.go b/tsc/internal/ls/autoimport/extract.go index 12ea044255167..e7adb14807080 100644 --- a/tsc/internal/ls/autoimport/extract.go +++ b/tsc/internal/ls/autoimport/extract.go @@ -181,7 +181,7 @@ func (e *exportExtractor) extractFromModuleDeclaration(decl *ast.ModuleDeclarati } } -func (e *symbolExtractor) extractFromSymbol(name string, symbol *ast.Symbol, moduleID ModuleID, moduleFileName tspath.RootedFilePath, file *ast.SourceFile, exports *[]*Export) { +func (e *symbolExtractor) extractFromSymbol(name ast.SymbolName, symbol *ast.Symbol, moduleID ModuleID, moduleFileName tspath.RootedFilePath, file *ast.SourceFile, exports *[]*Export) { if shouldIgnoreSymbol(symbol) { return } @@ -251,7 +251,7 @@ func (e *symbolExtractor) extractFromSymbol(name string, symbol *ast.Symbol, mod *exports = slices.Grow(*exports, len(expression.AsObjectLiteralExpression().Properties.Nodes)) for _, prop := range expression.AsObjectLiteralExpression().Properties.Nodes { if ast.IsShorthandPropertyAssignment(prop) || ast.IsPropertyAssignment(prop) && prop.AsPropertyAssignment().Name().Kind == ast.KindIdentifier { - export, _ := e.createExport(expression.Symbol().Members()[prop.Name().Text()], moduleID, moduleFileName, syntax, file, checkerLease) + export, _ := e.createExport(expression.Symbol().Members()[prop.Name().TextSymbolName()], moduleID, moduleFileName, syntax, file, checkerLease) if export != nil { export.through = name *exports = append(*exports, export) @@ -352,7 +352,7 @@ func (e *symbolExtractor) createExport(symbol *ast.Symbol, moduleID ModuleID, mo // Last resort: derive identifier from the file name. Use FileName() (original // casing) rather than ModuleID/Path() which is lowercased on case-insensitive // file systems, losing PascalCase. - export.localName = lsutil.ModuleSpecifierToValidIdentifier(fileNameForDefaultExportName(targetSymbol, moduleFileName, moduleID), false) + export.localName = ast.MakeSymbolName(lsutil.ModuleSpecifierToValidIdentifier(fileNameForDefaultExportName(targetSymbol, moduleFileName, moduleID), false)) } } @@ -399,7 +399,7 @@ func (e *symbolExtractor) tryResolveSymbol(symbol *ast.Symbol, syntax ExportSynt } if loc != nil { - local := e.localNameResolver.Resolve(loc, name, ast.SymbolFlagsAll, nil, false, false) + local := e.localNameResolver.Resolve(loc, ast.MakeSymbolName(name), ast.SymbolFlagsAll, nil, false, false) if local != nil && !ast.IsNonLocalAlias(local, ast.SymbolFlagsNone) { return local } @@ -450,9 +450,9 @@ func getSyntax(symbol *ast.Symbol) ExportSyntax { return ExportSyntaxNone } -func isUnusableName(name string) bool { - return name == "" || - name == "_default" || +func isUnusableName(name ast.SymbolName) bool { + return name.IsZero() || name == ast.EmptySymbolName || + name == ast.SymbolNameUnderscoreDefault || name == ast.InternalSymbolNameExportStar || name == ast.InternalSymbolNameDefault || name == ast.InternalSymbolNameExportEquals diff --git a/tsc/internal/ls/autoimport/fix.go b/tsc/internal/ls/autoimport/fix.go index d0f5e27da6047..42474d4605fbe 100644 --- a/tsc/internal/ls/autoimport/fix.go +++ b/tsc/internal/ls/autoimport/fix.go @@ -30,7 +30,7 @@ import ( type newImportBinding struct { kind lsproto.ImportKind propertyName string - name string + name ast.SymbolName addAsTypeOnly lsproto.AddAsTypeOnly } @@ -82,12 +82,13 @@ func (f *Fix) Edits( return edits, diagnostics.Update_import_from_0.Localize(locale, f.ModuleSpecifier), safe case lsproto.AutoImportFixKindAddNew: var declarations []*ast.Statement - defaultImport := core.IfElse(f.ImportKind == lsproto.ImportKindDefault, &newImportBinding{name: f.Name, addAsTypeOnly: f.AddAsTypeOnly}, nil) - namedImports := core.IfElse(f.ImportKind == lsproto.ImportKindNamed, []*newImportBinding{{name: f.Name, addAsTypeOnly: f.AddAsTypeOnly}}, nil) + name := ast.MakeSymbolName(f.Name) + defaultImport := core.IfElse(f.ImportKind == lsproto.ImportKindDefault, &newImportBinding{name: name, addAsTypeOnly: f.AddAsTypeOnly}, nil) + namedImports := core.IfElse(f.ImportKind == lsproto.ImportKindNamed, []*newImportBinding{{name: name, addAsTypeOnly: f.AddAsTypeOnly}}, nil) var namespaceLikeImport *newImportBinding // qualification := f.qualification() if f.ImportKind == lsproto.ImportKindNamespace || f.ImportKind == lsproto.ImportKindCommonJS { - namespaceLikeImport = &newImportBinding{kind: f.ImportKind, name: f.Name} + namespaceLikeImport = &newImportBinding{kind: f.ImportKind, name: name} // if qualification != nil && qualification.namespacePref != "" { // namespaceLikeImport.name = qualification.namespacePref // } @@ -193,8 +194,9 @@ func getAddToExistingImportFix(file *ast.SourceFile, fix *Fix) *addToExistingImp panic("expected import declaration or require call expression") } - defaultImport := core.IfElse(fix.ImportKind == lsproto.ImportKindDefault, &newImportBinding{kind: lsproto.ImportKindDefault, name: fix.Name, addAsTypeOnly: fix.AddAsTypeOnly}, nil) - namedImports := core.IfElse(fix.ImportKind == lsproto.ImportKindNamed, &newImportBinding{kind: lsproto.ImportKindNamed, name: fix.Name, addAsTypeOnly: fix.AddAsTypeOnly}, nil) + name := ast.MakeSymbolName(fix.Name) + defaultImport := core.IfElse(fix.ImportKind == lsproto.ImportKindDefault, &newImportBinding{kind: lsproto.ImportKindDefault, name: name, addAsTypeOnly: fix.AddAsTypeOnly}, nil) + namedImports := core.IfElse(fix.ImportKind == lsproto.ImportKindNamed, &newImportBinding{kind: lsproto.ImportKindNamed, name: name, addAsTypeOnly: fix.AddAsTypeOnly}, nil) return &addToExistingImportFix{ importClauseOrBindingPattern: importClauseOrBindingPattern, defaultImport: defaultImport, @@ -214,10 +216,10 @@ func addToExistingImport( case ast.KindObjectBindingPattern: bindingPattern := importClauseOrBindingPattern.AsBindingPattern() if defaultImport != nil { - addElementToBindingPattern(ct, file, bindingPattern, defaultImport.name, "default") + addElementToBindingPattern(ct, file, bindingPattern, defaultImport.name.Value(), "default") } for _, namedImport := range namedImports { - addElementToBindingPattern(ct, file, bindingPattern, namedImport.name, "") + addElementToBindingPattern(ct, file, bindingPattern, namedImport.name.Value(), "") } return case ast.KindImportClause: @@ -238,7 +240,7 @@ func addToExistingImport( if defaultImport != nil { debug.Assert(importClause.Name() == nil, "Cannot add a default import to an import clause that already has one") - ct.InsertNodeAt(file, core.TextPos(astnav.GetStartOfNode(importClause.AsNode(), file, false)), ct.NodeFactory.NewIdentifier(defaultImport.name), change.NodeOptions{Suffix: ", "}) + ct.InsertNodeAt(file, core.TextPos(astnav.GetStartOfNode(importClause.AsNode(), file, false)), ct.NodeFactory.NewIdentifier(defaultImport.name.Value()), change.NodeOptions{Suffix: ", "}) } if len(namedImports) > 0 { @@ -251,7 +253,7 @@ func addToExistingImport( return ct.NodeFactory.NewImportSpecifier( (!importClause.IsTypeOnly() || promoteFromTypeOnly) && shouldUseTypeOnly(namedImport.addAsTypeOnly, preferences), identifier, - ct.NodeFactory.NewIdentifier(namedImport.name), + ct.NodeFactory.NewIdentifier(namedImport.name.Value()), ) }) slices.SortFunc(newSpecifiers, specifierComparer) @@ -374,7 +376,7 @@ func getNewImports( var defaultImportNode *ast.Node if defaultImport != nil { - defaultImportNode = ct.NodeFactory.NewIdentifier(defaultImport.name) + defaultImportNode = ct.NodeFactory.NewIdentifier(defaultImport.name.Value()) } statements = append(statements, makeImport(ct, defaultImportNode, core.Map(namedImports, func(namedImport *newImportBinding) *ast.Node { @@ -385,7 +387,7 @@ func getNewImports( return ct.NodeFactory.NewImportSpecifier( !topLevelTypeOnly && shouldUseTypeOnly(namedImport.addAsTypeOnly, preferences), namedImportPropertyName, - ct.NodeFactory.NewIdentifier(namedImport.name), + ct.NodeFactory.NewIdentifier(namedImport.name.Value()), ) }), moduleSpecifierStringLiteral, topLevelTypeOnly)) } @@ -396,7 +398,7 @@ func getNewImports( declaration = ct.NodeFactory.NewImportEqualsDeclaration( /*modifiers*/ nil, shouldUseTypeOnly(namespaceLikeImport.addAsTypeOnly, preferences), - ct.NodeFactory.NewIdentifier(namespaceLikeImport.name), + ct.NodeFactory.NewIdentifier(namespaceLikeImport.name.Value()), ct.NodeFactory.NewExternalModuleReference(moduleSpecifierStringLiteral), ) } else { @@ -405,7 +407,7 @@ func getNewImports( ct.NodeFactory.NewImportClause( /*phaseModifier*/ core.IfElse(shouldUseTypeOnly(namespaceLikeImport.addAsTypeOnly, preferences), ast.KindTypeKeyword, ast.KindUnknown), /*name*/ nil, - ct.NodeFactory.NewNamespaceImport(ct.NodeFactory.NewIdentifier(namespaceLikeImport.name)), + ct.NodeFactory.NewNamespaceImport(ct.NodeFactory.NewIdentifier(namespaceLikeImport.name.Value())), ), moduleSpecifierStringLiteral, /*attributes*/ nil, @@ -445,7 +447,7 @@ func getNewRequires( bindingElements = append(bindingElements, changeTracker.NodeFactory.NewBindingElement( /*dotDotDotToken*/ nil, propertyName, - changeTracker.NodeFactory.NewIdentifier(namedImport.name), + changeTracker.NodeFactory.NewIdentifier(namedImport.name.Value()), /*initializer*/ nil, )) } @@ -454,7 +456,7 @@ func getNewRequires( changeTracker.NodeFactory.NewBindingElement( /*dotDotDotToken*/ nil, changeTracker.NodeFactory.NewIdentifier("default"), - changeTracker.NodeFactory.NewIdentifier(defaultImport.name), + changeTracker.NodeFactory.NewIdentifier(defaultImport.name.Value()), /*initializer*/ nil, ), }, bindingElements...) @@ -474,7 +476,7 @@ func getNewRequires( if namespaceLikeImport != nil { declaration := createConstEqualsRequireDeclaration( changeTracker, - changeTracker.NodeFactory.NewIdentifier(namespaceLikeImport.name), + changeTracker.NodeFactory.NewIdentifier(namespaceLikeImport.name.Value()), quotedModuleSpecifier, ) statements = append(statements, declaration) @@ -588,7 +590,7 @@ func (v *View) GetFixes(export *Export, forJSX bool, isValidTypeOnlyUseSite bool AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindJsdocTypeImport, ModuleSpecifier: moduleSpecifier.AsString(), - Name: export.Name(), + Name: export.Name().Value(), UsagePosition: usagePosition, }, ModuleSpecifierKind: moduleSpecifierKind, @@ -602,10 +604,11 @@ func (v *View) GetFixes(export *Export, forJSX bool, isValidTypeOnlyUseSite bool addAsTypeOnly := getAddAsTypeOnly(isValidTypeOnlyUseSite, export, v.program.Options()) name := export.Name() - startsWithUpper := unicode.IsUpper(rune(name[0])) + nameText := name.Value() + startsWithUpper := unicode.IsUpper(rune(nameText[0])) if forJSX && !startsWithUpper { if export.IsRenameable() { - name = fmt.Sprintf("%c%s", unicode.ToUpper(rune(name[0])), name[1:]) + name = ast.MakeSymbolName(fmt.Sprintf("%c%s", unicode.ToUpper(rune(nameText[0])), nameText[1:])) } else { return nil } @@ -616,7 +619,7 @@ func (v *View) GetFixes(export *Export, forJSX bool, isValidTypeOnlyUseSite bool Kind: lsproto.AutoImportFixKindAddNew, ImportKind: importKind, ModuleSpecifier: moduleSpecifier.AsString(), - Name: name, + Name: name.Value(), UseRequire: v.shouldUseRequire(), AddAsTypeOnly: addAsTypeOnly, }, @@ -659,7 +662,7 @@ func (v *View) tryUseExistingNamespaceImport(export *Export, usagePosition *lspr return &Fix{ AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindUseNamespace, - Name: export.Name(), + Name: export.Name().Value(), ModuleSpecifier: existingImport.moduleSpecifier, ImportKind: lsproto.ImportKindNamespace, AddAsTypeOnly: lsproto.AddAsTypeOnlyAllowed, @@ -729,7 +732,7 @@ func (v *View) tryAddToExistingImport( fix := &Fix{ AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindAddToExisting, - Name: export.Name(), + Name: export.Name().Value(), ImportKind: importKind, ImportIndex: int32(existingImport.index), ModuleSpecifier: existingImport.moduleSpecifier, @@ -780,7 +783,7 @@ func (v *View) tryAddToExistingImport( fix := &Fix{ AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindAddToExisting, - Name: export.Name(), + Name: export.Name().Value(), ImportKind: importKind, ImportIndex: int32(existingImport.index), ModuleSpecifier: existingImport.moduleSpecifier, diff --git a/tsc/internal/ls/autoimport/import_adder.go b/tsc/internal/ls/autoimport/import_adder.go index facc01393ad0b..dd5c481274b9b 100644 --- a/tsc/internal/ls/autoimport/import_adder.go +++ b/tsc/internal/ls/autoimport/import_adder.go @@ -5,6 +5,7 @@ import ( "fmt" "maps" "slices" + "strings" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -32,13 +33,13 @@ type ImportAdder interface { type addToExistingState struct { importClauseOrBindingPattern *ast.ImportClauseOrBindingPattern defaultImport *newImportBinding - namedImports map[string]*newImportBinding + namedImports map[ast.SymbolName]*newImportBinding } // importsCollection tracks new imports to be created for a given module specifier type importsCollection struct { defaultImport *newImportBinding - namedImports map[string]*newImportBinding + namedImports map[ast.SymbolName]*newImportBinding namespaceLikeImport *newImportBinding useRequire bool } @@ -175,8 +176,8 @@ func (adder *importAdder) Edits() []*lsproto.TextEdit { return changes[adder.view.importingFile.OriginalFileName()] } -func sortedNamedImports(m map[string]*newImportBinding) []*newImportBinding { - keys := slices.Sorted(maps.Keys(m)) +func sortedNamedImports(m map[ast.SymbolName]*newImportBinding) []*newImportBinding { + keys := slices.SortedFunc(maps.Keys(m), func(a, b ast.SymbolName) int { return strings.Compare(a.Value(), b.Value()) }) result := make([]*newImportBinding, 0, len(keys)) for _, k := range keys { result = append(result, m[k]) @@ -187,7 +188,7 @@ func sortedNamedImports(m map[string]*newImportBinding) []*newImportBinding { // AddImportFix adds a fix to the import adder, accumulating it with other fixes // so that multiple imports from the same module are coalesced into a single import statement. func (adder *importAdder) AddImportFix(fix *Fix) { - symbolName := fix.Name + symbolName := ast.MakeSymbolName(fix.Name) compilerOptions := adder.view.program.Options() switch fix.Kind { @@ -201,7 +202,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { if entry == nil { entry = &addToExistingState{ importClauseOrBindingPattern: existingFix.importClauseOrBindingPattern, - namedImports: make(map[string]*newImportBinding), + namedImports: make(map[ast.SymbolName]*newImportBinding), } adder.addToExisting[existingFix.importClauseOrBindingPattern] = entry } @@ -260,7 +261,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { case lsproto.ImportKindNamed: if entry.namedImports == nil { - entry.namedImports = make(map[string]*newImportBinding) + entry.namedImports = make(map[ast.SymbolName]*newImportBinding) } prevImport := entry.namedImports[symbolName] var prevTypeOnly lsproto.AddAsTypeOnly @@ -277,7 +278,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { case lsproto.ImportKindCommonJS: if compilerOptions.VerbatimModuleSyntax == core.TSTrue { if entry.namedImports == nil { - entry.namedImports = make(map[string]*newImportBinding) + entry.namedImports = make(map[ast.SymbolName]*newImportBinding) } prevImport := entry.namedImports[symbolName] var prevTypeOnly lsproto.AddAsTypeOnly @@ -469,13 +470,13 @@ func getNameForExportedSymbol(symbol *ast.Symbol, preferCapitalized bool) string // - export { foo as default } => foo // - export default 0 => filename converted to camelCase name := getDefaultLikeExportNameFromDeclaration(symbol) - if name != "" { - return name + if name != ast.EmptySymbolName { + return name.Value() } debug.Assert(symbol.Parent() != nil, "Expected exported symbol to have module symbol as parent") return lsutil.ModuleSymbolToValidIdentifier(symbol.Parent(), preferCapitalized) } - return symbol.Name() + return symbol.Name().Value() } func replaceFirstIdentifierOfEntityName(factory *ast.NodeFactory, name *ast.EntityName, newIdentifier *ast.IdentifierNode) *ast.EntityName { diff --git a/tsc/internal/ls/autoimport/index.go b/tsc/internal/ls/autoimport/index.go index 5afb37d927fb0..3f21c54eb2910 100644 --- a/tsc/internal/ls/autoimport/index.go +++ b/tsc/internal/ls/autoimport/index.go @@ -5,12 +5,13 @@ import ( "unicode" "unicode/utf8" + "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" ) // Named is a constraint for types that can provide their name. type Named interface { - Name() string + Name() ast.SymbolName } // Index stores entries with an index mapping uppercase letters to entries whose name @@ -21,11 +22,12 @@ type Index[T Named] struct { index map[rune][]int } -func (idx *Index[T]) Find(name string, caseSensitive bool) []T { - if len(idx.entries) == 0 || len(name) == 0 { +func (idx *Index[T]) Find(name ast.SymbolName, caseSensitive bool) []T { + if len(idx.entries) == 0 || name == ast.EmptySymbolName { return nil } - firstRune := core.FirstResult(utf8.DecodeRuneInString(name)) + nameText := name.Value() + firstRune := core.FirstResult(utf8.DecodeRuneInString(nameText)) if firstRune == utf8.RuneError { return nil } @@ -39,7 +41,7 @@ func (idx *Index[T]) Find(name string, caseSensitive bool) []T { for _, entryIndex := range candidates { entry := idx.entries[entryIndex] entryName := entry.Name() - if (caseSensitive && entryName == name) || (!caseSensitive && strings.EqualFold(entryName, name)) { + if (caseSensitive && entryName == name) || (!caseSensitive && strings.EqualFold(entryName.Value(), nameText)) { results = append(results, entry) } } @@ -85,7 +87,7 @@ func (idx *Index[T]) SearchWordPrefix(prefix string) []T { for _, starts := range [][]int{nameStarts, wordStarts} { for _, i := range starts { entry := idx.entries[i] - if containsCharsInOrder(entry.Name(), prefix) { + if containsCharsInOrder(entry.Name().Value(), prefix) { results = append(results, entry) } } @@ -116,7 +118,7 @@ func (idx *Index[T]) insertAsWords(value T) { idx.index = make(map[rune][]int) } - name := value.Name() + name := value.Name().Value() if len(name) == 0 { panic("Cannot index entry with empty name") } diff --git a/tsc/internal/ls/autoimport/index_test.go b/tsc/internal/ls/autoimport/index_test.go index 1f9299553450d..e13353c7721a7 100644 --- a/tsc/internal/ls/autoimport/index_test.go +++ b/tsc/internal/ls/autoimport/index_test.go @@ -1,8 +1,12 @@ package autoimport import ( + "slices" + "strings" "testing" + "github.com/microsoft/TypeScript/tsc/internal/ast" + "gotest.tools/v3/assert" ) @@ -11,7 +15,24 @@ type testEntry struct { package_ string } -func (e *testEntry) Name() string { return e.name } +func (e *testEntry) Name() ast.SymbolName { return ast.MakeSymbolName(e.name) } + +func TestIndexFind(t *testing.T) { + t.Parallel() + idx := &Index[*testEntry]{} + lower := &testEntry{name: "fooBar"} + upper := &testEntry{name: "FooBar"} + idx.insertAsWords(lower) + idx.insertAsWords(upper) + + assert.Assert(t, slices.Equal(idx.Find(ast.MakeSymbolName(strings.Clone("fooBar")), true), []*testEntry{lower})) + assert.Assert(t, slices.Equal(idx.Find(upper.Name(), true), []*testEntry{upper})) + query := ast.MakeSymbolName(strings.ToUpper(lower.name)) + assert.Assert(t, slices.Equal(idx.Find(query, false), []*testEntry{lower, upper})) + assert.Equal(t, len(idx.Find(query, true)), 0) + assert.Equal(t, len(idx.Find(ast.EmptySymbolName, true)), 0) + assert.Assert(t, slices.Equal(idx.SearchWordPrefix("fb"), []*testEntry{lower, upper})) +} func TestIndexClone(t *testing.T) { t.Parallel() @@ -36,12 +57,12 @@ func TestIndexClone(t *testing.T) { assert.Equal(t, len(cloned.entries), 2) // Search should work on cloned index - results := cloned.Find("fooBar", true) + results := cloned.Find(idx.entries[0].Name(), true) assert.Equal(t, len(results), 1) assert.Equal(t, results[0].name, "fooBar") // bazQux should not be in cloned index - results = cloned.Find("bazQux", true) + results = cloned.Find(idx.entries[1].Name(), true) assert.Equal(t, len(results), 0) // Word prefix search should work diff --git a/tsc/internal/ls/autoimport/util.go b/tsc/internal/ls/autoimport/util.go index 73b4461913afc..5e6519afbdf0c 100644 --- a/tsc/internal/ls/autoimport/util.go +++ b/tsc/internal/ls/autoimport/util.go @@ -114,31 +114,31 @@ func getPackageNamesInNodeModules(nodeModulesDir tspath.RootedDirectoryPath, fs return packageNames } -func getDefaultLikeExportNameFromDeclaration(symbol *ast.Symbol) string { +func getDefaultLikeExportNameFromDeclaration(symbol *ast.Symbol) ast.SymbolName { for _, d := range symbol.Declarations() { // "export default" in this case. See `ExportAssignment`for more details. if ast.IsExportAssignment(d) { if innerExpression := ast.SkipOuterExpressions(d.Expression(), ast.OEKAll); ast.IsIdentifier(innerExpression) { - return innerExpression.Text() + return innerExpression.TextSymbolName() } continue } // "export { ~ as default }" if ast.IsExportSpecifier(d) && d.Symbol().Flags() == ast.SymbolFlagsAlias && d.PropertyName() != nil { if d.PropertyName().Kind == ast.KindIdentifier { - return d.PropertyName().Text() + return d.PropertyName().TextSymbolName() } continue } // GH#52694 if name := ast.GetNameOfDeclaration(d); name != nil && name.Kind == ast.KindIdentifier { - return name.Text() + return name.TextSymbolName() } if symbol.Parent() != nil && !checker.IsExternalModuleSymbol(symbol.Parent()) { return symbol.Parent().Name() } } - return "" + return ast.EmptySymbolName } func getResolvedPackageNames(ctx context.Context, program *compiler.Program) *collections.Set[string] { diff --git a/tsc/internal/ls/autoimport/view.go b/tsc/internal/ls/autoimport/view.go index b743a46b1aa02..28898a3ada312 100644 --- a/tsc/internal/ls/autoimport/view.go +++ b/tsc/internal/ls/autoimport/view.go @@ -78,14 +78,18 @@ const ( ) func (v *View) Search(query string, kind QueryKind) []*Export { + var queryName ast.SymbolName + if kind != QueryKindWordPrefix { + queryName = ast.MakeSymbolName(query) + } searchFn := func(bucket *RegistryBucket) []*Export { switch kind { case QueryKindWordPrefix: return bucket.Index.SearchWordPrefix(query) case QueryKindExactMatch: - return bucket.Index.Find(query, true) + return bucket.Index.Find(queryName, true) case QueryKindCaseInsensitiveMatch: - return bucket.Index.Find(query, false) + return bucket.Index.Find(queryName, false) default: panic("unreachable") } @@ -181,17 +185,17 @@ func (v *View) GetCompletions(prefix string, position lsproto.Position, forJSX b type exportGroupKey struct { target ExportID - name string + name ast.SymbolName ambientModuleOrPackageName string } grouped := make(map[exportGroupKey][]*Export, len(results)) outer: for _, e := range results { name := e.Name() - if !scanner.IsIdentifierText(name, core.LanguageVariantStandard) { + if !scanner.IsIdentifierText(name.Value(), core.LanguageVariantStandard) { continue } - if forJSX && !(unicode.IsUpper(rune(name[0])) || e.IsRenameable()) { + if forJSX && !(unicode.IsUpper(rune(name.Value()[0])) || e.IsRenameable()) { continue } target := e.ExportID diff --git a/tsc/internal/ls/codeactions_fixclassincorrectlyimplementsinterface.go b/tsc/internal/ls/codeactions_fixclassincorrectlyimplementsinterface.go index b91cc1b1c44b4..bb4b54da23007 100644 --- a/tsc/internal/ls/codeactions_fixclassincorrectlyimplementsinterface.go +++ b/tsc/internal/ls/codeactions_fixclassincorrectlyimplementsinterface.go @@ -177,7 +177,7 @@ func getConstructor(classDeclaration *ast.Node) *ast.Node { func getMissingMembers(typeChecker *checker.Checker, classDeclaration *ast.Node, implementedTypes []*checker.Type) []*ast.Symbol { inheritedMembers := getInheritedMembers(typeChecker, classDeclaration) - seenMembers := make(map[string]*ast.Symbol) + seenMembers := make(ast.SymbolTable) var classMembers ast.SymbolTable if classDeclaration.Symbol() != nil { diff --git a/tsc/internal/ls/codeactions_fixmissingtypeannotation.go b/tsc/internal/ls/codeactions_fixmissingtypeannotation.go index 783f2207f78aa..e7f185454adf6 100644 --- a/tsc/internal/ls/codeactions_fixmissingtypeannotation.go +++ b/tsc/internal/ls/codeactions_fixmissingtypeannotation.go @@ -261,7 +261,7 @@ func (f *isolatedDeclarationsFixer) createNamespaceForExpandoProperties(expandoF var newProperties []*ast.Node for _, symbol := range elements { - if !scanner.IsIdentifierText(symbol.Name(), core.LanguageVariantStandard) { + if !scanner.IsIdentifierText(symbol.Name().Value(), core.LanguageVariantStandard) { continue } // skip symbols that already have a variable declaration @@ -275,7 +275,7 @@ func (f *isolatedDeclarationsFixer) createNamespaceForExpandoProperties(expandoF continue } - varDecl := factory.NewVariableDeclaration(factory.NewIdentifier(symbol.Name()), nil, typeNode, nil) + varDecl := factory.NewVariableDeclaration(factory.NewIdentifier(symbol.Name().Value()), nil, typeNode, nil) exportToken := factory.NewToken(ast.KindExportKeyword) varDeclList := factory.NewVariableDeclarationList(factory.NewNodeList([]*ast.Node{varDecl}), ast.NodeFlagsNone) varStmt := factory.NewVariableStatement(factory.NewModifierList([]*ast.Node{exportToken}), varDeclList) @@ -1134,7 +1134,7 @@ func (f *isolatedDeclarationsFixer) relativeType(node *ast.Node) *ast.TypeNode { varDecl := ast.FindAncestorKind(node, ast.KindVariableDeclaration) partName := "" if varDecl != nil && ast.IsIdentifier(varDecl.Name()) { - partName = varDecl.Name().AsIdentifier().Text + partName = varDecl.Name().Text() } return f.typeFromArraySpreadElements(node.AsArrayLiteralExpression(), partName) } @@ -1142,7 +1142,7 @@ func (f *isolatedDeclarationsFixer) relativeType(node *ast.Node) *ast.TypeNode { varDecl := ast.FindAncestorKind(node, ast.KindVariableDeclaration) partName := "" if varDecl != nil && ast.IsIdentifier(varDecl.Name()) { - partName = varDecl.Name().AsIdentifier().Text + partName = varDecl.Name().Text() } return f.typeFromObjectSpreadAssignment(node.AsObjectLiteralExpression(), partName) } @@ -1409,7 +1409,7 @@ func (f *isolatedDeclarationsFixer) addSymbolToExistingImport(sym *ast.Symbol) { // Add to existing named imports existingElements := importClause.NamedBindings.AsNamedImports().Elements.Nodes factory := f.changeTracker.NodeFactory - newSpecifier := factory.NewImportSpecifier(false, nil, factory.NewIdentifier(symbolName)) + newSpecifier := factory.NewImportSpecifier(false, nil, factory.NewIdentifier(symbolName.Value())) newElements := append(existingElements, newSpecifier.AsNode()) newNamedImports := factory.NewNamedImports(factory.NewNodeList(newElements)) newImportClause := factory.UpdateImportClause(importClause, importClause.PhaseModifier, importClause.Name(), newNamedImports) diff --git a/tsc/internal/ls/codeactions_importfixes.go b/tsc/internal/ls/codeactions_importfixes.go index 490d760c73261..085b7dbd8f68b 100644 --- a/tsc/internal/ls/codeactions_importfixes.go +++ b/tsc/internal/ls/codeactions_importfixes.go @@ -258,7 +258,7 @@ func getFixesInfoForUMDImport(token *ast.Node, view *autoimport.View, ch *checke } result = append(result, &fixInfo{ fix: fix, - symbolName: umdSymbol.Name(), + symbolName: umdSymbol.Name().Value(), errorIdentifierText: errorIdentifierText, }) } @@ -286,7 +286,7 @@ func getUmdSymbol(token *ast.Node, ch *checker.Checker) *ast.Symbol { location = parent } jsxNamespace := ch.GetJsxNamespace(parent) - parentSymbol := ch.ResolveName(jsxNamespace, location, ast.SymbolFlagsValue, false /* excludeGlobals */) + parentSymbol := ch.ResolveName(ast.MakeSymbolName(jsxNamespace), location, ast.SymbolFlagsValue, false /* excludeGlobals */) if isUMDExportSymbol(parentSymbol) { return parentSymbol } @@ -333,7 +333,7 @@ func getFixesInfoForNonUMDImport(fixContext *CodeFixContext, symbolToken *ast.No exports := view.Search(symbolName, queryKind) for _, export := range exports { - if isJSXTagName && !(export.Name() == symbolName || export.IsRenameable()) { + if isJSXTagName && !(export.Name() == ast.MakeSymbolName(symbolName) || export.IsRenameable()) { continue } @@ -354,7 +354,7 @@ func getFixesInfoForNonUMDImport(fixContext *CodeFixContext, symbolToken *ast.No func getTypeOnlyPromotionFix(sourceFile *ast.SourceFile, symbolToken *ast.Node, symbolName string, ch *checker.Checker) *autoimport.Fix { // Get the symbol at the token location - symbol := ch.ResolveName(symbolName, symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */) + symbol := ch.ResolveName(ast.MakeSymbolName(symbolName), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */) if symbol == nil { return nil } @@ -387,7 +387,7 @@ func getSymbolNamesToImport(sourceFile *ast.SourceFile, ch *checker.Checker, sym if needsJsxNamespaceFix(jsxNamespace, symbolToken, ch) { var result []symbolNameInfo if !scanner.IsIntrinsicJsxName(symbolToken.Text()) { - compSymbol := ch.ResolveName(symbolToken.Text(), symbolToken, ast.SymbolFlagsValue, false /* excludeGlobals */) + compSymbol := ch.ResolveName(symbolToken.TextSymbolName(), symbolToken, ast.SymbolFlagsValue, false /* excludeGlobals */) if compSymbol == nil { result = append(result, symbolNameInfo{name: symbolToken.Text()}) } else if ch.GetTypeOnlyAliasDeclaration(compSymbol) != nil { @@ -395,7 +395,7 @@ func getSymbolNamesToImport(sourceFile *ast.SourceFile, ch *checker.Checker, sym } } nsIsTypeOnly := false - if nsSymbol := ch.ResolveName(jsxNamespace, symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); nsSymbol != nil { + if nsSymbol := ch.ResolveName(ast.MakeSymbolName(jsxNamespace), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); nsSymbol != nil { nsIsTypeOnly = ch.GetTypeOnlyAliasDeclaration(nsSymbol) != nil } result = append(result, symbolNameInfo{name: jsxNamespace, isTypeOnly: nsIsTypeOnly}) @@ -403,7 +403,7 @@ func getSymbolNamesToImport(sourceFile *ast.SourceFile, ch *checker.Checker, sym } } tokenIsTypeOnly := false - if sym := ch.ResolveName(symbolToken.Text(), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); sym != nil { + if sym := ch.ResolveName(symbolToken.TextSymbolName(), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); sym != nil { tokenIsTypeOnly = ch.GetTypeOnlyAliasDeclaration(sym) != nil } return []symbolNameInfo{{name: symbolToken.Text(), isTypeOnly: tokenIsTypeOnly}} @@ -413,7 +413,7 @@ func needsJsxNamespaceFix(jsxNamespace string, symbolToken *ast.Node, ch *checke if scanner.IsIntrinsicJsxName(symbolToken.Text()) { return true } - namespaceSymbol := ch.ResolveName(jsxNamespace, symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */) + namespaceSymbol := ch.ResolveName(ast.MakeSymbolName(jsxNamespace), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */) if namespaceSymbol == nil { return true } diff --git a/tsc/internal/ls/codeactions_missingmemberfixer.go b/tsc/internal/ls/codeactions_missingmemberfixer.go index 4f1cf6caf0a36..fc7e4b3b1c690 100644 --- a/tsc/internal/ls/codeactions_missingmemberfixer.go +++ b/tsc/internal/ls/codeactions_missingmemberfixer.go @@ -111,7 +111,7 @@ func (f *missingMemberFixer) createMemberFromSymbol(symbol *ast.Symbol, enclosin nodes = append(nodes, f.changeTracker.NodeFactory.NewSetAccessorDeclaration( modifiers, createPropertyName(f.changeTracker.NodeFactory, declarationName, quotePreference), - nil /*typeParameters*/, createDummyParameters(f.changeTracker.NodeFactory, 1, []string{parameter.Name().Text()}, []*ast.TypeNode{f.createTypeNode(t, enclosingDeclaration, flags, nodeBuilder, idToSymbol)}, 1, ast.IsInJSFile(enclosingDeclaration)), + nil /*typeParameters*/, createDummyParameters(f.changeTracker.NodeFactory, 1, []ast.SymbolName{parameter.Name().TextSymbolName()}, []*ast.TypeNode{f.createTypeNode(t, enclosingDeclaration, flags, nodeBuilder, idToSymbol)}, 1, ast.IsInJSFile(enclosingDeclaration)), nil /*type*/, nil /*fullSignature*/, f.createBody(body, quotePreference, signatureOnly), ), ) @@ -323,7 +323,7 @@ func (f *missingMemberFixer) createSignatureDeclarationFromSignatures(signatures } maxNonRestArgs := len(maxArgsSignature.Parameters()) - core.IfElse(maxArgsSignature.HasRestParameter(), 1, 0) - parameterNames := make([]string, 0, len(maxArgsSignature.Parameters())) + parameterNames := make([]ast.SymbolName, 0, len(maxArgsSignature.Parameters())) for _, symbol := range maxArgsSignature.Parameters() { parameterNames = append(parameterNames, symbol.Name()) } @@ -331,8 +331,8 @@ func (f *missingMemberFixer) createSignatureDeclarationFromSignatures(signatures if hasRestParameter { restParameterName := "rest" - if maxNonRestArgs < len(parameterNames) && parameterNames[maxNonRestArgs] != "" { - restParameterName = parameterNames[maxNonRestArgs] + if maxNonRestArgs < len(parameterNames) && parameterNames[maxNonRestArgs] != ast.EmptySymbolName { + restParameterName = parameterNames[maxNonRestArgs].Value() } var questionToken *ast.QuestionToken @@ -448,23 +448,23 @@ func (f *missingMemberFixer) createStubbedMethodBody(quotePreference lsutil.Quot }), true /*multiLine*/) } -func createDummyParameters(factory *ast.NodeFactory, argCount int, names []string, types []*ast.TypeNode, minArgumentCount int, inJS bool) *ast.ParameterList { +func createDummyParameters(factory *ast.NodeFactory, argCount int, names []ast.SymbolName, types []*ast.TypeNode, minArgumentCount int, inJS bool) *ast.ParameterList { parameters := make([]*ast.Node, 0, argCount) - parameterNameCounts := make(map[string]int) + parameterNameCounts := make(map[ast.SymbolName]int) for i := range argCount { - parameterName := "" - if i < len(names) && names[i] != "" { + parameterName := ast.EmptySymbolName + if i < len(names) && names[i] != ast.EmptySymbolName { parameterName = names[i] } else { - parameterName = "arg" + strconv.Itoa(i) + parameterName = ast.MakeSymbolName("arg" + strconv.Itoa(i)) } count := parameterNameCounts[parameterName] parameterNameCounts[parameterName] = count + 1 if count > 0 { - parameterName += strconv.Itoa(count) + parameterName = ast.MakeSymbolName(parameterName.Value() + strconv.Itoa(count)) } var questionToken *ast.QuestionToken @@ -481,7 +481,7 @@ func createDummyParameters(factory *ast.NodeFactory, argCount int, names []strin typeNode = factory.NewKeywordTypeNode(ast.KindUnknownKeyword) } parameters = append(parameters, - factory.NewParameterDeclaration(nil /*modifiers*/, nil /*dotDotDotToken*/, factory.NewIdentifier(parameterName), questionToken, typeNode, nil /*initializer*/)) + factory.NewParameterDeclaration(nil /*modifiers*/, nil /*dotDotDotToken*/, factory.NewIdentifier(parameterName.Value()), questionToken, typeNode, nil /*initializer*/)) } return factory.NewNodeList(parameters) } @@ -490,14 +490,14 @@ func createDeclarationName(factory *ast.NodeFactory, typeChecker *checker.Checke if symbol != nil && symbol.CheckFlags()&ast.CheckFlagsMapped != 0 { nameType := typeChecker.GetNameTypeOfSymbol(symbol) if nameType != nil && checker.IsTypeUsableAsPropertyName(nameType) { - return factory.NewIdentifier(checker.GetPropertyNameFromType(nameType)) + return factory.NewIdentifier(checker.GetPropertyNameFromType(nameType).Value()) } } if declaration != nil && declaration.Name() != nil { return declaration.Name().Clone(factory) } if symbol != nil { - return factory.NewIdentifier(symbol.Name()) + return factory.NewIdentifier(symbol.Name().Value()) } return nil } diff --git a/tsc/internal/ls/completions.go b/tsc/internal/ls/completions.go index 62564fbbd2f7e..2dd07e04f3755 100644 --- a/tsc/internal/ls/completions.go +++ b/tsc/internal/ls/completions.go @@ -1050,7 +1050,7 @@ func (l *LanguageService) getCompletionData( members := getPropertiesForCompletion(containerExpectedType, typeChecker) existingMembers := getPropertiesForCompletion(containerActualType, typeChecker) - existingMemberNames := collections.Set[string]{} + existingMemberNames := collections.Set[ast.SymbolName]{} for _, member := range existingMembers { existingMemberNames.Add(member.Name()) } @@ -1326,15 +1326,15 @@ func (l *LanguageService) getCompletionData( isNewIdentifierLocation = false exports := typeChecker.GetExportsAndPropertiesOfModule(moduleSpecifierSymbol) - existing := collections.Set[string]{} + existing := collections.Set[ast.SymbolName]{} for _, element := range namedImportsOrExports.Elements() { if isCurrentlyEditingNode(element, file, position) { continue } - existing.Add(element.PropertyNameOrName().Text()) + existing.Add(element.PropertyNameOrName().TextSymbolName()) } uniques := core.Filter(exports, func(symbol *ast.Symbol) bool { - return ast.SymbolName(symbol) != ast.InternalSymbolNameDefault && !existing.Has(ast.SymbolName(symbol)) + return symbol.Name() != ast.InternalSymbolNameDefault && !existing.Has(symbol.Name()) }) symbols = append(symbols, uniques...) @@ -1366,14 +1366,14 @@ func (l *LanguageService) getCompletionData( if importAttributes.AsImportAttributes().Attributes != nil { elements = importAttributes.AsImportAttributes().Attributes.Nodes } - attributeNames := core.Map(elements, func(el *ast.Node) string { - return el.AsImportAttribute().Name().Text() + attributeNames := core.Map(elements, func(el *ast.Node) ast.SymbolName { + return el.AsImportAttribute().Name().TextSymbolName() }) existing := collections.NewSetFromItems(attributeNames...) uniques := core.Filter( typeChecker.GetApparentProperties(typeChecker.GetTypeAtLocation(importAttributes)), func(symbol *ast.Symbol) bool { - return !existing.Has(ast.SymbolName(symbol)) + return !existing.Has(symbol.Name()) }, ) symbols = append(symbols, uniques...) @@ -1549,7 +1549,7 @@ func (l *LanguageService) getCompletionData( // Set sort texts. for _, symbol := range filteredSymbols { symbolId := ast.GetSymbolId(symbol) - if spreadMemberNames.Has(ast.SymbolName(symbol)) { + if spreadMemberNames.Has(ast.MakeSymbolName(ast.SymbolNameText(symbol))) { symbolToSortTextMap[symbolId] = SortTextMemberDeclaredBySpreadAssignment } if symbol.Flags()&ast.SymbolFlagsOptional != 0 { @@ -3171,7 +3171,7 @@ func getCompletionEntryDisplayNameForSymbol( if originIncludesSymbolName(origin) { name = origin.symbolName() } else { - name = ast.SymbolName(symbol) + name = ast.SymbolNameText(symbol) } if name == "" || // If the symbol is external module, don't show it in the completion list @@ -4252,15 +4252,15 @@ func isSnippetScope(scopeNode *ast.Node) bool { func isProbablyGlobalType(t *checker.Type, file *ast.SourceFile, typeChecker *checker.Checker) bool { // The type of `self` and `window` is the same in lib.dom.d.ts, but `window` does not exist in // lib.webworker.d.ts, so checking against `self` is also a check against `window` when it exists. - selfSymbol := typeChecker.GetGlobalSymbol("self", ast.SymbolFlagsValue, nil /*diagnostic*/) + selfSymbol := typeChecker.GetGlobalSymbol(ast.SymbolNameSelf, ast.SymbolFlagsValue, nil /*diagnostic*/) if selfSymbol != nil && typeChecker.GetTypeOfSymbolAtLocation(selfSymbol, file.AsNode()) == t { return true } - globalSymbol := typeChecker.GetGlobalSymbol("global", ast.SymbolFlagsValue, nil /*diagnostic*/) + globalSymbol := typeChecker.GetGlobalSymbol(ast.SymbolNameGlobal, ast.SymbolFlagsValue, nil /*diagnostic*/) if globalSymbol != nil && typeChecker.GetTypeOfSymbolAtLocation(globalSymbol, file.AsNode()) == t { return true } - globalThisSymbol := typeChecker.GetGlobalSymbol("globalThis", ast.SymbolFlagsValue, nil /*diagnostic*/) + globalThisSymbol := typeChecker.GetGlobalSymbol(ast.SymbolNameGlobalThis, ast.SymbolFlagsValue, nil /*diagnostic*/) if globalThisSymbol != nil && typeChecker.GetTypeOfSymbolAtLocation(globalThisSymbol, file.AsNode()) == t { return true } @@ -4316,7 +4316,7 @@ func getConstraintOfTypeArgumentProperty(node *ast.Node, typeChecker *checker.Ch // (e.g. JSDoc types that never get re-attached) so we'll use // the name as declared by the property as a best-effort. if name, ok := ast.TryGetTextOfPropertyName(reparsed.Name()); ok { - return typeChecker.GetTypeOfPropertyOfContextualType(t, name) + return typeChecker.GetTypeOfPropertyOfContextualType(t, ast.MakeSymbolName(name)) } return nil @@ -4487,13 +4487,13 @@ func filterObjectMembersList( file *ast.SourceFile, position int, typeChecker *checker.Checker, -) (filteredMembers []*ast.Symbol, spreadMemberNames collections.Set[string]) { +) (filteredMembers []*ast.Symbol, spreadMemberNames collections.Set[ast.SymbolName]) { if len(existingMembers) == 0 { - return contextualMemberSymbols, collections.Set[string]{} + return contextualMemberSymbols, collections.Set[ast.SymbolName]{} } - membersDeclaredBySpreadAssignment := collections.Set[string]{} - existingMemberNames := collections.Set[string]{} + membersDeclaredBySpreadAssignment := collections.Set[ast.SymbolName]{} + existingMemberNames := collections.Set[ast.SymbolName]{} for _, member := range existingMembers { // Ignore omitted expressions for missing members. if member.Kind != ast.KindPropertyAssignment && @@ -4531,7 +4531,7 @@ func filterObjectMembersList( } if existingName != "" { - existingMemberNames.Add(existingName) + existingMemberNames.Add(ast.MakeSymbolName(existingName)) } } @@ -4547,7 +4547,7 @@ func isCurrentlyEditingNode(node *ast.Node, file *ast.SourceFile, position int) return start <= position && position <= node.End() } -func setMemberDeclaredBySpreadAssignment(declaration *ast.Node, members *collections.Set[string], typeChecker *checker.Checker) { +func setMemberDeclaredBySpreadAssignment(declaration *ast.Node, members *collections.Set[ast.SymbolName], typeChecker *checker.Checker) { expression := declaration.Expression() symbol := typeChecker.GetSymbolAtLocation(expression) var t *checker.Type @@ -4701,7 +4701,7 @@ func filterClassMembersList( file *ast.SourceFile, position int, ) []*ast.Symbol { - existingMemberNames := collections.Set[string]{} + existingMemberNames := collections.Set[ast.SymbolName]{} for _, member := range existingMembers { // Ignore omitted expressions for missing members. if member.Kind != ast.KindPropertyDeclaration && @@ -4727,13 +4727,13 @@ func filterClassMembersList( } existingName := ast.GetPropertyNameForPropertyNameNode(member.Name()) - if existingName != "" { + if existingName != ast.EmptySymbolName { existingMemberNames.Add(existingName) } } return core.Filter(baseSymbols, func(propertySymbol *ast.Symbol) bool { - return !existingMemberNames.Has(ast.SymbolName(propertySymbol)) && + return !existingMemberNames.Has(ast.MakeSymbolName(ast.SymbolNameText(propertySymbol))) && len(propertySymbol.Declarations()) > 0 && checker.GetDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsPrivate == 0 && !(propertySymbol.ValueDeclaration() != nil && ast.IsPrivateIdentifierClassElementDeclaration(propertySymbol.ValueDeclaration())) @@ -4810,9 +4810,9 @@ func filterJsxAttributes( file *ast.SourceFile, position int, typeChecker *checker.Checker, -) (filteredMembers []*ast.Symbol, spreadMemberNames *collections.Set[string]) { - existingNames := collections.Set[string]{} - membersDeclaredBySpreadAssignment := collections.Set[string]{} +) (filteredMembers []*ast.Symbol, spreadMemberNames *collections.Set[ast.SymbolName]) { + existingNames := collections.Set[ast.SymbolName]{} + membersDeclaredBySpreadAssignment := collections.Set[ast.SymbolName]{} for _, attr := range attributes { // If this is the item we are editing right now, do not filter it out. if isCurrentlyEditingNode(attr, file, position) { @@ -4820,7 +4820,7 @@ func filterJsxAttributes( } if attr.Kind == ast.KindJsxAttribute { - existingNames.Add(attr.Name().Text()) + existingNames.Add(attr.Name().TextSymbolName()) } else if ast.IsJsxSpreadAttribute(attr) { setMemberDeclaredBySpreadAssignment(attr, &membersDeclaredBySpreadAssignment, typeChecker) } diff --git a/tsc/internal/ls/definition.go b/tsc/internal/ls/definition.go index eb1761a6d98d2..8c8ee995eccf6 100644 --- a/tsc/internal/ls/definition.go +++ b/tsc/internal/ls/definition.go @@ -340,7 +340,7 @@ func getDeclarationsFromLocation(c *checker.Checker, node *ast.Node) []*ast.Node } var result []*ast.Node for _, unionType := range types { - if prop := c.GetPropertyOfType(unionType, name); prop != nil { + if prop := c.GetPropertyOfType(unionType, ast.MakeSymbolName(name)); prop != nil { result = append(result, prop.Declarations()...) } } @@ -485,9 +485,9 @@ func getSymbolForOverriddenMember(typeChecker *checker.Checker, node *ast.Node) } name := ast.GetTextOfPropertyName(classElement.Name()) if ast.HasStaticModifier(classElement) { - return typeChecker.GetPropertyOfType(typeChecker.GetTypeOfSymbol(base), name) + return typeChecker.GetPropertyOfType(typeChecker.GetTypeOfSymbol(base), ast.MakeSymbolName(name)) } - return typeChecker.GetPropertyOfType(typeChecker.GetDeclaredTypeOfSymbol(base), name) + return typeChecker.GetPropertyOfType(typeChecker.GetDeclaredTypeOfSymbol(base), ast.MakeSymbolName(name)) } func getTypeOfSymbolAtLocation(c *checker.Checker, symbol *ast.Symbol, node *ast.Node) *checker.Type { diff --git a/tsc/internal/ls/findallreferences.go b/tsc/internal/ls/findallreferences.go index 6e40e4aa1211c..006ed40e76aa5 100644 --- a/tsc/internal/ls/findallreferences.go +++ b/tsc/internal/ls/findallreferences.go @@ -395,7 +395,7 @@ func skipPastExportOrImportSpecifierOrUnion(symbol *ast.Symbol, node *ast.Node, return nil } // Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here. - panic(fmt.Sprintf("Unexpected symbol at %s: %s", node.Kind.String(), symbol.Name())) + panic(fmt.Sprintf("Unexpected symbol at %s: %s", node.Kind.String(), symbol.Name().Value())) } if decl.Parent.Kind == ast.KindTypeLiteral && decl.Parent.Parent.Kind == ast.KindUnionType { return checker.GetPropertyOfType(checker.GetTypeFromTypeNode(decl.Parent.Parent), symbol.Name()) @@ -1393,7 +1393,7 @@ func (l *LanguageService) getReferencesForStringLiteral( func isStringLiteralPropertyReference(node *ast.StringLiteralLike, checker *checker.Checker) bool { if ast.IsPropertySignatureDeclaration(node.Parent) { - return checker.GetPropertyOfType(checker.GetTypeAtLocation(node.Parent.Parent), node.Text()) != nil + return checker.GetPropertyOfType(checker.GetTypeAtLocation(node.Parent.Parent), node.TextSymbolName()) != nil } return false } @@ -1964,8 +1964,8 @@ func (state *refState) createSearch(location *ast.Node, symbol *ast.Symbol, comi s = symbol } } - symbolName := ast.SymbolName(s) - if moduleName, ok := ast.TryGetAmbientModuleNameFromSymbolName(symbolName); ok { + symbolName := ast.SymbolNameText(s) + if moduleName, ok := ast.TryGetAmbientModuleNameFromSymbolName(ast.MakeSymbolName(symbolName)); ok { text = moduleName } else { text = symbolName diff --git a/tsc/internal/ls/importTracker.go b/tsc/internal/ls/importTracker.go index e4aa7f94dd940..5e6561617554c 100644 --- a/tsc/internal/ls/importTracker.go +++ b/tsc/internal/ls/importTracker.go @@ -357,7 +357,7 @@ func getSearchesFromDirectImports( isNameMatch := func(name string) bool { // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports - return name == exportSymbol.Name() || exportKind != ExportKindNamed && name == ast.InternalSymbolNameDefault + return ast.MakeSymbolName(name) == exportSymbol.Name() || exportKind != ExportKindNamed && ast.MakeSymbolName(name) == ast.InternalSymbolNameDefault } // `import x = require("./x")` or `import * as x from "./x"`. @@ -385,7 +385,7 @@ func getSearchesFromDirectImports( singleReferences = append(singleReferences, propertyName) // If renaming `{ foo as bar }`, don't touch `bar`, just `foo`. // But do rename `foo` in ` { default as foo }` if that's the original export name. - if !isForRename || name.Text() == exportSymbol.Name() { + if !isForRename || name.TextSymbolName() == exportSymbol.Name() { // Search locally for `bar`. addSearch(name, checker.GetSymbolAtLocation(name)) } @@ -415,7 +415,7 @@ func getSearchesFromDirectImports( if ast.IsImportTypeNode(decl) { if qualifier := decl.AsImportTypeNode().Qualifier; qualifier != nil { firstIdentifier := ast.GetFirstIdentifier(qualifier) - if firstIdentifier.Text() == ast.SymbolName(exportSymbol) { + if firstIdentifier.TextSymbolName() == exportSymbol.Name() { singleReferences = append(singleReferences, firstIdentifier) } } else if exportKind == ExportKindExportEquals { @@ -448,7 +448,7 @@ func getSearchesFromDirectImports( // `export =` might be imported by a default import if `--allowSyntheticDefaultImports` is on, so this handles both ExportKind.Default and ExportKind.ExportEquals. // If a default import has the same name as the default export, allow to rename it. // Given `import f` and `export default function f`, we will rename both, but for `import g` we will rename just that. - if name := importClause.Name(); name != nil && (exportKind == ExportKindDefault || exportKind == ExportKindExportEquals) && (!isForRename || name.Text() == symbolNameNoDefault(exportSymbol)) { + if name := importClause.Name(); name != nil && (exportKind == ExportKindDefault || exportKind == ExportKindExportEquals) && (!isForRename || name.TextSymbolName() == symbolNameNoDefault(exportSymbol)) { defaultImportAlias := checker.GetSymbolAtLocation(name) addSearch(name, defaultImportAlias) } @@ -583,7 +583,7 @@ func getImportOrExportSymbol(node *ast.Node, symbol *ast.Symbol, checker *checke return nil } // Similarly, skip past the symbol for 'export =' - if importedSymbol.Name() == "export=" { + if importedSymbol.Name() == ast.InternalSymbolNameExportEquals { importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker) if importedSymbol == nil { return nil @@ -593,7 +593,7 @@ func getImportOrExportSymbol(node *ast.Node, symbol *ast.Symbol, checker *checke // If `importedName` is undefined, do continue searching as the export is anonymous. // (All imports returned from this function will be ignored anyway if we are in rename and this is a not a named export.) importedName := symbolNameNoDefault(importedSymbol) - if importedName == "" || importedName == ast.InternalSymbolNameDefault || importedName == symbol.Name() { + if importedName == ast.EmptySymbolName || importedName == ast.InternalSymbolNameDefault || importedName == symbol.Name() { return &ImportExportSymbol{ kind: ImpExpKindImport, symbol: importedSymbol, @@ -699,17 +699,17 @@ func getExportEqualsLocalSymbol(importedSymbol *ast.Symbol, checker *checker.Che return nil } -func symbolNameNoDefault(symbol *ast.Symbol) string { +func symbolNameNoDefault(symbol *ast.Symbol) ast.SymbolName { if symbol.Name() != ast.InternalSymbolNameDefault { return symbol.Name() } for _, decl := range symbol.Declarations() { name := ast.GetNameOfDeclaration(decl) if name != nil && ast.IsIdentifier(name) { - return name.Text() + return name.TextSymbolName() } } - return "" + return ast.EmptySymbolName } // findModuleReferences finds all references to a module symbol across the given source files. diff --git a/tsc/internal/ls/inlay_hints.go b/tsc/internal/ls/inlay_hints.go index b74c97e187a7b..f8c15dd3b7992 100644 --- a/tsc/internal/ls/inlay_hints.go +++ b/tsc/internal/ls/inlay_hints.go @@ -891,7 +891,7 @@ func (s *inlayHintState) getParameterIdentifierInfoAtPosition(signature *checker if pos == paramCount { return ¶meterInfo{ parameter: restId, - name: restParameter.Name(), + name: restParameter.Name().Value(), isRestParameter: true, } } diff --git a/tsc/internal/ls/jsdoc.go b/tsc/internal/ls/jsdoc.go index c3ac3eb1cbef6..1a73ae8b989c9 100644 --- a/tsc/internal/ls/jsdoc.go +++ b/tsc/internal/ls/jsdoc.go @@ -190,7 +190,7 @@ func getJSDocOrTag(c *checker.Checker, node *ast.Node, seenSymbols *collections. case ast.IsBindingElement(node) && ast.IsObjectBindingPattern(node.Parent): if name := node.PropertyNameOrName(); ast.IsIdentifier(name) { if objectType := c.GetTypeAtLocation(node.Parent); objectType != nil { - if prop := c.GetPropertyOfType(objectType, name.Text()); prop != nil { + if prop := c.GetPropertyOfType(objectType, name.TextSymbolName()); prop != nil { for _, d := range prop.Declarations() { if jsdoc := getJSDoc(d); jsdoc != nil { return jsdoc diff --git a/tsc/internal/ls/lsutil/utilities.go b/tsc/internal/ls/lsutil/utilities.go index bd85ec586f839..aca7b2a78fc43 100644 --- a/tsc/internal/ls/lsutil/utilities.go +++ b/tsc/internal/ls/lsutil/utilities.go @@ -115,9 +115,9 @@ func GetQuotePreference(sourceFile *ast.SourceFile, preferences UserPreferences) func ModuleSymbolToValidIdentifier(moduleSymbol *ast.Symbol, forceCapitalize bool) string { moduleName := moduleSymbol.Name() if ambientModuleName, ok := ast.TryGetAmbientModuleNameFromSymbolName(moduleName); ok { - moduleName = ambientModuleName + moduleName = ast.MakeSymbolName(ambientModuleName) } - return ModuleSpecifierToValidIdentifier(moduleName, forceCapitalize) + return ModuleSpecifierToValidIdentifier(moduleName.Value(), forceCapitalize) } func ModuleSpecifierToValidIdentifier(moduleSpecifier string, forceCapitalize bool) string { diff --git a/tsc/internal/ls/signaturehelp.go b/tsc/internal/ls/signaturehelp.go index 423c84dc0759b..c729df23cb500 100644 --- a/tsc/internal/ls/signaturehelp.go +++ b/tsc/internal/ls/signaturehelp.go @@ -319,7 +319,7 @@ func (l *LanguageService) createSignatureHelpItems(ctx context.Context, candidat // "\xFEtype". There is no meaningful name to show, so render the signature with // no prefix (as we already do when there is no call target symbol) rather than // leaking the internal name. - if callTargetSymbol != nil && !strings.HasPrefix(callTargetSymbol.Name(), ast.InternalSymbolNamePrefix) { + if callTargetSymbol != nil && !strings.HasPrefix(callTargetSymbol.Name().Value(), ast.InternalSymbolNamePrefix) { if useFullPrefix { callTargetDisplayParts.WriteString(c.SymbolToStringEx(callTargetSymbol, sourceFile.AsNode(), ast.SymbolFlagsNone, checker.SymbolFormatFlagsUseAliasDefinedOutsideCurrentScope)) } else { diff --git a/tsc/internal/ls/sourcedefinition.go b/tsc/internal/ls/sourcedefinition.go index 58eeda3b7b22e..a3dd4e69ed3b9 100644 --- a/tsc/internal/ls/sourcedefinition.go +++ b/tsc/internal/ls/sourcedefinition.go @@ -229,7 +229,7 @@ func getSourceDefCheckerInfo( isPropertyName := node.Parent != nil && ast.IsAccessExpression(node.Parent) && node.Parent.Name() == node if len(declarations) == 0 && isPropertyName { if left := node.Parent.Expression(); left != nil { - if prop := c.GetPropertyOfType(c.GetTypeAtLocation(left), node.Text()); prop != nil { + if prop := c.GetPropertyOfType(c.GetTypeAtLocation(left), node.TextSymbolName()); prop != nil { declarations = prop.Declarations() } } diff --git a/tsc/internal/ls/string_completions.go b/tsc/internal/ls/string_completions.go index c453bb239d3a5..ee5da8c36c945 100644 --- a/tsc/internal/ls/string_completions.go +++ b/tsc/internal/ls/string_completions.go @@ -396,8 +396,8 @@ func (l *LanguageService) getStringLiteralCompletionEntries( return nil } exports := typeChecker.GetExportsAndPropertiesOfModule(moduleSpecifierSymbol) - existing := collections.NewSetFromItems(core.Map(namedImportsOrExports.Elements(), func(n *ast.Node) string { - return n.PropertyNameOrName().Text() + existing := collections.NewSetFromItems(core.Map(namedImportsOrExports.Elements(), func(n *ast.Node) ast.SymbolName { + return n.PropertyNameOrName().TextSymbolName() })...) uniques := core.Filter(exports, func(e *ast.Symbol) bool { return e.Name() != ast.InternalSymbolNameDefault && !existing.Has(e.Name()) @@ -518,11 +518,12 @@ func fromUnionableLiteralType( switch { case result.fromProperties != nil: result := result.fromProperties + alreadyUsedNames := collections.NewSetFromItems(core.Map(alreadyUsedTypes, ast.MakeSymbolName)...) return &stringLiteralCompletions{ fromProperties: &completionsFromProperties{ symbols: core.Filter( result.symbols, - func(s *ast.Symbol) bool { return !slices.Contains(alreadyUsedTypes, s.Name()) }, + func(s *ast.Symbol) bool { return !alreadyUsedNames.Has(s.Name()) }, ), hasIndexSignature: result.hasIndexSignature, }, @@ -929,7 +930,7 @@ func getAmbientModuleName(symbol *ast.Symbol) string { if declaration != nil && ast.IsModuleWithStringLiteralName(declaration) { return declaration.Name().Text() } - return stringutil.StripQuotes(symbol.Name()) + return stringutil.StripQuotes(symbol.Name().Value()) } func (l *LanguageService) getCompletionEntriesFromTypings( @@ -2028,7 +2029,7 @@ func getStringLiteralCompletionsFromSignature( } t := typeChecker.GetTypeParameterAtPosition(candidate, argumentInfo.argumentIndex) if ast.IsJsxOpeningLikeElement(call) { - propType := typeChecker.GetTypeOfPropertyOfType(t, editingArgument.AsJsxAttribute().Name().Text()) + propType := typeChecker.GetTypeOfPropertyOfType(t, editingArgument.AsJsxAttribute().Name().TextSymbolName()) if propType != nil { t = propType } @@ -2089,7 +2090,7 @@ func (l *LanguageService) stringLiteralCompletionDetails( case completion.fromProperties != nil: properties := completion.fromProperties for _, symbol := range properties.symbols { - if symbol.Name() == name { + if symbol.Name() == ast.MakeSymbolName(name) { return l.createCompletionDetailsForSymbol(item, symbol, checker, location, position, docFormat) } } diff --git a/tsc/internal/ls/utilities.go b/tsc/internal/ls/utilities.go index a05994440d530..ea3ffa679c753 100644 --- a/tsc/internal/ls/utilities.go +++ b/tsc/internal/ls/utilities.go @@ -960,7 +960,7 @@ func getParentSymbolsOfPropertyAccess(location *ast.Node, symbol *ast.Symbol, ch // @param cb a cache of symbol from previous iterations of calling this function to prevent infinite revisiting of the same symbol. // // The value of previousIterationSymbol is undefined when the function is first called. -func getPropertySymbolsFromBaseTypes(symbol *ast.Symbol, propertyName string, checker *checker.Checker, cb func(base *ast.Symbol) *ast.Symbol) *ast.Symbol { +func getPropertySymbolsFromBaseTypes(symbol *ast.Symbol, propertyName ast.SymbolName, checker *checker.Checker, cb func(base *ast.Symbol) *ast.Symbol) *ast.Symbol { var seen collections.Set[*ast.Symbol] var recur func(*ast.Symbol) *ast.Symbol recur = func(symbol *ast.Symbol) *ast.Symbol { @@ -995,7 +995,7 @@ func getPropertySymbolsFromBaseTypes(symbol *ast.Symbol, propertyName string, ch func getPropertySymbolFromBindingElement(checker *checker.Checker, bindingElement *ast.Node) *ast.Symbol { if typeOfPattern := checker.GetTypeAtLocation(bindingElement.Parent); typeOfPattern != nil { - return checker.GetPropertyOfType(typeOfPattern, bindingElement.Name().Text()) + return checker.GetPropertyOfType(typeOfPattern, bindingElement.Name().TextSymbolName()) } return nil } diff --git a/tsc/internal/parser/jsdoc.go b/tsc/internal/parser/jsdoc.go index 6d239d2f228fc..468873a115c78 100644 --- a/tsc/internal/parser/jsdoc.go +++ b/tsc/internal/parser/jsdoc.go @@ -1349,7 +1349,7 @@ func (p *Parser) parseJSDocIdentifierName(diagnosticMessage *diagnostics.Message } pos := p.scanner.TokenStart() end := p.scanner.TokenEnd() - text := p.scanner.TokenValue() + identifier := p.newScannedIdentifier(p.scanner.TokenValue()) p.nextTokenJSDoc() - return p.finishNodeWithEnd(p.newIdentifier(text), pos, end) + return p.finishNodeWithEnd(identifier, pos, end) } diff --git a/tsc/internal/parser/parser.go b/tsc/internal/parser/parser.go index c670d64ad21c2..0e63ea8b24197 100644 --- a/tsc/internal/parser/parser.go +++ b/tsc/internal/parser/parser.go @@ -84,6 +84,7 @@ type Parser struct { hasParseError bool identifierCount int + identifierNames *ast.SymbolNameCache notParenthesizedArrow collections.Set[int] nodeSliceArena core.Arena[*ast.Node] stringSliceArena core.Arena[string] @@ -101,7 +102,7 @@ type Parser struct { } func newParser() *Parser { - res := &Parser{} + res := &Parser{identifierNames: &ast.SymbolNameCache{}} res.initializeClosures() return res } @@ -127,7 +128,7 @@ func getParser() *Parser { } func putParser(p *Parser) { - *p = Parser{scanner: p.scanner, setParentFromContext: p.setParentFromContext} + *p = Parser{scanner: p.scanner, setParentFromContext: p.setParentFromContext, identifierNames: p.identifierNames} parserPool.Put(p) } @@ -3039,8 +3040,22 @@ func (p *Parser) parseRightSideOfDot(allowIdentifierNames bool, allowPrivateIden } func (p *Parser) newIdentifier(text string) *ast.Node { + return p.newIdentifierFromSymbolName(text, p.identifierNames.Make(text)) +} + +// newScannedIdentifier creates an identifier for the current token's value, +// reusing the hash the scanner computed for it if available. Call it before +// advancing past the token. +func (p *Parser) newScannedIdentifier(text string) *ast.Node { + if hash, ok := p.scanner.IdentifierHash(text); ok { + return p.newIdentifierFromSymbolName(text, p.identifierNames.MakeHashed(text, hash)) + } + return p.newIdentifier(text) +} + +func (p *Parser) newIdentifierFromSymbolName(text string, name ast.SymbolName) *ast.Node { p.identifierCount++ - id := p.factory.NewIdentifier(text) + id := p.factory.NewIdentifierFromSymbolName(name) if text == "await" { p.statementHasAwaitIdentifier = true } @@ -5936,9 +5951,9 @@ func (p *Parser) createIdentifierWithDiagnostic(isIdentifier bool, diagnosticMes } else { pos = p.nodePos() } - text := p.scanner.TokenValue() + identifier := p.newScannedIdentifier(p.scanner.TokenValue()) p.nextTokenWithoutCheck() - return p.finishNode(p.newIdentifier(text), pos) + return p.finishNode(identifier, pos) } if p.token == ast.KindPrivateIdentifier { if privateIdentifierDiagnosticMessage != nil { diff --git a/tsc/internal/parser/reparser.go b/tsc/internal/parser/reparser.go index bd0e5e4d04588..e598380f066d0 100644 --- a/tsc/internal/parser/reparser.go +++ b/tsc/internal/parser/reparser.go @@ -43,7 +43,7 @@ func (p *Parser) checkNonIdentifierName(name *ast.Node) *ast.Node { if name == nil { return nil } - if ast.IsIdentifier(name) && !scanner.IsValidIdentifier(name.AsIdentifier().Text) { + if ast.IsIdentifier(name) && !scanner.IsValidIdentifier(name.Text()) { errLoc := name.Loc if errLoc.Len() == 0 { // missing name, emit error on the character before the missing name node errLoc = core.NewTextRange(name.Loc.Pos()-1, name.Loc.Pos()) @@ -197,10 +197,10 @@ func (p *Parser) reparseJSDocSignature(jsSignature *ast.Node, fun *ast.Node, jsD } } name := jsparam.Name() - if ast.IsIdentifier(name) && !scanner.IsValidIdentifier(name.AsIdentifier().Text) { + if ast.IsIdentifier(name) && !scanner.IsValidIdentifier(name.Text()) { // drop invalid chars for _, if empty, write _0, etc., so we have a valid param name to emit later result := strings.Builder{} - for i, ch := range name.AsIdentifier().Text { + for i, ch := range name.Text() { if i == 0 { if !scanner.IsIdentifierStart(ch) { result.WriteRune('_') @@ -258,8 +258,8 @@ func (p *Parser) reparseJSDocTypeLiteral(t *ast.TypeNode) *ast.Node { if name.Kind == ast.KindQualifiedName { name = name.AsQualifiedName().Right } - if ast.IsIdentifier(name) && !scanner.IsValidIdentifier(name.AsIdentifier().Text) { - name = p.addTransformedReparse(p.factory.NewStringLiteral(name.AsIdentifier().Text, ast.TokenFlagsNone), name) + if ast.IsIdentifier(name) && !scanner.IsValidIdentifier(name.Text()) { + name = p.addTransformedReparse(p.factory.NewStringLiteral(name.Text(), ast.TokenFlagsNone), name) } else { name = p.addDeepCloneReparse(name) } diff --git a/tsc/internal/printer/emitresolver.go b/tsc/internal/printer/emitresolver.go index d86a0ca378ecc..e79887b842176 100644 --- a/tsc/internal/printer/emitresolver.go +++ b/tsc/internal/printer/emitresolver.go @@ -103,7 +103,7 @@ type EmitResolver interface { IsLiteralConstDeclaration(node *ast.Node) bool RequiresAddingImplicitUndefined(node *ast.Node, symbol *ast.Symbol, enclosingDeclaration *ast.Node) bool IsDeclarationVisible(node *ast.Node) bool - IsNameResolvable(location *ast.Node, name string) bool + IsNameResolvable(location *ast.Node, name ast.SymbolName) bool IsImportRequiredByAugmentation(decl *ast.ImportDeclaration) bool IsDefinitelyReferenceToGlobalSymbolObject(node *ast.Node) bool IsImplementationOfOverload(node *ast.SignatureDeclaration) bool diff --git a/tsc/internal/printer/namegenerator.go b/tsc/internal/printer/namegenerator.go index 81078f087a3bd..6d6fca689a281 100644 --- a/tsc/internal/printer/namegenerator.go +++ b/tsc/internal/printer/namegenerator.go @@ -366,7 +366,7 @@ func isUniqueLocalName(name string, container *ast.Node) bool { locals := node.Locals() if locals != nil { // We conservatively include alias symbols to cover cases where they're emitted as locals - if local, ok := locals[name]; ok && local.Flags()&(ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias) != 0 { + if local, ok := locals[ast.MakeSymbolName(name)]; ok && local.Flags()&(ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias) != 0 { return false } } diff --git a/tsc/internal/printer/printer.go b/tsc/internal/printer/printer.go index a27452d51472d..f4d3b39914b99 100644 --- a/tsc/internal/printer/printer.go +++ b/tsc/internal/printer/printer.go @@ -1170,7 +1170,7 @@ func (p *Printer) emitIdentifierReference(node *ast.Identifier) { } if p.uniqueHelperNames != nil { // Substitute `__helper` with `__helper_1` if there is a conflict in an ES module. - helperName := p.getUniqueHelperName(node.Text) + helperName := p.getUniqueHelperName(node.Text.Value()) p.emitContext.AssignCommentAndSourceMapRanges(helperName, node.AsNode()) node = helperName.AsIdentifier() } @@ -1185,7 +1185,7 @@ func (p *Printer) emitBindingIdentifier(node *ast.Identifier) { if p.uniqueHelperNames != nil && p.emitContext.EmitFlags(node.AsNode())&EFHelperName != 0 { // Substitute `__helper` with `__helper_1` if there is a conflict in an ES module. - helperName := p.getUniqueHelperName(node.Text) + helperName := p.getUniqueHelperName(node.Text.Value()) p.emitContext.AssignCommentAndSourceMapRanges(helperName, node.AsNode()) node = helperName.AsIdentifier() } diff --git a/tsc/internal/pseudochecker/lookup.go b/tsc/internal/pseudochecker/lookup.go index 3fc7243df41f5..899ce442cb421 100644 --- a/tsc/internal/pseudochecker/lookup.go +++ b/tsc/internal/pseudochecker/lookup.go @@ -269,7 +269,7 @@ func (ch *PseudoChecker) typeFromExpression(node *ast.Node) *PseudoType { case ast.KindIdentifier: // !!! TODO: in strada, this uses symbol information to ensure `node` refers to the global `undefined` symbol instead // we should probably import `resolveName` and use it here to check for the same; but we have to setup some barebones pseudoglobals for that to work! - if node.AsIdentifier().Text == "undefined" { + if node.AsIdentifier().Text == ast.SymbolNameUndefined { return PseudoTypeUndefined } case ast.KindNullKeyword: diff --git a/tsc/internal/scanner/scanner.go b/tsc/internal/scanner/scanner.go index 785fe50a4e7df..1ae302782771c 100644 --- a/tsc/internal/scanner/scanner.go +++ b/tsc/internal/scanner/scanner.go @@ -9,6 +9,7 @@ import ( "unicode" "unicode/utf16" "unicode/utf8" + "unsafe" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -210,12 +211,18 @@ type ScannerState struct { } type Scanner struct { - text string - end int - languageVariant core.LanguageVariant - scriptTarget core.ScriptTarget - onError ErrorCallback - skipTrivia bool + text string + // Hash of the most recent identifier scanned by the ASCII fast path, keyed + // by the address and length of its token value. Stored as integers so + // updating them needs no write barriers. + identifierHash uint64 + identifierHashData uintptr + identifierHashLen int + end int + languageVariant core.LanguageVariant + scriptTarget core.ScriptTarget + onError ErrorCallback + skipTrivia bool ScannerState numberCache map[string]string @@ -282,6 +289,15 @@ func (s *Scanner) TokenValue() string { return s.tokenValue } +// IdentifierHash returns ast.SymbolNameHash(text) if text is the exact string +// most recently produced by the identifier fast path. +func (s *Scanner) IdentifierHash(text string) (uint64, bool) { + if len(text) != 0 && len(text) == s.identifierHashLen && uintptr(unsafe.Pointer(unsafe.StringData(text))) == s.identifierHashData { + return s.identifierHash, true + } + return 0, false +} + func (s *Scanner) TokenRange() core.TextRange { return core.NewTextRange(s.tokenStart, s.pos) } @@ -1489,13 +1505,25 @@ func (s *Scanner) scanIdentifier(prefixLength int, variant identifierVariant) bo ch := s.char() // Fast path for simple ASCII identifiers if variant != identifierVariantJSX && (stringutil.IsASCIILetter(ch) || ch == '_' || ch == '$') { - s.pos++ - s.scanASCIIWhile(func(b byte) bool { - return (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || b == '_' || b == '$' - }) + h := ast.SymbolNameHashAdd(ast.SymbolNameHashSeed, byte(ch)) + text := s.text[:s.end] + i := s.pos + 1 + for ; i < len(text); i++ { + b := text[i] + if !((b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') || (b >= '0' && b <= '9') || b == '_' || b == '$') { + break + } + h = ast.SymbolNameHashAdd(h, b) + } + s.pos = i ch = s.char() if ch < utf8.RuneSelf && ch != '\\' { s.tokenValue = s.text[start:s.pos] + if start == identifierStart { + s.identifierHash = ast.SymbolNameHashFinish(h) + s.identifierHashData = uintptr(unsafe.Pointer(unsafe.StringData(s.tokenValue))) + s.identifierHashLen = len(s.tokenValue) + } return true } s.pos = identifierStart diff --git a/tsc/internal/scanner/utilities.go b/tsc/internal/scanner/utilities.go index 6a8ad06ef4ad7..317d14f07be36 100644 --- a/tsc/internal/scanner/utilities.go +++ b/tsc/internal/scanner/utilities.go @@ -16,7 +16,7 @@ func tokenIsIdentifierOrKeyword(token ast.Kind) bool { } func IdentifierToKeywordKind(node *ast.Identifier) ast.Kind { - return textToKeyword[node.Text] + return textToKeyword[node.Text.Value()] } func GetSourceTextOfNodeFromSourceFile(sourceFile *ast.SourceFile, node *ast.Node, includeTrivia bool) string { diff --git a/tsc/internal/tracing/tracing.go b/tsc/internal/tracing/tracing.go index f13ba7bf07377..244c68181de25 100644 --- a/tsc/internal/tracing/tracing.go +++ b/tsc/internal/tracing/tracing.go @@ -605,9 +605,9 @@ func (t *typeTracer) buildTypeDescriptor(typ TracedType, recursionIdentityMap ma // Symbol name - escape the internal symbol name prefix for valid JSON if sym := aliasSymbol; sym != nil { - desc.SymbolName = ast.EscapeAllInternalSymbolNames(sym.Name()) + desc.SymbolName = ast.EscapeAllInternalSymbolNames(sym.Name().Value()) } else if symbol != nil { - desc.SymbolName = ast.EscapeAllInternalSymbolNames(symbol.Name()) + desc.SymbolName = ast.EscapeAllInternalSymbolNames(symbol.Name().Value()) } // Tuple flag diff --git a/tsc/internal/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index 7e362d9fb1660..2b4a46829eb0e 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -1193,7 +1193,7 @@ func (tx *DeclarationTransformer) tryGetNameOfAssignedExpression(unwrapped *ast. nameText = unwrapped.Text() } if nameText != "" && nameText != "default" { - if tx.resolver.IsNameResolvable(tx.enclosingDeclaration, nameText) { + if tx.resolver.IsNameResolvable(tx.enclosingDeclaration, ast.MakeSymbolName(nameText)) { // create a unique name that shares the same text as its' base nameNode = tx.Factory().NewUniqueNameEx(nameText, printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) } else { @@ -2811,7 +2811,7 @@ func (tx *DeclarationTransformer) transformExpandoAssignment(node *ast.BinaryExp exportName := tx.Factory().NewIdentifier(property) localName := tx.tryGetNameOfAssignedExpression(node.AsNode()) - if localName == nil && !tx.resolver.IsNameResolvable(tx.enclosingDeclaration, property) && !ast.IsNonContextualKeyword(scanner.StringToToken(exportName.Text())) { + if localName == nil && !tx.resolver.IsNameResolvable(tx.enclosingDeclaration, ast.MakeSymbolName(property)) && !ast.IsNonContextualKeyword(scanner.StringToToken(exportName.Text())) { // use exportName as localName if there won't be any conflicts or keyword issues localName = exportName } @@ -2847,7 +2847,7 @@ func (tx *DeclarationTransformer) transformExpandoAssignment(node *ast.BinaryExp declarationData.Symbol = host containerData := synthesizedNamespace.LocalsContainerData() containerData.Locals = make(ast.SymbolTable, 0) - containerData.Locals[localName.Text()] = symbol + containerData.Locals[localName.TextSymbolName()] = symbol oldEnclosing := tx.enclosingDeclaration tx.enclosingDeclaration = synthesizedNamespace @@ -3020,7 +3020,7 @@ func extractExpandoHostParams(node *ast.Node) (typeParameters *ast.TypeParameter func (tx *DeclarationTransformer) tryGetPropertyName(node *ast.Node) string { if ast.IsElementAccessExpression(node) { - return tx.resolver.GetElementAccessExpressionName(node.AsElementAccessExpression()) + return tx.resolver.GetElementAccessExpressionName(node.AsElementAccessExpression()).Value() } if ast.IsPropertyAccessExpression(node) { return node.Name().Text() diff --git a/tsc/internal/transformers/tstransforms/typeserializer.go b/tsc/internal/transformers/tstransforms/typeserializer.go index 21c5d183370a5..514d7014357fc 100644 --- a/tsc/internal/transformers/tstransforms/typeserializer.go +++ b/tsc/internal/transformers/tstransforms/typeserializer.go @@ -267,7 +267,7 @@ func (s *metadataSerializer) serializeUnionOrIntersectionConstituents(types []*a } serializedConstituent := s.serializeTypeNode(typeNode) - if ast.IsIdentifier(serializedConstituent) && serializedConstituent.AsIdentifier().Text == "Object" { + if ast.IsIdentifier(serializedConstituent) && serializedConstituent.AsIdentifier().Text == ast.SymbolNameObject { // One of the individual is global object, return immediately return serializedConstituent }