From 45e3b50e150d5c7db82a1d1612934d3dc3ebb9d2 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 8 Oct 2026 13:51:33 -0700 Subject: [PATCH 01/14] Intern symbol names with unique handles Symbols should share canonical names so identity checks and symbol-table lookups do not repeatedly compare string contents. Preserve textual behavior for diagnostics, emitted output, and the JavaScript API. --- tools/scripts/tsc/generate-enums.ts | 12 +- tools/scripts/tsc/options.test.ts | 8 + tsc/internal/api/session.go | 13 +- .../api/session_symbolresponse_test.go | 7 +- tsc/internal/ast/symbol.go | 70 +- tsc/internal/ast/symbol_test.go | 89 +- tsc/internal/ast/utilities.go | 16 +- tsc/internal/binder/binder.go | 57 +- tsc/internal/binder/binder_test.go | 52 ++ tsc/internal/binder/nameresolver.go | 28 +- tsc/internal/binder/referenceresolver.go | 16 +- tsc/internal/checker/checker.go | 805 +++++++++--------- tsc/internal/checker/emitresolver.go | 15 +- tsc/internal/checker/emitsupport.go | 3 +- tsc/internal/checker/exports.go | 12 +- tsc/internal/checker/flow.go | 86 +- tsc/internal/checker/grammarchecks.go | 6 +- tsc/internal/checker/inference.go | 5 +- tsc/internal/checker/jsx.go | 121 +-- tsc/internal/checker/nodebuilder_hover.go | 39 +- tsc/internal/checker/nodebuilderimpl.go | 87 +- tsc/internal/checker/nodebuilderscopes.go | 16 +- tsc/internal/checker/pseudotypenodebuilder.go | 4 +- tsc/internal/checker/relater.go | 92 +- tsc/internal/checker/services.go | 85 +- tsc/internal/checker/symbolaccessibility.go | 3 +- tsc/internal/checker/types.go | 26 +- tsc/internal/checker/types_test.go | 45 +- tsc/internal/checker/utilities.go | 139 +-- tsc/internal/ls/autoimport/export.go | 14 +- tsc/internal/ls/autoimport/extract.go | 15 +- tsc/internal/ls/autoimport/fix.go | 16 +- tsc/internal/ls/autoimport/import_adder.go | 46 +- tsc/internal/ls/autoimport/index.go | 11 +- tsc/internal/ls/autoimport/index_test.go | 22 +- tsc/internal/ls/autoimport/util.go | 11 +- tsc/internal/ls/autoimport/view.go | 6 +- ..._fixclassincorrectlyimplementsinterface.go | 2 +- .../codeactions_fixmissingtypeannotation.go | 6 +- tsc/internal/ls/codeactions_importfixes.go | 17 +- .../ls/codeactions_missingmemberfixer.go | 6 +- tsc/internal/ls/completions.go | 53 +- tsc/internal/ls/definition.go | 7 +- tsc/internal/ls/findallreferences.go | 9 +- tsc/internal/ls/importTracker.go | 19 +- tsc/internal/ls/inlay_hints.go | 2 +- tsc/internal/ls/jsdoc.go | 3 +- tsc/internal/ls/lsutil/utilities.go | 5 +- tsc/internal/ls/signaturehelp.go | 2 +- tsc/internal/ls/sourcedefinition.go | 3 +- tsc/internal/ls/string_completions.go | 14 +- tsc/internal/ls/utilities.go | 5 +- tsc/internal/printer/namegenerator.go | 3 +- tsc/internal/tracing/tracing.go | 4 +- .../transformers/declarations/transform.go | 5 +- 55 files changed, 1219 insertions(+), 1044 deletions(-) diff --git a/tools/scripts/tsc/generate-enums.ts b/tools/scripts/tsc/generate-enums.ts index 2f2a315e4b49f..260a7d720b632 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 `unique.Make`, * 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\((.*)\)$/, "$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/options.test.ts b/tools/scripts/tsc/options.test.ts index 27c9827bdb056..5d794428dd799 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.d.ts"), "utf8"); + assert.equal(actual.replaceAll("\r\n", "\n"), code.replace("export enum ", "export declare enum ")); +}); + 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/tsc/internal/api/session.go b/tsc/internal/api/session.go index c88ef9a1b3bee..731a79b1217fe 100644 --- a/tsc/internal/api/session.go +++ b/tsc/internal/api/session.go @@ -14,6 +14,7 @@ import ( "sync" "sync/atomic" "time" + "unique" "github.com/microsoft/TypeScript/tsc/internal/api/encoder" "github.com/microsoft/TypeScript/tsc/internal/api/requestfilesystem" @@ -2903,7 +2904,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(unique.Make(params.Name), location, ast.SymbolFlags(params.Meaning), params.ExcludeGlobals) if symbol == nil { return nil, nil } @@ -3487,7 +3488,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)) @@ -4319,7 +4320,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) @@ -4605,7 +4606,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, unique.Make(params.Name)) if prop == nil { return nil, nil } @@ -4626,7 +4627,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, unique.Make(params.Name)), setup.checker), nil } // handleGetConstantValue returns the constant value of an enum member or const enum access. @@ -4897,7 +4898,7 @@ func (s *Session) handleGetMemberInModuleExports(ctx context.Context, params *Ge return nil, nil } - member := setup.checker.TryGetMemberInModuleExports(params.Name, symbol) + member := setup.checker.TryGetMemberInModuleExports(unique.Make(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 90b19bc927beb..727a40858771f 100644 --- a/tsc/internal/api/session_symbolresponse_test.go +++ b/tsc/internal/api/session_symbolresponse_test.go @@ -4,6 +4,7 @@ import ( "strconv" "strings" "testing" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -62,7 +63,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(unique.Make("C")) symbol.SetDeclarations([]*ast.Node{class}) sd := newTestSnapshotData() @@ -86,7 +87,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()[unique.Make("property")] response := newFileSymbolResponse(member) assert.DeepEqual(t, response.Parent, reference) } @@ -110,6 +111,6 @@ func TestContentMappedSymbolsAreSnapshotOwned(t *testing.T) { assert.NilError(t, err) assert.Equal(t, resolved, class) - reference := newSymbolReference(class.Members()["property"]) + reference := newSymbolReference(class.Members()[unique.Make("property")]) assert.Equal(t, reference.File, "") } diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index 00312310691c5..b910707063acc 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -3,6 +3,7 @@ package ast import ( "strings" "sync/atomic" + "unique" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/debug" @@ -21,7 +22,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 +43,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 +71,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 +110,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 +165,46 @@ 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 = unique.Handle[string] -type SymbolTable map[string]*Symbol +// EmptySymbolName is a valid empty name, distinct from an unset zero handle. +var EmptySymbolName = unique.Make("") + +type SymbolTable map[SymbolName]*Symbol 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 = unique.Make(InternalSymbolNamePrefix + "call") // Call signatures + InternalSymbolNameConstructor = unique.Make(InternalSymbolNamePrefix + "constructor") // Constructor implementations + InternalSymbolNameNew = unique.Make(InternalSymbolNamePrefix + "new") // Constructor signatures + InternalSymbolNameIndex = unique.Make(InternalSymbolNamePrefix + "index") // Index signatures + InternalSymbolNameExportStar = unique.Make(InternalSymbolNamePrefix + "export") // Module export * declarations + InternalSymbolNameGlobal = unique.Make(InternalSymbolNamePrefix + "global") // Global self-reference + InternalSymbolNameMissing = unique.Make(InternalSymbolNamePrefix + "missing") // Indicates missing symbol + InternalSymbolNameType = unique.Make(InternalSymbolNamePrefix + "type") // Anonymous type literal symbol + InternalSymbolNameObject = unique.Make(InternalSymbolNamePrefix + "object") // Anonymous object literal declaration + InternalSymbolNameJSXAttributes = unique.Make(InternalSymbolNamePrefix + "jsxAttributes") // Anonymous JSX attributes object literal declaration + InternalSymbolNameClass = unique.Make(InternalSymbolNamePrefix + "class") // Unnamed class expression + InternalSymbolNameFunction = unique.Make(InternalSymbolNamePrefix + "function") // Unnamed function expression + InternalSymbolNameComputed = unique.Make(InternalSymbolNamePrefix + "computed") // Computed property name declaration with dynamic name + InternalSymbolNameAssignmentDeclaration = unique.Make(InternalSymbolNamePrefix + "assignment") // Assignment declarations + InternalSymbolNameInstantiationExpression = unique.Make(InternalSymbolNamePrefix + "instantiationExpression") // Instantiation expressions + InternalSymbolNameImportAttributes = unique.Make(InternalSymbolNamePrefix + "importAttributes") + InternalSymbolNameExportEquals = unique.Make("export=") // Export assignment symbol + InternalSymbolNameDefault = unique.Make("default") // Default export symbol (technically not wholly internal, but included here for usability) + InternalSymbolNameThis = unique.Make("this") + InternalSymbolNameModuleExports = unique.Make("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 +212,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 +224,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 } diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index 1f8f44aaa66d2..c714e5227da4f 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -3,13 +3,44 @@ package ast_test import ( "reflect" "runtime" + "strings" "testing" + "unique" "unsafe" "github.com/microsoft/TypeScript/tsc/internal/ast" "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 := unique.Make(text) + otherName := unique.Make(strings.Clone(text)) + symbol := ast.NewSymbol() + symbol.SetName(name) + var storedName unique.Handle[string] = 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(unique.Make(text + "other")) + assert.Assert(t, symbol.Name() == shared.Name()) + }) + } + assert.Assert(t, ast.InternalSymbolNameCall != unique.Make("__call")) + assert.Assert(t, ast.NewSymbol().Name() == unique.Make("")) + assert.Assert(t, new(ast.SymbolWithData).Initialize().Name() == unique.Make("")) +} + func TestSymbolFieldsArePrivate(t *testing.T) { t.Parallel() for field := range reflect.TypeFor[ast.Symbol]().Fields() { @@ -23,7 +54,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 +69,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{unique.Make("member"): member} + exports := ast.SymbolTable{unique.Make("export"): export} symbol.SetFlags(ast.SymbolFlagsClass | ast.SymbolFlagsTransient) symbol.SetCheckFlags(ast.CheckFlagsReadonly) - symbol.SetName("C") + symbol.SetName(unique.Make("C")) symbol.SetDeclarations(declarations) symbol.SetValueDeclaration(declaration) symbol.SetMembers(members, &arena) @@ -53,11 +84,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()[unique.Make("member")], member) + assert.Equal(t, symbol.Exports()[unique.Make("export")], export) assert.Equal(t, symbol.Parent(), parent) assert.Equal(t, symbol.ExportSymbol(), exportSymbol) @@ -65,14 +96,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()[unique.Make("added")] = export + assert.Equal(t, members[unique.Make("added")], export) + symbol.Exports()[unique.Make("added")] = member + assert.Equal(t, exports[unique.Make("added")], member) symbol.SetFlags(ast.SymbolFlagsNone) symbol.SetCheckFlags(0) - symbol.SetName("") + symbol.SetName(unique.Make("")) symbol.SetDeclarations(nil) symbol.SetValueDeclaration(nil) symbol.SetMembers(nil, &arena) @@ -82,7 +113,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 +130,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[unique.Make("member")] = member + assert.Equal(t, symbol.Members()[unique.Make("member")], member) + assert.Equal(t, ast.GetMembers(symbol, &arena)[unique.Make("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[unique.Make("export")] = export + assert.Equal(t, symbol.Exports()[unique.Make("export")], export) + assert.Equal(t, ast.GetExports(symbol, &arena)[unique.Make("export")], export) symbol.SetMembers(nil, &arena) symbol.SetExports(nil, &arena) @@ -118,7 +149,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 +173,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{unique.Make("member"): member}, &arena) + symbol.SetExports(ast.SymbolTable{unique.Make("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()[unique.Make("member")], member) + assert.Equal(t, alias.Exports()[unique.Make("export")], export) assert.Equal(t, symbol.ExportSymbol(), export) symbol.SetMembers(nil, &otherArena) alias.SetExports(nil, &arena) @@ -155,14 +186,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)[unique.Make("new")] = export + ast.GetExports(symbol, &arena)[unique.Make("new")] = member for range 1024 { - ast.NewSymbol().SetExports(ast.SymbolTable{"export": export}, &arena) + ast.NewSymbol().SetExports(ast.SymbolTable{unique.Make("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()[unique.Make("new")], export) + assert.Equal(t, alias.Exports()[unique.Make("new")], member) } diff --git a/tsc/internal/ast/utilities.go b/tsc/internal/ast/utilities.go index ff11fd6a2c2f4..9b4ffbdc399cc 100644 --- a/tsc/internal/ast/utilities.go +++ b/tsc/internal/ast/utilities.go @@ -6,6 +6,7 @@ import ( "strings" "sync" "sync/atomic" + "unique" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/debug" @@ -1708,14 +1709,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 +2668,7 @@ func GetNamespaceDeclarationNode(node *Node) *Node { } func ModuleExportNameIsDefault(node *Node) bool { - return node.Text() == InternalSymbolNameDefault + return unique.Make(node.Text()) == InternalSymbolNameDefault } func IsDefaultImport(node *Node /*ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration*/) bool { @@ -3282,22 +3284,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 unique.Make(name.Text()) case KindComputedPropertyName: nameExpression := name.Expression() if IsStringOrNumericLiteralLike(nameExpression) { - return nameExpression.Text() + return unique.Make(nameExpression.Text()) } if IsSignedNumericLiteral(nameExpression) { text := nameExpression.AsPrefixUnaryExpression().Operand.Text() if nameExpression.AsPrefixUnaryExpression().Operator == KindMinusToken { text = "-" + text } - return text + return unique.Make(text) } return InternalSymbolNameMissing } diff --git a/tsc/internal/binder/binder.go b/tsc/internal/binder/binder.go index a95bb19ecdff7..0ff6ba5042742 100644 --- a/tsc/internal/binder/binder.go +++ b/tsc/internal/binder/binder.go @@ -4,6 +4,7 @@ import ( "slices" "strconv" "sync" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -129,7 +130,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 +154,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 +299,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 +312,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 unique.Make(ast.InternalSymbolNamePrefix + "\"" + moduleName + "\"pattern@" + strconv.FormatUint(uint64(ast.GetNodeId(attributes)), 10)) } } - return "\"" + moduleName + "\"" + return unique.Make("\"" + moduleName + "\"") } if ast.IsPrivateIdentifier(name) { // containingClass exists because private names only allowed inside classes @@ -326,17 +327,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 unique.Make(name.Text()) } 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 unique.Make(nameExpression.Text()) } if ast.IsSignedNumericLiteral(nameExpression) { unaryExpression := nameExpression.AsPrefixUnaryExpression() - return scanner.TokenToString(unaryExpression.Operator) + unaryExpression.Operand.Text() + return unique.Make(scanner.TokenToString(unaryExpression.Operator) + unaryExpression.Operand.Text()) } panic("Only computed properties with literal names have declaration names") } @@ -366,13 +367,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 unique.Make(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 +771,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, unique.Make("\""+b.file.FileName().RemoveFileExtension().AsString()+"\"")) } func (b *Binder) bindModuleDeclaration(node *ast.Node) { @@ -919,7 +920,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 = unique.Make(node.AsFunctionExpression().Name().Text()) } b.bindAnonymousDeclaration(node, ast.SymbolFlagsFunction, bindingName) } @@ -953,7 +954,7 @@ func (b *Binder) bindClassLikeDeclaration(node *ast.Node) { case ast.KindClassExpression: nameText := ast.InternalSymbolNameClass if name != nil { - nameText = name.Text() + nameText = unique.Make(name.Text()) } b.bindAnonymousDeclaration(node, ast.SymbolFlagsClass, nameText) } @@ -967,10 +968,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, unique.Make("prototype")) 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 +1204,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, unique.Make("__"+strconv.Itoa(index))) } else { b.declareSymbolAndAddToSymbolTable(node, ast.SymbolFlagsFunctionScopedVariable, ast.SymbolFlagsParameterExcludes) } @@ -1235,7 +1236,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 +1274,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(unique.Make(node.Text()), 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[unique.Make(name.Text())] } } 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()[unique.Make(name.Text())] } } 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 +1614,8 @@ func (b *Binder) bindContainer(node *ast.Node, containerFlags ContainerFlags) { } } if b.file.CommonJSModuleIndicator != nil { - b.declareCommonJSVariable("module") - b.declareCommonJSVariable("exports") + b.declareCommonJSVariable(unique.Make("module")) + b.declareCommonJSVariable(unique.Make("exports")) } } if ast.IsSourceFile(node) && ast.IsExternalOrCommonJSModule(node.AsSourceFile()) || ast.IsAmbientModule(node) { @@ -1625,19 +1626,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 == unique.Make("module") { + exportsProperty := b.newSymbol(ast.SymbolFlagsModuleExports|ast.SymbolFlagsProperty, unique.Make("exports")) 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()[unique.Make("exports")] = exportsProperty } locals[name] = symbol } diff --git a/tsc/internal/binder/binder_test.go b/tsc/internal/binder/binder_test.go index dc3c4bc1bc26c..a5340ad1ea15a 100644 --- a/tsc/internal/binder/binder_test.go +++ b/tsc/internal/binder/binder_test.go @@ -3,6 +3,7 @@ package binder import ( "runtime" "testing" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -10,8 +11,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 := unique.Make("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()[unique.Make("Shape")].Members() + for _, name := range []ast.SymbolName{ast.InternalSymbolNameCall, unique.Make("__call"), unique.Make("literal"), unique.Make("0")} { + assert.Assert(t, members[name] != nil) + assert.Assert(t, members[name].Name() == name) + } + assert.Assert(t, members[ast.InternalSymbolNameCall] != members[unique.Make("__call")]) + assert.Assert(t, file.Symbol.Exports()[unique.Make("renamed")].Name() == unique.Make("renamed")) + + first := file.Symbol.Exports()[ast.InternalSymbolNameDefault] + second := file.Symbol.Exports()[unique.Make("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..d1dc1507cfa8a 100644 --- a/tsc/internal/binder/nameresolver.go +++ b/tsc/internal/binder/nameresolver.go @@ -1,6 +1,8 @@ package binder import ( + "unique" + "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/diagnostics" @@ -13,16 +15,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 +33,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 == unique.Make("const") loop: for location != nil { if nameIsConst && ast.IsConstAssertion(location) { @@ -161,7 +163,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 +198,7 @@ loop: } if ast.IsClassExpression(location) && meaning&ast.SymbolFlagsClass != 0 { className := location.Name() - if className != nil && name == className.Text() { + if className != nil && name == unique.Make(className.Text()) { result = location.Symbol() break loop } @@ -234,18 +236,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 == unique.Make("arguments") { result = r.argumentsSymbol() break loop } case ast.KindFunctionExpression: - if meaning&ast.SymbolFlagsVariable != 0 && name == "arguments" { + if meaning&ast.SymbolFlagsVariable != 0 && name == unique.Make("arguments") { result = r.argumentsSymbol() break loop } if meaning&ast.SymbolFlagsFunction != 0 { functionName := location.AsFunctionExpression().Name() - if functionName != nil && name == functionName.Text() { + if functionName != nil && name == unique.Make(functionName.Text()) { result = location.Symbol() break loop } @@ -295,7 +297,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 == unique.Make(parameterName.Text()) { result = location.AsInferTypeNode().TypeParameter.Symbol() break loop } @@ -423,7 +425,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 +445,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(unique.Make("arguments")) 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..8bce7e8a58ad2 100644 --- a/tsc/internal/binder/referenceresolver.go +++ b/tsc/internal/binder/referenceresolver.go @@ -1,6 +1,8 @@ package binder import ( + "unique" + "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/diagnostics" @@ -11,19 +13,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 +94,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, unique.Make(reference.Text()), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } if r.resolver == nil { @@ -101,7 +103,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, unique.Make(reference.Text()), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } func (r *referenceResolver) isTypeOnlyAliasDeclaration(symbol *ast.Symbol) bool { @@ -237,7 +239,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 +247,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 67a9ab08cfd17..e34bfa56564f1 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -12,6 +12,7 @@ import ( "strings" "sync" "sync/atomic" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -361,12 +362,12 @@ const ( IntrinsicTypeKindNoInfer ) -var intrinsicTypeKinds = map[string]IntrinsicTypeKind{ - "Uppercase": IntrinsicTypeKindUppercase, - "Lowercase": IntrinsicTypeKindLowercase, - "Capitalize": IntrinsicTypeKindCapitalize, - "Uncapitalize": IntrinsicTypeKindUncapitalize, - "NoInfer": IntrinsicTypeKindNoInfer, +var intrinsicTypeKinds = map[ast.SymbolName]IntrinsicTypeKind{ + unique.Make("Uppercase"): IntrinsicTypeKindUppercase, + unique.Make("Lowercase"): IntrinsicTypeKindLowercase, + unique.Make("Capitalize"): IntrinsicTypeKindCapitalize, + unique.Make("Uncapitalize"): IntrinsicTypeKindUncapitalize, + unique.Make("NoInfer"): IntrinsicTypeKindNoInfer, } type MappedTypeModifiers uint32 @@ -523,7 +524,7 @@ const ( ) type IterationTypesResolver struct { - iteratorSymbolName string + iteratorSymbolName ast.SymbolName getGlobalIteratorType func() *Type getGlobalIterableType func() *Type getGlobalIterableTypeChecked func() *Type @@ -540,10 +541,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 } @@ -657,14 +658,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 @@ -694,7 +695,7 @@ type Checker struct { structuredTypeExtraArena core.Arena[structuredTypeExtra] lazyStateArena core.Arena[LazyState] memberLayoutArena core.Arena[MemberLayout] - layoutMemberInfos map[string]MemberInfo + layoutMemberInfos map[ast.SymbolName]MemberInfo freeTypeSets *temporaryTypeSet freePropertyCounts *temporaryPropertyCounts mergedSymbols map[*ast.Symbol]*ast.Symbol @@ -991,14 +992,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, unique.Make("undefined")) + c.argumentsSymbol = c.newSymbol(ast.SymbolFlagsProperty, unique.Make("arguments")) + c.requireSymbol = c.newSymbol(ast.SymbolFlagsProperty, unique.Make("require")) + c.unknownSymbol = c.newSymbol(ast.SymbolFlagsProperty, unique.Make("unknown")) + 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, unique.Make("globalThis"), ast.CheckFlagsReadonly) c.globalThisSymbol.SetExports(c.globals, &c.symbolExtraArena) c.globals[c.globalThisSymbol.Name()] = c.globalThisSymbol c.resolveName = c.createNameResolver().Resolve @@ -1077,7 +1078,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: unique.Make("<>"), 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) @@ -1099,57 +1100,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(unique.Make("Symbol"), 0 /*arity*/, false /*reportErrors*/) + c.getGlobalBigIntType = c.getGlobalTypeResolver(unique.Make("BigInt"), 0 /*arity*/, false /*reportErrors*/) + c.getGlobalImportMetaType = c.getGlobalTypeResolver(unique.Make("ImportMeta"), 0 /*arity*/, true /*reportErrors*/) + c.getGlobalImportAttributesType = c.getGlobalTypeResolver(unique.Make("ImportAttributes"), 0 /*arity*/, false /*reportErrors*/) + c.getGlobalImportAttributesTypeChecked = c.getGlobalTypeResolver(unique.Make("ImportAttributes"), 0 /*arity*/, true /*reportErrors*/) + c.getGlobalNonNullableTypeAliasOrNil = c.getGlobalTypeAliasResolver(unique.Make("NonNullable"), 1 /*arity*/, false /*reportErrors*/) + c.getGlobalExtractSymbol = c.getGlobalTypeAliasResolver(unique.Make("Extract"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalDisposableType = c.getGlobalTypeResolver(unique.Make("Disposable"), 0 /*arity*/, true /*reportErrors*/) + c.getGlobalAsyncDisposableType = c.getGlobalTypeResolver(unique.Make("AsyncDisposable"), 0 /*arity*/, true /*reportErrors*/) + c.getGlobalAwaitedSymbol = c.getGlobalTypeAliasResolver(unique.Make("Awaited"), 1 /*arity*/, true /*reportErrors*/) + c.getGlobalAwaitedSymbolOrNil = c.getGlobalTypeAliasResolver(unique.Make("Awaited"), 1 /*arity*/, false /*reportErrors*/) + c.getGlobalNaNSymbolOrNil = c.getGlobalValueSymbolResolver(unique.Make("NaN"), false /*reportErrors*/) + c.getGlobalRecordSymbol = c.getGlobalTypeAliasResolver(unique.Make("Record"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalTemplateStringsArrayType = c.getGlobalTypeResolver(unique.Make("TemplateStringsArray"), 0 /*arity*/, true /*reportErrors*/) + c.getGlobalESSymbolConstructorSymbolOrNil = c.getGlobalValueSymbolResolver(unique.Make("Symbol"), false /*reportErrors*/) + c.getGlobalESSymbolConstructorTypeSymbolOrNil = c.getGlobalTypeSymbolResolver(unique.Make("SymbolConstructor"), false /*reportErrors*/) + c.getGlobalImportCallOptionsType = c.getGlobalTypeResolver(unique.Make("ImportCallOptions"), 0 /*arity*/, false /*reportErrors*/) + c.getGlobalImportCallOptionsTypeChecked = c.getGlobalTypeResolver(unique.Make("ImportCallOptions"), 0 /*arity*/, true /*reportErrors*/) + c.getGlobalPromiseType = c.getGlobalTypeResolver(unique.Make("Promise"), 1 /*arity*/, false /*reportErrors*/) + c.getGlobalPromiseTypeChecked = c.getGlobalTypeResolver(unique.Make("Promise"), 1 /*arity*/, true /*reportErrors*/) + c.getGlobalPromiseLikeType = c.getGlobalTypeResolver(unique.Make("PromiseLike"), 1 /*arity*/, true /*reportErrors*/) + c.getGlobalAbstractModuleSourceType = c.getGlobalTypeResolver(unique.Make("AbstractModuleSource"), 0 /*arity*/, true /*reportErrors*/) + c.getGlobalPromiseConstructorSymbol = c.getGlobalValueSymbolResolver(unique.Make("Promise"), true /*reportErrors*/) + c.getGlobalPromiseConstructorSymbolOrNil = c.getGlobalValueSymbolResolver(unique.Make("Promise"), false /*reportErrors*/) + c.getGlobalOmitSymbol = c.getGlobalTypeAliasResolver(unique.Make("Omit"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalNoInferSymbolOrNil = c.getGlobalTypeAliasResolver(unique.Make("NoInfer"), 1 /*arity*/, false /*reportErrors*/) + c.getGlobalIteratorType = c.getGlobalTypeResolver(unique.Make("Iterator"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIterableType = c.getGlobalTypeResolver(unique.Make("Iterable"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIterableTypeChecked = c.getGlobalTypeResolver(unique.Make("Iterable"), 3 /*arity*/, true /*reportErrors*/) + c.getGlobalIterableIteratorType = c.getGlobalTypeResolver(unique.Make("IterableIterator"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIterableIteratorTypeChecked = c.getGlobalTypeResolver(unique.Make("IterableIterator"), 3 /*arity*/, true /*reportErrors*/) + c.getGlobalIteratorObjectType = c.getGlobalTypeResolver(unique.Make("IteratorObject"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalGeneratorType = c.getGlobalTypeResolver(unique.Make("Generator"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIteratorType = c.getGlobalTypeResolver(unique.Make("AsyncIterator"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIterableType = c.getGlobalTypeResolver(unique.Make("AsyncIterable"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIterableTypeChecked = c.getGlobalTypeResolver(unique.Make("AsyncIterable"), 3 /*arity*/, true /*reportErrors*/) + c.getGlobalAsyncIterableIteratorType = c.getGlobalTypeResolver(unique.Make("AsyncIterableIterator"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncIterableIteratorTypeChecked = c.getGlobalTypeResolver(unique.Make("AsyncIterableIterator"), 3 /*arity*/, true /*reportErrors*/) + c.getGlobalAsyncIteratorObjectType = c.getGlobalTypeResolver(unique.Make("AsyncIteratorObject"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalAsyncGeneratorType = c.getGlobalTypeResolver(unique.Make("AsyncGenerator"), 3 /*arity*/, false /*reportErrors*/) + c.getGlobalIteratorYieldResultType = c.getGlobalTypeResolver(unique.Make("IteratorYieldResult"), 1 /*arity*/, false /*reportErrors*/) + c.getGlobalIteratorReturnResultType = c.getGlobalTypeResolver(unique.Make("IteratorReturnResult"), 1 /*arity*/, false /*reportErrors*/) + c.getGlobalTypedPropertyDescriptorType = c.getGlobalTypeResolver(unique.Make("TypedPropertyDescriptor"), 1 /*arity*/, true /*reportErrors*/) + c.getGlobalClassDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassDecoratorContext"), 1 /*arity*/, true /*reportErrors*/) + c.getGlobalClassMethodDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassMethodDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassGetterDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassGetterDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassSetterDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassSetterDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassAccessorDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassAccessorDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassAccessorDecoratorTargetType = c.getGlobalTypeResolver(unique.Make("ClassAccessorDecoratorTarget"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassAccessorDecoratorResultType = c.getGlobalTypeResolver(unique.Make("ClassAccessorDecoratorResult"), 2 /*arity*/, true /*reportErrors*/) + c.getGlobalClassFieldDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassFieldDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) c.initializeClosures() c.initializeIterationResolvers() c.initializeChecker() @@ -1189,27 +1190,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)) }) @@ -1218,12 +1219,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(unique.Make(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 @@ -1233,7 +1234,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 } @@ -1248,7 +1249,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 { @@ -1257,10 +1258,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 { @@ -1279,7 +1280,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*/) } @@ -1299,7 +1300,7 @@ func (c *Checker) initializeClosures() { func (c *Checker) initializeIterationResolvers() { c.syncIterationTypesResolver = &IterationTypesResolver{ - iteratorSymbolName: "iterator", + iteratorSymbolName: unique.Make("iterator"), getGlobalIteratorType: c.getGlobalIteratorType, getGlobalIterableType: c.getGlobalIterableType, getGlobalIterableTypeChecked: c.getGlobalIterableTypeChecked, @@ -1316,7 +1317,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: unique.Make("asyncIterator"), getGlobalIteratorType: c.getGlobalAsyncIteratorType, getGlobalIterableType: c.getGlobalAsyncIterableType, getGlobalIterableTypeChecked: c.getGlobalAsyncIterableTypeChecked, @@ -1341,7 +1342,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[unique.Make("globalThis")]; fileGlobalThisSymbol != nil { for _, d := range fileGlobalThisSymbol.Declarations() { c.addDiagnostic(NewDiagnosticForNode(d, diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, "globalThis")) } @@ -1384,31 +1385,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(unique.Make("IArguments"), 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(unique.Make("Array"), 1 /*arity*/, true /*reportErrors*/) + c.globalObjectType = c.getGlobalType(unique.Make("Object"), 0 /*arity*/, true /*reportErrors*/) + c.globalFunctionType = c.getGlobalType(unique.Make("Function"), 0 /*arity*/, true /*reportErrors*/) + c.globalCallableFunctionType = c.getGlobalStrictFunctionType(unique.Make("CallableFunction")) + c.globalNewableFunctionType = c.getGlobalStrictFunctionType(unique.Make("NewableFunction")) + c.globalStringType = c.getGlobalType(unique.Make("String"), 0 /*arity*/, true /*reportErrors*/) + c.globalNumberType = c.getGlobalType(unique.Make("Number"), 0 /*arity*/, true /*reportErrors*/) + c.globalBooleanType = c.getGlobalType(unique.Make("Boolean"), 0 /*arity*/, true /*reportErrors*/) + c.globalRegExpType = c.getGlobalType(unique.Make("RegExp"), 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(unique.Make("ReadonlyArray"), 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(unique.Make("ThisType"), 1 /*arity*/, false /*reportErrors*/) // Now merge global ambient module declarations for _, symbol := range ambientModuleSymbols { c.mergeGlobalSymbol(symbol) @@ -1500,8 +1501,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)[unique.Make(moduleName.Text())] = merged + ast.GetSymbolTable(&c.patternAmbientModuleAugmentationTargets)[unique.Make(moduleName.Text())] = 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 @@ -1527,7 +1528,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 { @@ -1583,7 +1584,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 @@ -1595,14 +1596,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) || unique.Make(errorLocation.Text()) != name || isTypeReferenceIdentifier(errorLocation) || IsInTypeQuery(errorLocation) { return false } container := c.getThisContainer(errorLocation, false /*includeArrowFunctions*/, false /*includeClassComputedPropertyName*/) @@ -1615,7 +1616,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. @@ -1624,7 +1625,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 } } @@ -1633,7 +1634,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) { @@ -1650,13 +1651,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) && unique.Make(errorLocation.Text()) == name { + declarationName = unique.Make(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 @@ -1666,7 +1667,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)) } @@ -1674,10 +1675,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 { @@ -1685,22 +1686,22 @@ 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), unique.Make(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 { - 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) +func (c *Checker) checkAndReportErrorForExportingPrimitiveType(errorLocation *ast.Node, name ast.SymbolName) bool { + if isPrimitiveTypeName(name.Value()) && errorLocation.Parent.Kind == ast.KindExportSpecifier { + c.error(errorLocation, diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name.Value()) return true } return false @@ -1710,43 +1711,43 @@ func isPrimitiveTypeName(s string) bool { return s == "any" || s == "string" || s == "number" || s == "boolean" || s == "never" || s == "unknown" } -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) { + if isPrimitiveTypeName(name.Value()) { grandparent := errorLocation.Parent.Parent if grandparent != nil && grandparent.Parent != nil && ast.IsHeritageClause(grandparent) { 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 } @@ -1759,12 +1760,12 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node if isExportAssignmentExpressionName(errorLocation) { 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) + if isES2015OrLaterConstructorName(name.Value()) { + 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 == unique.Make("K"), "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 } @@ -1791,18 +1792,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 @@ -1810,12 +1811,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"}, @@ -1826,8 +1827,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(unique.Make(e.primitive)) + result[unique.Make(e.builtin)] = sym } return result }) @@ -1844,7 +1845,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 @@ -1869,9 +1870,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 "" } @@ -1886,7 +1887,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) { @@ -1915,7 +1916,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 @@ -1935,7 +1936,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') @@ -1951,7 +1952,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()) } } } @@ -2245,7 +2246,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 { @@ -2635,7 +2636,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), unique.Make("prototype")) if proto != nil { t = c.getTypeOfSymbol(proto) } @@ -2643,7 +2644,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, unique.Make(name.AsQualifiedName().Right.Text())) } } } @@ -3086,7 +3087,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()) } } } @@ -3169,7 +3170,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()) } } } @@ -3187,14 +3188,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) && unique.Make(name.Text()) == 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) { @@ -3219,21 +3220,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 } @@ -3261,8 +3262,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() == unique.Make("prototype") { + 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. @@ -3277,7 +3278,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 { @@ -3289,7 +3290,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() { @@ -3731,7 +3732,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) } } } @@ -4319,7 +4320,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()) } } } @@ -4474,11 +4475,11 @@ func (c *Checker) checkClassForStaticPropertyNameConflicts(node *ast.Node) { if isStaticMember && memberNameNode != nil { memberName, _ := c.getEffectivePropertyNameForPropertyNameNode(memberNameNode) switch memberName { - case "name", "length", "caller", "arguments": + case unique.Make("name"), unique.Make("length"), unique.Make("caller"), unique.Make("arguments"): 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)), ) } @@ -4528,7 +4529,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 unique.Make(source.Name().Text()) != target.symbol.Name() { return false } // If the type parameter node does not have an identical constraintNode as the resolved @@ -4846,7 +4847,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(unique.Make(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 { @@ -4887,7 +4888,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) } @@ -5148,7 +5149,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} @@ -5605,7 +5606,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, unique.Make(attribute.Name().Text())) c.valueSymbolLinks.Get(member).resolvedType = c.getRegularTypeOfLiteralType(c.checkExpressionCached(attribute.AsImportAttribute().Value)) members[member.Name()] = member } @@ -5625,7 +5626,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), unique.Make("with")) } return nil } @@ -5748,7 +5749,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, unique.Make(exportedName.Text()), 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 { @@ -5914,7 +5915,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()) } } } @@ -6198,7 +6199,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, unique.Make(name.Text()), 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) @@ -6734,21 +6735,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, unique.Make("next"), errorNode, diagnosticOutput), + c.getIterationTypesOfMethod(t, r, unique.Make("return"), errorNode, diagnosticOutput), + c.getIterationTypesOfMethod(t, r, unique.Make("throw"), 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 != unique.Make("next") { return IterationTypes{} } var methodType *Type - if method != nil && !(methodName == "next" && method.Flags()&ast.SymbolFlagsOptional != 0) { - if methodName == "next" { + if method != nil && !(methodName == unique.Make("next") && method.Flags()&ast.SymbolFlagsOptional != 0) { + if methodName == unique.Make("next") { methodType = c.getTypeOfSymbol(method) } else { methodType = c.getTypeWithFacts(c.getTypeOfSymbol(method), TypeFactsNEUndefinedOrNull) @@ -6764,8 +6765,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 == unique.Make("next"), resolver.mustHaveANextMethodDiagnostic, resolver.mustBeAMethodDiagnostic) + c.reportDiagnostic(NewDiagnosticForNode(errorNode, diagnostic, methodName.Value()), diagnosticOutput) } return IterationTypes{} } @@ -6785,7 +6786,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 == unique.Make("next") { nextType = getMappedType(typeParameters[2], mapper) } return IterationTypes{getMappedType(typeParameters[0], mapper), getMappedType(typeParameters[1], mapper), nextType} @@ -6795,7 +6796,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 != unique.Make("throw") && len(signature.parameters) != 0 { methodParameterTypes = append(methodParameterTypes, c.getTypeAtPosition(signature, 0)) } methodReturnTypes = append(methodReturnTypes, c.getReturnTypeOfSignature(signature)) @@ -6804,17 +6805,17 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes // `return()` method, respectively. var returnTypes []*Type var nextType *Type - if methodName != "throw" { + if methodName != unique.Make("throw") { var methodParameterType *Type if methodParameterTypes != nil { methodParameterType = c.getUnionType(methodParameterTypes) } else { methodParameterType = c.unknownType } - if methodName == "next" { + if methodName == unique.Make("next") { // The value of `next(value)` is *not* awaited by async generators nextType = methodParameterType - } else if methodName == "return" { + } else if methodName == unique.Make("return") { // The value of `return(value)` *is* awaited by async generators resolvedMethodParameterType := core.OrElse(resolver.resolveIterationType(methodParameterType, errorNode), c.anyType) returnTypes = append(returnTypes, resolvedMethodParameterType) @@ -6832,7 +6833,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) @@ -6864,12 +6865,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, unique.Make("value") /* 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, unique.Make("value") /* as __String */) } if yieldType == nil && returnType == nil { return IterationTypes{} @@ -6894,7 +6895,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, unique.Make("done")), c.falseType) return c.isTypeAssignableTo(core.IfElse(kind == IterationTypeKindYield, c.falseType, c.trueType), doneType) } @@ -6918,7 +6919,7 @@ func (c *Checker) getIterationDiagnosticDetails(use IterationUse, inputType *Typ if yieldType != nil { return diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, false } - if inputType.symbol != nil && isES2015OrLaterIterable(inputType.symbol.Name()) { + if inputType.symbol != nil && isES2015OrLaterIterable(inputType.symbol.Name().Value()) { return diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, true } if allowsStrings { @@ -6956,16 +6957,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()[unique.Make(node.PropertyNameOrName().Text())]; 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 = unique.Make(errorNode.Text()) } specifierText := "..." if importDeclaration := ast.FindAncestor(node, func(n *ast.Node) bool { @@ -6977,9 +6978,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 } @@ -7060,7 +7061,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()) } } } @@ -7091,7 +7092,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[unique.Make(node.Name().Text())] != 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, @@ -7329,7 +7330,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: @@ -7364,7 +7365,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)) } } } @@ -7789,7 +7790,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, unique.Make(ast.GetFirstIdentifier(node).Text()), 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()) @@ -7891,8 +7892,8 @@ func (c *Checker) getUniqueTypeParameters(context *InferenceContext, typeParamet for _, tp := range typeParameters { name := tp.symbol.Name() if hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name) { - newName := getUniqueTypeParameterName(core.Concatenate(context.inferredTypeParameters, result), name) - symbol := c.newSymbol(ast.SymbolFlagsTypeParameter, newName) + newName := getUniqueTypeParameterName(core.Concatenate(context.inferredTypeParameters, result), name.Value()) + symbol := c.newSymbol(ast.SymbolFlagsTypeParameter, unique.Make(newName)) newTypeParameter := c.newTypeParameter(symbol) newTypeParameter.AsTypeParameter().target = tp oldTypeParameters = append(oldTypeParameters, tp) @@ -7911,7 +7912,7 @@ 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 }) @@ -7924,7 +7925,7 @@ func getUniqueTypeParameterName(typeParameters []*Type, baseName string) string index := 1 for { augmentedName := baseName + strconv.Itoa(index) - if !hasTypeParameterByName(typeParameters, augmentedName) { + if !hasTypeParameterByName(typeParameters, unique.Make(augmentedName)) { return augmentedName } index++ @@ -8049,7 +8050,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(unique.Make(node.Text()), node) } return links.resolvedSymbol } @@ -8441,7 +8442,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 } } @@ -8450,7 +8451,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 { @@ -8498,7 +8499,7 @@ func (c *Checker) checkImportCallExpression(node *ast.Node) *Type { } } } - importAttributesType = c.getTypeOfPropertyOfType(optionsType, "with") + importAttributesType = c.getTypeOfPropertyOfType(optionsType, unique.Make("with")) } if ast.IsSourcePhaseImportCall(node) { return c.createPromiseReturnType(node, c.getGlobalAbstractModuleSourceType()) @@ -8603,7 +8604,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, unique.Make("Symbol"), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) } /** @@ -10051,7 +10052,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(), unique.Make(node.Expression().Text()), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) if symbol == nil { return false } @@ -11514,7 +11515,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l c.checkExternalEmitHelpers(node, ExternalEmitHelpersClassPrivateFieldGet) } } - lexicallyScopedSymbol := c.lookupSymbolForPrivateIdentifierDeclaration(right.Text(), right) + lexicallyScopedSymbol := c.lookupSymbolForPrivateIdentifierDeclaration(unique.Make(right.Text()), 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()) } @@ -11558,14 +11559,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, unique.Make(right.Text()), 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, unique.Make(right.Text())) } if indexInfo == nil { isUncheckedJS := c.isUncheckedJSSuggestion(node, leftType.symbol, true /*excludeClasses*/) @@ -11573,7 +11574,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()[unique.Make(right.Text())] 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 { @@ -11710,10 +11711,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 @@ -11783,19 +11784,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, unique.Make(propNode.Text())) == nil && c.getApplicableIndexInfoForName(subtype, unique.Make(propNode.Text())) == 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(unique.Make(propNode.Text()), 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, unique.Make(propNode.Text())) != 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 { @@ -11807,7 +11808,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 { @@ -11852,7 +11853,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(unique.Make(name.Text()), slices.Values(props), ast.SymbolFlagsValue) } // Checks if an existing property access is valid for completions purposes. @@ -11899,7 +11900,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 == unique.Make("EventTarget") || name == unique.Make("Node") || name == unique.Make("Element") || strings.HasPrefix(name.Value(), "HTML") && strings.HasSuffix(name.Value(), "Element") } func (c *Checker) checkAndReportErrorForExtendingInterface(errorLocation *ast.Node) bool { @@ -13015,7 +13016,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()), unique.Make(left.Name().Text())) 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 } @@ -13615,7 +13616,7 @@ func (c *Checker) checkDeprecatedProperty(name *ast.Node, contextualType *Type) if contextualType == nil { return } - prop := c.getPropertyOfType(contextualType, name.Text()) + prop := c.getPropertyOfType(contextualType, unique.Make(name.Text())) if prop == nil || len(prop.Declarations()) == 0 { return } @@ -13628,7 +13629,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)) } } @@ -13693,7 +13694,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) @@ -14104,8 +14105,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, unique.Make("value")); valueType != nil { + if writableProp := c.getPropertyOfType(propertyDescriptorType, unique.Make("writable")); writableProp != nil { var writableType *Type if writableProp.ValueDeclaration() != nil && ast.IsPropertyAssignment(writableProp.ValueDeclaration()) { writableType = c.checkExpression(writableProp.ValueDeclaration().Initializer()) @@ -14116,7 +14117,7 @@ func (c *Checker) isReadonlyAssignmentDeclaration(node *ast.Node) bool { } return true } - return c.getTypeOfPropertyOfType(propertyDescriptorType, "set") == nil + return c.getTypeOfPropertyOfType(propertyDescriptorType, unique.Make("set")) == nil } func (c *Checker) isReadonlySymbol(symbol *ast.Symbol) bool { @@ -14165,7 +14166,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, unique.Make(node.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, c.getCannotFindNameDiagnosticForName(node), !ast.IsWriteOnlyAccess(node), false /*excludeGlobals*/) } links.resolvedSymbol = core.OrElse(symbol, c.unknownSymbol) @@ -14182,7 +14183,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, unique.Make(reference.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias, nil, false /*isUse*/, false /*excludeGlobals*/) } func (c *Checker) getCannotFindNameDiagnosticForName(node *ast.Node) *diagnostics.Message { @@ -14340,7 +14341,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) @@ -14356,19 +14357,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 @@ -14809,7 +14810,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, unique.Make(node.Name().Text())) symbol.SetDeclarations(alias.Declarations()) c.valueSymbolLinks.Get(symbol).resolvedType = c.getGlobalAbstractModuleSourceType() links.immediateTarget = symbol @@ -14911,7 +14912,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 { @@ -15000,9 +15001,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), unique.Make(nameText), true /*skipObjectFunctionPropertyAugment*/, false /*includeTypeOnlyMembers*/) } else { - symbolFromVariable = c.getPropertyOfVariable(targetSymbol, nameText) + symbolFromVariable = c.getPropertyOfVariable(targetSymbol, unique.Make(nameText)) } // if symbolFromVariable is export - get its final target symbolFromVariable = c.resolveSymbolEx(symbolFromVariable, dontResolveAlias) @@ -15011,8 +15012,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, unique.Make(nameText), specifier, dontResolveAlias) + if symbolFromModule == nil && unique.Make(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) @@ -15028,7 +15029,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) && unique.Make(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) @@ -15039,7 +15040,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 { @@ -15090,7 +15091,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) @@ -15159,7 +15160,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, unique.Make("__esModule"), 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 @@ -15175,7 +15176,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, unique.Make("__esModule"), nil /*sourceNode*/, dontResolveAlias) == nil } func (c *Checker) getEmitSyntaxForModuleSpecifierExpression(usage *ast.Node) core.ResolutionMode { @@ -15213,7 +15214,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[unique.Make(name.Text())] } exports := moduleSymbol.Exports() if localSymbol != nil { @@ -15796,8 +15797,8 @@ func (c *Checker) tryResolvePatternAmbientModule(resolvedSymbol *ast.Symbol, mod }) if len(candidates) > 0 { - augmentation := c.patternAmbientModuleAugmentations[moduleReference] - augmentationTarget := c.patternAmbientModuleAugmentationTargets[moduleReference] + augmentation := c.patternAmbientModuleAugmentations[unique.Make(moduleReference)] + augmentationTarget := c.patternAmbientModuleAugmentationTargets[unique.Make(moduleReference)] if len(candidates) == 1 { mergedCandidate := c.getMergedSymbol(candidates[0].Symbol) @@ -15940,7 +15941,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, unique.Make("\""+moduleName+"\""), ast.SymbolFlagsValueModule) // merged symbol is module declaration symbol combined with all augmentations if withAugmentations { return c.getMergedSymbol(symbol) @@ -16094,7 +16095,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(), unique.Make(node.Expression().Text()), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if resolvedRequire == c.requireSymbol { return true } @@ -16204,19 +16205,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, unique.Make(name.Text()), 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, unique.Make(name.Text()), 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, unique.Make(name.Text()), 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, unique.Make(name.Text()), meaning, message, true /*isUse*/, false /*excludeGlobals*/)) } case ast.KindQualifiedName: qualified := name.AsQualifiedName() @@ -16264,10 +16265,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), unique.Make(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)), unique.Make(text), meaning)) } if symbol == nil { if !ignoreErrors { @@ -16289,7 +16290,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), unique.Make(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()) @@ -16305,14 +16306,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, unique.Make(id.Text()), 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, unique.Make(n.Parent.AsQualifiedName().Right.Text())) if symbol == nil { return nil } @@ -16322,7 +16323,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(unique.Make(name.Text()), maps.Values(c.getExportsOfModule(targetModule)), ast.SymbolFlagsModuleMember) } func (c *Checker) getFullyQualifiedName(symbol *ast.Symbol, containingLocation *ast.Node) string { @@ -16458,12 +16459,12 @@ func (c *Checker) lateBindMember(parent *ast.Symbol, earlySymbols ast.SymbolTabl } name := memberName if t.flags&TypeFlagsUniqueESSymbol != 0 { - name = scanner.DeclarationNameToString(declName) + name = unique.Make(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) } @@ -16558,11 +16559,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 @@ -16596,14 +16597,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 @@ -16739,7 +16740,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 { @@ -17013,7 +17014,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() == unique.Make("exports") { return c.getTypeOfSymbol(c.resolveExternalModuleSymbol(symbol.ValueDeclaration().Symbol(), false /*dontResolveAlias*/)) } return c.newAnonymousType(symbol, symbol.Members(), nil, nil, nil) @@ -17263,7 +17264,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) @@ -18297,7 +18298,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) { @@ -18608,15 +18609,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, unique.Make("value")); valueType != nil { return valueType } - if getFunc := c.getTypeOfPropertyOfType(objectLiteralType, "get"); getFunc != nil { + if getFunc := c.getTypeOfPropertyOfType(objectLiteralType, unique.Make("get")); 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, unique.Make("set")); setFunc != nil { if setSig := c.getSingleCallSignature(setFunc); setSig != nil { return c.getTypeOfFirstParameterOfSignature(setSig) } @@ -18730,7 +18731,7 @@ func (c *Checker) reportImplicitAny(declaration *ast.Node, t *Type, wideningKind originalKeywordKind := scanner.IdentifierToKeywordKind(name) if (ast.IsCallSignatureDeclaration(declaration.Parent) || ast.IsMethodSignatureDeclaration(declaration.Parent) || ast.IsFunctionTypeNode(declaration.Parent)) && slices.Contains(declaration.Parent.Parameters(), declaration) && - (ast.IsTypeNodeKind(originalKeywordKind) || c.resolveName(declaration, name.Text, ast.SymbolFlagsType, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) != nil) { + (ast.IsTypeNodeKind(originalKeywordKind) || c.resolveName(declaration, unique.Make(name.Text), ast.SymbolFlagsType, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) != nil) { newName := fmt.Sprintf("arg%v", slices.Index(declaration.Parent.Parameters(), declaration)) typeName := scanner.DeclarationNameToString(param.Name()) + core.IfElse(param.DotDotDotToken != nil, "[]", "") c.errorOrSuggestion(c.noImplicitAny, declaration, diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName) @@ -18890,13 +18891,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 @@ -18904,7 +18905,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) { @@ -19143,7 +19144,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: @@ -19159,21 +19160,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 unique.Make(s), true case t.flags&TypeFlagsNumberLiteral != 0: s := getNumberLiteralValue(t).String() - return s, true + return unique.Make(s), true default: - return "", false + return ast.EmptySymbolName, false } } @@ -19331,7 +19332,7 @@ func (c *Checker) getLazyStateOfType(t *Type) *LazyState { 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) { @@ -19354,7 +19355,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*/) } @@ -19366,7 +19367,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: @@ -19418,7 +19419,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) @@ -19482,11 +19483,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 { - if isLateBoundName(name) { +func (c *Checker) getApplicableIndexInfoForName(t *Type, name ast.SymbolName) *IndexInfo { + if isLateBoundName(name.Value()) { 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 { @@ -19662,7 +19663,7 @@ func (c *Checker) createMemberLayout(t *Type, baseTypes []*Type) *MemberLayout { addMember := func(symbol *ast.Symbol, baseIndex int) { if _, ok := layoutMemberInfos[symbol.Name()]; !ok { if layoutMemberInfos == nil { - layoutMemberInfos = make(map[string]MemberInfo) + layoutMemberInfos = make(map[ast.SymbolName]MemberInfo) } layoutMemberInfos[symbol.Name()] = MemberInfo{symbol: symbol, baseIndex: int32(baseIndex)} } @@ -19705,7 +19706,7 @@ func (c *Checker) createMemberLayout(t *Type, baseTypes []*Type) *MemberLayout { }) // Store slot indices in the sorted memberInfos and build the memberInfoMap. Slot indices are used to // identify slots in the instantiated type's properties list. - memberInfoMap := make(map[string]*MemberInfo, len(memberInfos)) + memberInfoMap := make(map[ast.SymbolName]*MemberInfo, len(memberInfos)) for i := range memberInfos { memberInfo := &memberInfos[i] memberInfo.slotIndex = int32(i) @@ -20314,7 +20315,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 { @@ -21140,7 +21141,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, unique.Make(param.Name().Text()), int32(i), trueType) } } return nil @@ -21639,7 +21640,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 @@ -21832,7 +21833,7 @@ func (c *Checker) combineUnionOrIntersectionParameters(left *Signature, right *S if paramName == "" { paramName = "arg" + strconv.Itoa(i) } - paramSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable|core.IfElse(isOptional && !isRestParam, ast.SymbolFlagsOptional, 0), paramName, + paramSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable|core.IfElse(isOptional && !isRestParam, ast.SymbolFlagsOptional, 0), unique.Make(paramName), core.IfElse(isRestParam, ast.CheckFlagsRestParameter, core.IfElse(isOptional, ast.CheckFlagsOptionalParameter, 0))) links := c.valueSymbolLinks.Get(paramSymbol) if isRestParam { @@ -21843,7 +21844,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, unique.Make("args"), ast.CheckFlagsRestParameter) links := c.valueSymbolLinks.Get(restParamSymbol) links.resolvedType = c.createArrayType(c.getTypeAtPosition(shorter, longestCount)) if shorter == right { @@ -21969,7 +21970,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.getMember(name) @@ -21980,7 +21981,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 { @@ -21994,7 +21995,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) @@ -22018,7 +22019,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] @@ -22102,7 +22103,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name s } } else if isUnion { var indexInfo *IndexInfo - if !isLateBoundName(name) { + if !isLateBoundName(name.Value()) { indexInfo = c.getApplicableIndexInfoForName(t, name) } if indexInfo != nil { @@ -22709,8 +22710,8 @@ func (c *Checker) isDeclarationContainedBy(symbol *ast.Symbol, container *ast.Sy return false } -func (c *Checker) isNamedMember(symbol *ast.Symbol, id string) bool { - return !isReservedMemberName(id) && c.symbolIsValue(symbol) +func (c *Checker) isNamedMember(symbol *ast.Symbol, id ast.SymbolName) bool { + return !isReservedMemberName(id.Value()) && c.symbolIsValue(symbol) } func (c *Checker) symbolIsValue(symbol *ast.Symbol) bool { @@ -22787,7 +22788,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) } @@ -23642,10 +23643,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, unique.Make(b.String())) c.uniqueESSymbolTypes[symbol] = uniqueType } return uniqueType @@ -23814,10 +23815,10 @@ func (c *Checker) getUnresolvedSymbolForEntityName(name *ast.Node) *ast.Symbol { } else { path = text } - result := c.unresolvedSymbols[path] + result := c.unresolvedSymbols[unique.Make(path)] if result == nil { - result = c.newSymbolEx(ast.SymbolFlagsTypeAlias, text, ast.CheckFlagsUnresolved) - c.unresolvedSymbols[path] = result + result = c.newSymbolEx(ast.SymbolFlagsTypeAlias, unique.Make(text), ast.CheckFlagsUnresolved) + c.unresolvedSymbols[unique.Make(path)] = result result.SetParent(parentSymbol) c.typeAliasLinks.Get(result).declaredType = c.unresolvedType } @@ -23828,9 +23829,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 { @@ -24232,11 +24233,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, unique.Make("0")) != nil { return true } if c.isArrayLikeType(t) { - if lengthType := c.getTypeOfPropertyOfType(t, "length"); lengthType != nil { + if lengthType := c.getTypeOfPropertyOfType(t, unique.Make("length")); lengthType != nil { return everyType(lengthType, func(t *Type) bool { return t.flags&TypeFlagsNumberLiteral != 0 }) } } @@ -24252,7 +24253,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, unique.Make(strconv.Itoa(index))) if propType != nil { return propType } @@ -24554,7 +24555,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() == unique.Make("BuiltinIteratorReturn") { t = c.getBuiltinIteratorReturnType() } } else { @@ -24729,7 +24730,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(unique.Make(expr.Text()), 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. @@ -24760,7 +24761,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()[unique.Make(name)] if member != nil { if location != nil { return c.evaluateEnumMember(expr, member, location) @@ -25306,9 +25307,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), unique.Make(current.Text()), false /*skipObjectFunctionPropertyAugment*/, true /*includeTypeOnlyMembers*/) } else { - symbolFromModule = c.getSymbol(c.getExportsOfSymbol(mergedResolvedSymbol), current.Text(), meaning) + symbolFromModule = c.getSymbol(c.getExportsOfSymbol(mergedResolvedSymbol), unique.Make(current.Text()), meaning) if symbolFromModule == nil { // a CommonJS module might have typedefs exported alongside an export= // !!! @@ -25316,7 +25317,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()), unique.Make(current.Text()), meaning) } } } @@ -25372,7 +25373,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*/) } @@ -25382,9 +25383,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, unique.Make("ImportMetaExpression")) importMetaType := c.getGlobalImportMetaType() - metaPropertySymbol := c.newSymbolEx(ast.SymbolFlagsProperty, "meta", ast.CheckFlagsReadonly) + metaPropertySymbol := c.newSymbolEx(ast.SymbolFlagsProperty, unique.Make("meta"), ast.CheckFlagsReadonly) metaPropertySymbol.SetParent(symbol) c.valueSymbolLinks.Get(metaPropertySymbol).resolvedType = importMetaType members := createSymbolTable([]*ast.Symbol{metaPropertySymbol}) @@ -25488,7 +25489,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), unique.Make(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 @@ -25496,7 +25497,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, unique.Make("length"), core.IfElse(readonly, ast.CheckFlagsReadonly, 0)) if combinedFlags&ElementFlagsVariable != 0 { c.valueSymbolLinks.Get(lengthSymbol).resolvedType = c.numberType } else { @@ -25751,7 +25752,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) @@ -27488,7 +27489,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)) } } } @@ -27511,7 +27512,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)) @@ -27736,7 +27737,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) @@ -27761,7 +27762,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)) @@ -27791,8 +27792,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 { @@ -27802,9 +27803,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 { @@ -27876,11 +27877,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 { @@ -27889,7 +27890,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 != "" { @@ -27945,7 +27946,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()) @@ -27953,10 +27954,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 "" } @@ -27964,7 +27965,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, unique.Make(name)) if prop != nil { s := c.getSingleCallSignature(c.getTypeOfSymbol(prop)) return s != nil && c.getMinArgumentCount(s) >= 1 && c.isTypeAssignableTo(keyedType, c.getTypeAtPosition(s, 0)) @@ -28085,7 +28086,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) } @@ -28115,8 +28116,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) } } @@ -28476,7 +28477,7 @@ func (c *Checker) expandSignatureParametersWithTupleMembers(signature *Signature case flags&ElementFlagsOptional != 0: checkFlags = ast.CheckFlagsOptionalParameter } - symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, associatedNames[i], checkFlags) + symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, unique.Make(associatedNames[i]), checkFlags) links := c.valueSymbolLinks.Get(symbol) if flags&ElementFlagsRest != 0 { links.resolvedType = c.createArrayType(t) @@ -29202,7 +29203,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(unique.Make(right.Text()), right) } assignmentKind := getAssignmentTargetKind(location) var apparentType *Type @@ -29216,7 +29217,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, unique.Make(right.Text())) } } if !(prop != nil && (isConstEnumOrConstEnumOnlyModule(prop) || prop.Flags()&ast.SymbolFlagsEnumMember != 0 && location.Parent.Kind == ast.KindEnumMember)) { @@ -29267,7 +29268,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, unique.Make(jsxFactoryNamespace), flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) } if jsxFactorySym != nil { // Mark local symbol as referenced here because it might not have been marked @@ -29288,7 +29289,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, unique.Make(localJsxNamespace), flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) } } } @@ -29305,7 +29306,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, unique.Make(exportedName.Text()), 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 { @@ -29341,7 +29342,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), unique.Make(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 { @@ -29613,7 +29614,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, unique.Make(rootName.Text()), meaning, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if rootSymbol != nil && rootSymbol.Flags()&ast.SymbolFlagsAlias != 0 { if c.canCollectSymbolAliasAccessibilityData && @@ -29699,7 +29700,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, unique.Make("then")) // TODO: GH#18217 if IsTypeAny(thenFunction) { return nil @@ -30082,7 +30083,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 @@ -30631,7 +30632,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), unique.Make(left.Name().Text())) } nameType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) if isTypeUsableAsPropertyName(nameType) { @@ -30656,7 +30657,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, unique.Make(name.Text())) } } else { propType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) @@ -30781,7 +30782,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, unique.Make(strconv.Itoa(index))) if propType != nil { return propType } @@ -30807,7 +30808,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(), unique.Make(node.Name().Text())) } // Returns the effective arguments for an expression that works like a function invocation. @@ -30941,7 +30942,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(unique.Make("target"), 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)) { @@ -30964,9 +30965,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(unique.Make("target"), targetType) + keyParam := c.newParameter(unique.Make("propertyKey"), keyType) + indexParam := c.newParameter(unique.Make("parameterIndex"), 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) { @@ -30975,9 +30976,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(unique.Make("target"), targetType) keyType := c.getClassElementPropertyKeyType(node) - keyParam := c.newParameter("propertyKey", keyType) + keyParam := c.newParameter(unique.Make("propertyKey"), keyType) returnType := c.voidType if !ast.IsPropertyDeclaration(node) { returnType = c.newTypedPropertyDescriptorType(c.getTypeOfNode(node)) @@ -30985,7 +30986,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(unique.Make("descriptor"), 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})) @@ -31213,9 +31214,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[unique.Make("name")] = c.newProperty(unique.Make("name"), nameType) + members[unique.Make("private")] = c.newProperty(unique.Make("private"), core.IfElse(isPrivate, c.trueType, c.falseType)) + members[unique.Make("static")] = c.newProperty(unique.Make("static"), core.IfElse(isStatic, c.trueType, c.falseType)) overrideType := c.newAnonymousType(nil, members, nil, nil, nil) c.cachedTypes[key] = overrideType return overrideType @@ -31258,16 +31259,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(unique.Make("this"), thisType) + valueParam := c.newParameter(unique.Make("value"), 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(unique.Make("target"), targetType) + contextParam := c.newParameter(unique.Make("context"), contextType) returnType := c.getUnionType([]*Type{nonOptionalReturnType, c.voidType}) return c.newCallSignature(nil, nil /*thisParameter*/, []*ast.Symbol{targetParam, contextParam}, returnType) } @@ -31283,7 +31284,7 @@ func (c *Checker) newGetterFunctionType(t *Type) *Type { } func (c *Checker) newSetterFunctionType(t *Type) *Type { - valueParam := c.newParameter("value", t) + valueParam := c.newParameter(unique.Make("value"), t) return c.newFunctionType(nil, nil /*thisParameter*/, []*ast.Symbol{valueParam}, c.voidType) } @@ -31320,11 +31321,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 @@ -31376,10 +31377,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 @@ -31407,7 +31408,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 @@ -31415,15 +31416,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 { @@ -31492,7 +31493,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() } @@ -31556,7 +31557,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()) }) @@ -31916,7 +31917,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.getMember("bind") != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) + return len(resolved.getSignatures()) != 0 || resolved.getMember(unique.Make("bind")) != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) } func (c *Checker) getTypeWithFacts(t *Type, include TypeFacts) *Type { @@ -32223,7 +32224,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, unique.Make("then")) return thenFunction != nil && len(c.getSignaturesOfType(c.getTypeWithFacts(thenFunction, TypeFactsNEUndefinedOrNull), SignatureKindCall)) != 0 } @@ -32398,7 +32399,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, unique.Make(node.Text())); propertyDeclaration != nil { return propertyDeclaration } } else if ast.IsMetaProperty(parent) && parent.Name() == node { @@ -32412,7 +32413,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().getMember("meta") + return c.getGlobalImportMetaExpressionType().AsObjectType().getMember(unique.Make("meta")) } // no other meta properties are valid syntax, thus no others should have symbols return nil @@ -32483,7 +32484,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, unique.Make(node.Text())) } return nil case ast.KindDefaultKeyword, ast.KindFunctionKeyword, ast.KindEqualsGreaterThanToken, ast.KindClassKeyword: @@ -32635,8 +32636,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), unique.Make(name.Text()), meaning)); result == nil { + result = c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), unique.Make(name.Text())) } } } @@ -32911,7 +32912,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 unique.Make(node.Text()) == 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..34f13c2ce0560 100644 --- a/tsc/internal/checker/emitresolver.go +++ b/tsc/internal/checker/emitresolver.go @@ -4,6 +4,7 @@ import ( "maps" "slices" "sync" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -172,7 +173,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, unique.Make(node.Text()), 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 +194,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, unique.Make(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) nextSymbol = importSymbol } } @@ -298,7 +299,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(unique.Make("Symbol"), 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 @@ -607,13 +608,13 @@ func (r *EmitResolver) IsNameResolvable(location *ast.Node, name string) bool { r.checkerMu.Lock() defer r.checkerMu.Unlock() - symbol := r.checker.resolveName(location, name, ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) + symbol := r.checker.resolveName(location, unique.Make(name), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) 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 +792,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, unique.Make(firstIdentifier.Text()), 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..0338a6b232675 100644 --- a/tsc/internal/checker/emitsupport.go +++ b/tsc/internal/checker/emitsupport.go @@ -3,6 +3,7 @@ package checker import ( "maps" "slices" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -164,7 +165,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, unique.Make(firstIdentifier.Text()), 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 bce0ba48cfa20..ad871474f6610 100644 --- a/tsc/internal/checker/exports.go +++ b/tsc/internal/checker/exports.go @@ -95,11 +95,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) } @@ -155,7 +155,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) } @@ -175,7 +175,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) } @@ -276,7 +276,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) } @@ -308,7 +308,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..a6c93ba15c2f2 100644 --- a/tsc/internal/checker/flow.go +++ b/tsc/internal/checker/flow.go @@ -5,6 +5,7 @@ import ( "slices" "strconv" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -458,7 +459,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 == unique.Make(argument.Text()) { return c.getTypeWithFacts(t, core.IfElse(assumeTrue, TypeFactsNEUndefined, TypeFactsEQUndefined)) } } @@ -702,7 +703,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 +769,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, unique.Make("prototype")) if prototypeProperty == nil { return t } @@ -882,14 +883,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 +965,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, unique.Make("prototype")) if prototypePropertyType != nil && !IsTypeAny(prototypePropertyType) { return prototypePropertyType } @@ -1021,7 +1022,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 +1232,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 +1640,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 unique.Make(source.AsQualifiedName().Right.Text()) == targetPropertyName && c.isMatchingReference(source.AsQualifiedName().Left, target.Expression()) } } case ast.KindBinaryExpression: @@ -1700,7 +1701,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 +1725,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 unique.Make(access.Name().Text()), true } if ast.IsElementAccessExpression(access) { return c.tryGetElementAccessExpressionName(access.AsElementAccessExpression()) @@ -1735,29 +1736,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 unique.Make(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 unique.Make(node.ArgumentExpression.Text()), 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 +1774,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 unique.Make(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 unique.Make(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 +1800,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 unique.Make(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 unique.Make(evaluator.AnyToString(t.AsLiteralType().value)), true } - return "", false + return ast.EmptySymbolName, false } func (c *Checker) isConstantReference(node *ast.Node) bool { @@ -2091,7 +2093,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(unique.Make("hasInstance")) if c.allTypesAssignableToKind(t, TypeFlagsNonPrimitive) { hasInstanceProperty := c.getPropertyOfType(t, hasInstancePropertyName) if hasInstanceProperty != nil { @@ -2104,7 +2106,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 +2114,7 @@ func (c *Checker) getPropertyNameForKnownSymbolName(symbolName string) string { return getPropertyNameFromType(uniqueType) } } - return ast.InternalSymbolNamePrefix + "@" + symbolName + return unique.Make(ast.InternalSymbolNamePrefix + "@" + symbolName.Value()) } // We require the dotted function name in an assertion expression to be comprised of identifiers @@ -2139,7 +2141,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, unique.Make(name.Text())) } if prop != nil { return c.getExplicitTypeOfSymbol(prop, diagnostic) @@ -2465,10 +2467,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 +2490,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..9198a55c3b736 100644 --- a/tsc/internal/checker/grammarchecks.go +++ b/tsc/internal/checker/grammarchecks.go @@ -1111,9 +1111,9 @@ func (c *Checker) checkGrammarObjectLiteralExpression(node *ast.ObjectLiteralExp continue } - existingKind := seen[effectiveName] + existingKind := seen[effectiveName.Value()] if existingKind == 0 { - seen[effectiveName] = currentKind + seen[effectiveName.Value()] = currentKind } else { if (currentKind&DeclarationMeaningMethod != 0) && (existingKind&DeclarationMeaningMethod != 0) { c.grammarErrorOnNode(name, diagnostics.Duplicate_identifier_0, scanner.GetTextOfNode(name)) @@ -1121,7 +1121,7 @@ func (c *Checker) checkGrammarObjectLiteralExpression(node *ast.ObjectLiteralExp c.grammarErrorOnNode(name, diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name, scanner.GetTextOfNode(name)) } else if (currentKind&DeclarationMeaningGetOrSetAccessor != 0) && (existingKind&DeclarationMeaningGetOrSetAccessor != 0) { if existingKind != DeclarationMeaningGetOrSetAccessor && currentKind != existingKind { - seen[effectiveName] = currentKind | existingKind + seen[effectiveName.Value()] = currentKind | existingKind } else { return c.grammarErrorOnNode(name, diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name) } diff --git a/tsc/internal/checker/inference.go b/tsc/internal/checker/inference.go index 02c7d009b9ec5..e148d1b7ef91c 100644 --- a/tsc/internal/checker/inference.go +++ b/tsc/internal/checker/inference.go @@ -2,6 +2,7 @@ package checker import ( "slices" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -1244,13 +1245,13 @@ func (c *Checker) createEmptyObjectTypeFromStringLiteral(t *Type) *Type { continue } name := getStringLiteralValue(t) - literalProp := c.newSymbol(ast.SymbolFlagsProperty, name) + literalProp := c.newSymbol(ast.SymbolFlagsProperty, unique.Make(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[unique.Make(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..2563d004874cc 100644 --- a/tsc/internal/checker/jsx.go +++ b/tsc/internal/checker/jsx.go @@ -4,6 +4,7 @@ import ( "iter" "math" "slices" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -40,27 +41,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: unique.Make("JSX"), + IntrinsicElements: unique.Make("IntrinsicElements"), + ElementClass: unique.Make("ElementClass"), + ElementAttributesPropertyNameContainer: unique.Make("ElementAttributesProperty"), + ElementChildrenAttributeNameContainer: unique.Make("ElementChildrenAttribute"), + Element: unique.Make("Element"), + ElementType: unique.Make("ElementType"), + IntrinsicAttributes: unique.Make("IntrinsicAttributes"), + IntrinsicClassAttributes: unique.Make("IntrinsicClassAttributes"), + LibraryManagedAttributes: unique.Make("LibraryManagedAttributes"), } var ReactNames = struct { @@ -221,7 +222,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, unique.Make(attribute.Name().Text())) } return c.getContextualType(attribute.Parent, contextFlags) } @@ -243,7 +244,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 +308,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 = unique.Make("children") } - 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 +334,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 +345,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 +358,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 +483,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 unique.Make("for"): + jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return x.Name() == unique.Make("htmlFor") }) + case unique.Make("class"): + jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return x.Name() == unique.Make("className") }) } if jsxSpecific != nil { return jsxSpecific @@ -517,13 +518,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, unique.Make(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() == unique.Make(ReactNames.Fragment) { links.jsxFragmentType = c.getTypeOfSymbol(jsxFactorySymbol) return links.jsxFragmentType } @@ -533,7 +534,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, unique.Make(ReactNames.Fragment), ast.SymbolFlagsBlockScopedVariable) if typeSymbol != nil { links.jsxFragmentType = c.getTypeOfSymbol(typeSymbol) } else { @@ -754,7 +755,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme if allAttributesTable != nil { allAttributesTable[attributeSymbol.Name()] = attributeSymbol } - if attributeDecl.Name().Text() == jsxChildrenPropertyName { + if unique.Make(attributeDecl.Name().Text()) == jsxChildrenPropertyName { explicitlySpecifyChildrenAttribute = true } if contextualType != nil && checkMode&CheckModeInferential != 0 && checkMode&CheckModeSkipContextSensitive == 0 && c.isContextSensitive(attributeDecl) { @@ -818,12 +819,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 +844,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 +901,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 +947,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) + attributesType = c.getJsxPropsTypeForSignatureFromMember(sig, forcedLookupLocation.Value()) 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 { @@ -999,7 +1000,7 @@ func (c *Checker) getJsxPropsTypeForSignatureFromMember(sig *Signature, forcedLo if IsTypeAny(instance) { return instance } - propType := c.getTypeOfPropertyOfType(instance, forcedLookupLocation) + propType := c.getTypeOfPropertyOfType(instance, unique.Make(forcedLookupLocation)) if propType == nil { return nil } @@ -1012,7 +1013,7 @@ func (c *Checker) getJsxPropsTypeForSignatureFromMember(sig *Signature, forcedLo if IsTypeAny(instanceType) { return instanceType } - return c.getTypeOfPropertyOfType(instanceType, forcedLookupLocation) + return c.getTypeOfPropertyOfType(instanceType, unique.Make(forcedLookupLocation)) } func (c *Checker) getJsxManagedAttributesFromLocatedAttributes(context *ast.Node, ns *ast.Symbol, attributesType *Type) *Type { @@ -1070,14 +1071,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 unique.Make("children") } return c.getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace) } @@ -1088,7 +1089,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 +1098,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 +1141,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, unique.Make(stringLiteralTypeName)) if intrinsicProp != nil { return c.getTypeOfSymbol(intrinsicProp) } @@ -1177,7 +1178,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, unique.Make("props")) c.valueSymbolLinks.Get(parameterSymbol).resolvedType = result return c.newSignature(SignatureFlagsNone, nil, nil, nil, []*ast.Symbol{parameterSymbol}, elementType, nil, 1) } @@ -1197,7 +1198,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), unique.Make(node.TagName().Text())) if indexInfo != nil { links.resolvedJsxElementAttributesType = indexInfo.valueType return links.resolvedJsxElementAttributesType @@ -1224,7 +1225,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, unique.Make(propName)) if intrinsicProp != nil { c.jsxElementLinks.Get(node).jsxFlags |= JsxFlagsIntrinsicNamedElement links.resolvedSymbol = intrinsicProp @@ -1237,18 +1238,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, unique.Make(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 +1291,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 +1314,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, unique.Make(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 7bf066a03485f..a105f5f200f8b 100644 --- a/tsc/internal/checker/nodebuilder_hover.go +++ b/tsc/internal/checker/nodebuilder_hover.go @@ -2,6 +2,7 @@ package checker import ( "fmt" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -50,7 +51,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 +62,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 +72,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 +110,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 +153,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() != unique.Make("prototype") && !b.isNamespaceMember(p) }) var staticMembers []*ast.Node staticMembers = b.serializePropertiesWithTruncation(staticProps, staticMembers) @@ -232,7 +233,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 +419,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 +458,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 +493,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 +501,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 +574,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 +598,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() == unique.Make("prototype") || (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 45f8ddc00dcf2..87e56f9972fb8 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -5,6 +5,7 @@ import ( "maps" "slices" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -90,8 +91,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 +384,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 +411,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(unique.Make(typeNode.AsTypeReferenceNode().TypeName.Text()), seenName{t, len(result) - 1}) } } } @@ -641,7 +642,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 +702,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()) } } @@ -774,13 +775,13 @@ func (b *NodeBuilderImpl) createAccessFromSymbolChain(chain []*ast.Symbol, index if exports != nil { // 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() + if symbol.Name() != ast.InternalSymbolNameExportEquals && !isLateBoundName(symbol.Name().Value()) && ok && res != nil && b.ch.getSymbolIfSameReference(res, symbol) != nil { + symbolName = symbol.Name().Value() } else { results := make(map[*ast.Symbol]string, 1) for name, ex := range exports { - if b.ch.getSymbolIfSameReference(ex, symbol) != nil && !isLateBoundName(name) && name != ast.InternalSymbolNameExportEquals { - results[ex] = name + if b.ch.getSymbolIfSameReference(ex, symbol) != nil && !isLateBoundName(name.Value()) && name != ast.InternalSymbolNameExportEquals { + results[ex] = name.Value() // break // must collect all results and sort them - exports are randomly iterated } } @@ -1380,7 +1381,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 +1397,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 +1480,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 @@ -1505,11 +1506,11 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi } if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 { rawText := result.Text() - i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(rawText) + i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(unique.Make(rawText)) text := rawText for true { - if !b.ctx.typeParameterNamesByText.Has(text) && !b.typeParameterShadowsOtherTypeParameterInScope(text, typeParameter) { + if !b.ctx.typeParameterNamesByText.Has(unique.Make(text)) && !b.typeParameterShadowsOtherTypeParameterInScope(unique.Make(text), typeParameter) { break } i++ @@ -1525,9 +1526,9 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi // 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(unique.Make(rawText), i) b.ctx.typeParameterNames.Set(typeParameter.id, result.AsIdentifier()) - b.ctx.typeParameterNamesByText.Add(text) + b.ctx.typeParameterNamesByText.Add(unique.Make(text)) } return result.AsIdentifier() @@ -1568,7 +1569,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, unique.Make("T")), ) name := b.typeParameterToName(newConstraintParam) target := t.Target() @@ -1583,7 +1584,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, unique.Make("T")), ) name := b.typeParameterToName(newParam) newTypeVariable = b.f.NewTypeReferenceNode(name.AsNode(), nil) @@ -1664,7 +1665,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 +1771,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 +1858,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() @@ -2060,7 +2061,7 @@ func (c *Checker) getExpandedParameters(sig *Signature, skipUnionExpanding bool) case flags&ElementFlagsOptional != 0: checkFlags = ast.CheckFlagsOptionalParameter } - symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, name, checkFlags) + symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, unique.Make(name), checkFlags) links := c.valueSymbolLinks.Get(symbol) if flags&ElementFlagsRest != 0 { links.resolvedType = c.createArrayType(t) @@ -2449,12 +2450,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, unique.Make(firstIdentifier.Text()), 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, unique.Make(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) if fallback != nil { b.ctx.tracker.TrackSymbol(fallback, enclosingDeclaration, ast.SymbolFlagsValue) } @@ -2527,7 +2528,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# @@ -2601,7 +2602,7 @@ func (b *NodeBuilderImpl) addPropertyToElementList(propertySymbol *ast.Symbol, t } saveEnclosingDeclaration := b.ctx.enclosingDeclaration b.ctx.enclosingDeclaration = nil - if isLateBoundName(propertySymbol.Name()) { + if isLateBoundName(propertySymbol.Name().Value()) { if len(propertySymbol.Declarations()) > 0 { decl := propertySymbol.Declarations()[0] if b.ch.hasLateBindableName(decl) { @@ -2627,7 +2628,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 +2669,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, unique.Make("arg")) 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 +2775,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 +2872,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 +3044,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, unique.Make("T") /* as __String */)) name := b.typeParameterToName(newParam) newTypeVariable := b.f.NewTypeReferenceNode(name.AsNode(), nil) b.ctx.approximateLength += 37 @@ -3433,7 +3434,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*/)) } @@ -3531,7 +3532,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { if !b.shouldExpandType(t, true /*isAlias*/) { sym := t.alias.Symbol() typeArgumentNodes := b.mapToTypeNodes(t.alias.TypeArguments(), false /*isBareList*/) - if isReservedMemberName(sym.Name()) && sym.Flags()&ast.SymbolFlagsClass == 0 { + if isReservedMemberName(sym.Name().Value()) && sym.Flags()&ast.SymbolFlagsClass == 0 { return b.f.NewTypeReferenceNode(b.f.NewIdentifier(""), typeArgumentNodes) } if typeArgumentNodes != nil && len(typeArgumentNodes.Nodes) == 1 && sym == b.ch.globalArrayType.symbol { @@ -3572,7 +3573,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 { @@ -3599,7 +3600,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 +3681,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(unique.Make("NoInfer"), 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..60fd7b3fb086a 100644 --- a/tsc/internal/checker/nodebuilderscopes.go +++ b/tsc/internal/checker/nodebuilderscopes.go @@ -1,6 +1,8 @@ package checker import ( + "unique" + "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/debug" @@ -33,7 +35,7 @@ func cloneNodeBuilderContext(context *NodeBuilderContext) func() { } type localsRecord struct { - name string + name ast.SymbolName oldSymbol *ast.Symbol } @@ -94,7 +96,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 +123,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 +165,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 +223,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 } @@ -230,7 +232,7 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] continue } typeParamName := b.typeParameterToName(typeParam).Text - add(typeParamName, typeParam.symbol) + add(unique.Make(typeParamName), typeParam.symbol) } }) } diff --git a/tsc/internal/checker/pseudotypenodebuilder.go b/tsc/internal/checker/pseudotypenodebuilder.go index 8f1e2bf1700e1..6f699740430a1 100644 --- a/tsc/internal/checker/pseudotypenodebuilder.go +++ b/tsc/internal/checker/pseudotypenodebuilder.go @@ -1,6 +1,8 @@ package checker import ( + "unique" + "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/debug" "github.com/microsoft/TypeScript/tsc/internal/nodebuilder" @@ -665,7 +667,7 @@ func (b *NodeBuilderImpl) pseudoReturnTypeMatchesPredicate(rt *pseudochecker.Pse } // For identifier predicates, check parameter name matches if !isThis { - if tp.ParameterName.Text() != predicate.parameterName { + if unique.Make(tp.ParameterName.Text()) != predicate.parameterName { return false } } diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index 007fba2511a13..20d8809d97a3d 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -4,6 +4,7 @@ import ( "slices" "strconv" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -531,7 +532,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, unique.Make(jsnum.Number(i).String())) == nil { continue } nameType := c.getNumberLiteralType(jsnum.Number(i)) @@ -583,7 +584,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 +605,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 +667,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, unique.Make("then")) == 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,15 +716,15 @@ 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 // we should remove this exception. if c.getPropertyOfObjectType(targetType, name) != nil || c.getApplicableIndexInfoForName(targetType, name) != nil || - isLateBoundName(name) && c.getIndexInfoOfType(targetType, c.stringType) != nil || - isComparingJsxAttributes && isHyphenatedJsxName(name) { + isLateBoundName(name.Value()) && c.getIndexInfoOfType(targetType, c.stringType) != nil || + isComparingJsxAttributes && isHyphenatedJsxName(name.Value()) { // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true } @@ -1007,7 +1009,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 } @@ -1039,7 +1041,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() } @@ -1079,7 +1081,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 { @@ -1097,7 +1099,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) @@ -1109,19 +1111,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 == (ast.SymbolName{}) { 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)] @@ -1131,13 +1133,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) @@ -1151,7 +1153,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) { @@ -1161,14 +1163,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 { @@ -1200,7 +1202,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 } @@ -1685,7 +1687,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 @@ -1964,7 +1966,7 @@ func (c *Checker) isInstantiatedGenericParameter(signature *Signature, pos int) func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) string { paramCount := len(signature.parameters) - core.IfElse(signatureHasRestParameter(signature), 1, 0) if pos < paramCount { - return signature.parameters[pos].Name() + return signature.parameters[pos].Name().Value() } restParameter := signature.parameters[paramCount] restType := c.getTypeOfSymbol(restParameter) @@ -1972,7 +1974,7 @@ func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) stri index := pos - paramCount return c.getTupleElementLabel(restType.TargetTupleType().elementInfos[index], restParameter, index) } - return restParameter.Name() + return restParameter.Name().Value() } func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol *ast.Symbol, index int) string { @@ -1984,7 +1986,7 @@ func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol } var rootName string if restSymbol != nil { - rootName = restSymbol.Name() + rootName = restSymbol.Name().Value() } else { rootName = "arg" } @@ -2125,12 +2127,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() == unique.Make(name) }) + return c.newTypePredicate(kind, unique.Make(name), int32(index), t) } func (c *Checker) instantiateTypePredicate(predicate *TypePredicate, mapper *TypeMapper) *TypePredicate { @@ -2141,7 +2143,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} } @@ -2787,7 +2789,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(unique.Make(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 { @@ -2806,7 +2808,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(unique.Make(name.Text()), errorTarget) } } if suggestion != "" { @@ -2829,7 +2831,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)) @@ -2837,7 +2839,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 { @@ -2860,7 +2862,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 { @@ -3265,7 +3267,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) } @@ -3277,7 +3279,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 { @@ -3896,7 +3898,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 { @@ -4056,7 +4058,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() @@ -4132,7 +4134,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) } @@ -4233,7 +4235,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(unique.Make(strconv.Itoa(sourcePosition))) { continue } } @@ -4288,7 +4290,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 == unique.Make("length")) && (!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) @@ -4449,7 +4451,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 b20d1798e89be..207dba6664232 100644 --- a/tsc/internal/checker/services.go +++ b/tsc/internal/checker/services.go @@ -4,6 +4,7 @@ import ( "maps" "slices" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -134,8 +135,8 @@ func (c *Checker) GetExportsOfModule(symbol *ast.Symbol) []*ast.Symbol { func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb func(*ast.Symbol, string)) { for key, exportedSymbol := range c.getExportsOfModule(moduleSymbol) { - if !isReservedMemberName(key) { - cb(exportedSymbol, key) + if !isReservedMemberName(key.Value()) { + cb(exportedSymbol, key.Value()) } } @@ -156,16 +157,16 @@ func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb } for name, symbol := range c.resolveStructuredTypeMembers(reducedType).getMembers() { if c.isNamedMember(symbol, name) { - cb(symbol, name) + cb(symbol, name.Value()) } } } -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 +178,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 +293,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 +311,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 +505,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 @@ -589,12 +590,12 @@ 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 } id := token.AsIdentifier() - if id.Text != identifierText { + if unique.Make(id.Text) != identifierText { continue } refSymbol := c.GetSymbolAtLocation(token) @@ -826,11 +827,11 @@ func (c *Checker) IsTypeInvalidDueToUnionDiscriminant(contextualType *Type, obj } var name string if nameType != nil && isTypeUsableAsPropertyName(nameType) { - name = getPropertyNameFromType(nameType) + name = getPropertyNameFromType(nameType).Value() } var expected *Type if name != "" { - expected = c.getTypeOfPropertyOfType(contextualType, name) + expected = c.getTypeOfPropertyOfType(contextualType, unique.Make(name)) } return expected != nil && isLiteralType(expected) && !c.isTypeAssignableTo(c.getTypeOfNode(property), expected) }) @@ -976,30 +977,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{}{ + unique.Make("Array"): {}, + unique.Make("ArrayLike"): {}, + unique.Make("ReadonlyArray"): {}, + unique.Make("Promise"): {}, + unique.Make("PromiseLike"): {}, + unique.Make("Iterable"): {}, + unique.Make("IterableIterator"): {}, + unique.Make("AsyncIterable"): {}, + unique.Make("Set"): {}, + unique.Make("WeakSet"): {}, + unique.Make("ReadonlySet"): {}, + unique.Make("Map"): {}, + unique.Make("WeakMap"): {}, + unique.Make("ReadonlyMap"): {}, + unique.Make("Partial"): {}, + unique.Make("Required"): {}, + unique.Make("Readonly"): {}, + unique.Make("Pick"): {}, + unique.Make("Omit"): {}, + unique.Make("NonNullable"): {}, +} + +func isKnownGenericTypeName(name ast.SymbolName) bool { _, exists := knownGenericTypeNames[name] return exists } @@ -1027,7 +1028,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, unique.Make(name)); symbol != nil { return []*ast.Symbol{symbol} } return nil @@ -1039,17 +1040,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, unique.Make(name)) }) if unionSymbolOk && (len(discriminatedPropertySymbols) == 0 || len(discriminatedPropertySymbols) == len(contextualType.Types())) { - if symbol := c.getPropertyOfType(contextualType, name); symbol != nil { + if symbol := c.getPropertyOfType(contextualType, unique.Make(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, unique.Make(name)) }) } // by eliminating duplicates we might even end up with a single symbol @@ -1070,7 +1071,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, unique.Make(location.Text())) } } return nil diff --git a/tsc/internal/checker/symbolaccessibility.go b/tsc/internal/checker/symbolaccessibility.go index 389980a60ff64..fc4a6beb1afab 100644 --- a/tsc/internal/checker/symbolaccessibility.go +++ b/tsc/internal/checker/symbolaccessibility.go @@ -3,6 +3,7 @@ package checker import ( "cmp" "slices" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -892,7 +893,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{unique.Make(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 f119288a21744..f9d27ab8e0efa 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) @@ -1143,7 +1143,7 @@ func (t *StructuredType) ConstructSignatures() []*Signature { return slices.Clip(t.extra.signatures[t.extra.callSignatureCount:]) } -func (t *StructuredType) getMember(name string) *ast.Symbol { +func (t *StructuredType) getMember(name ast.SymbolName) *ast.Symbol { if t.members != nil { return t.members[name] } @@ -1303,10 +1303,10 @@ type LazyState struct { } type MemberLayout struct { - id uint32 // Unique identifier for the member layout - memberInfoMap map[string]*MemberInfo // MemberInfos keyed by property name - memberInfos []MemberInfo // MemberInfos in sorted order - layoutProperties []*ast.Symbol // Lazily created list of layout properties (symbols corresponding to memberInfos) + id uint32 // Unique identifier for the member layout + memberInfoMap map[ast.SymbolName]*MemberInfo // MemberInfos keyed by property name + memberInfos []MemberInfo // MemberInfos in sorted order + layoutProperties []*ast.Symbol // Lazily created list of layout properties (symbols corresponding to memberInfos) } type MemberInfo struct { @@ -1477,7 +1477,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 } @@ -1757,7 +1757,7 @@ const ( type TypePredicate struct { kind TypePredicateKind parameterIndex int32 - parameterName string + parameterName ast.SymbolName t *Type } @@ -1773,7 +1773,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..b8b7078c7a371 100644 --- a/tsc/internal/checker/types_test.go +++ b/tsc/internal/checker/types_test.go @@ -7,6 +7,7 @@ import ( "strconv" "strings" "testing" + "unique" "unsafe" "github.com/microsoft/TypeScript/tsc/internal/ast" @@ -293,7 +294,7 @@ func TestIntersectionReductionAllocations(t *testing.T) { //nolint:paralleltest c, _ := newCompositeTestChecker() members := make(ast.SymbolTable) for i := range 128 { - name := strconv.Itoa(i) + name := unique.Make(strconv.Itoa(i)) members[name] = c.newSymbol(ast.SymbolFlagsProperty, name) } object := c.newAnonymousType(nil, members, nil, nil, nil) @@ -308,32 +309,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(unique.Make("second"), 1) + outer.Set(unique.Make("first"), 1) + outer.Set(unique.Make("second"), 2) + assert.Assert(t, slices.Equal(slices.Collect(outer.Keys()), []ast.SymbolName{unique.Make("second"), unique.Make("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(unique.Make("first"), 4) + assert.Equal(t, outer.GetOrZero(unique.Make("first")), 1) + assert.Equal(t, outer.GetOrZero(unique.Make("second")), 2) c.releaseTemporaryPropertyCounts(inner) assert.Equal(t, inner.Size(), 0) - assert.Assert(t, !inner.Has("first")) + assert.Assert(t, !inner.Has(unique.Make("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(unique.Make("second"), 3) + reused.Set(unique.Make("first"), 5) + assert.Assert(t, slices.Equal(slices.Collect(reused.Keys()), []ast.SymbolName{unique.Make("second"), unique.Make("first")})) + assert.Equal(t, outer.GetOrZero(unique.Make("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(unique.Make("second"))) for i := range 4097 { - reused.Set(strconv.Itoa(i), i) + reused.Set(unique.Make(strconv.Itoa(i)), i) } c.releaseTemporaryPropertyCounts(reused) for counts := c.freePropertyCounts; counts != nil; counts = counts.next { @@ -348,23 +349,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, unique.Make("value")) + object := c.newAnonymousType(nil, ast.SymbolTable{unique.Make("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, unique.Make("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, unique.Make("value"), ast.CheckFlagsContainsPrivate) + outer.AsUnionOrIntersectionType().propertyCacheWithoutFunctionPropertyAugment[unique.Make("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(unique.Make("value"))) } } @@ -628,7 +629,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, unique.Make("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..7820f34634860 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -5,6 +5,7 @@ import ( "slices" "strings" "sync" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -382,7 +383,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 +646,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 +935,7 @@ func (c *Checker) releaseTemporaryTypeSet(set *temporaryTypeSet) { } type temporaryPropertyCounts struct { - collections.OrderedMap[string, int] + collections.OrderedMap[ast.SymbolName, int] next *temporaryPropertyCounts } @@ -1005,12 +1006,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 unique.Make(t.AsLiteralType().value.(string)) case t.flags&TypeFlagsNumberLiteral != 0: - return t.AsLiteralType().value.(jsnum.Number).String() + return unique.Make(t.AsLiteralType().value.(jsnum.Number).String()) case t.flags&TypeFlagsUniqueESSymbol != 0: return t.AsUniqueESSymbolType().name } @@ -1095,14 +1096,14 @@ func isVariableDeclarationInVariableStatement(node *ast.Node) bool { } func IsKnownSymbol(symbol *ast.Symbol) bool { - return isLateBoundName(symbol.Name()) + return isLateBoundName(symbol.Name().Value()) } 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 { @@ -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{ + unique.Make("Array"): { {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": { + unique.Make("Iterator"): { {lib: "es2015", props: []string{}}, }, - "IteratorConstructor": { + unique.Make("IteratorConstructor"): { {lib: "es2026", props: []string{"concat"}}, }, - "RawJSON": { + unique.Make("RawJSON"): { {lib: "es2026", props: []string{}}, }, - "JSON": { + unique.Make("JSON"): { {lib: "es2026", props: []string{"isRawJSON", "rawJSON"}}, }, - "AsyncIterator": { + unique.Make("AsyncIterator"): { {lib: "es2015", props: []string{}}, }, - "ArrayBuffer": { + unique.Make("ArrayBuffer"): { {lib: "es2024", props: []string{ "maxByteLength", "resizable", @@ -1446,7 +1447,7 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "transferToFixedLength", }}, }, - "Atomics": { + unique.Make("Atomics"): { {lib: "es2017", props: []string{ "add", "and", @@ -1465,7 +1466,7 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "waitAsync", }}, }, - "SharedArrayBuffer": { + unique.Make("SharedArrayBuffer"): { {lib: "es2017", props: []string{ "byteLength", "slice", @@ -1476,59 +1477,59 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "grow", }}, }, - "AsyncIterable": { + unique.Make("AsyncIterable"): { {lib: "es2018", props: []string{}}, }, - "AsyncIterableIterator": { + unique.Make("AsyncIterableIterator"): { {lib: "es2018", props: []string{}}, }, - "AsyncGenerator": { + unique.Make("AsyncGenerator"): { {lib: "es2018", props: []string{}}, }, - "AsyncGeneratorFunction": { + unique.Make("AsyncGeneratorFunction"): { {lib: "es2018", props: []string{}}, }, - "RegExp": { + unique.Make("RegExp"): { {lib: "es2015", props: []string{"flags", "sticky", "unicode"}}, {lib: "es2018", props: []string{"dotAll"}}, {lib: "es2024", props: []string{"unicodeSets"}}, }, - "RegExpConstructor": { + unique.Make("RegExpConstructor"): { {lib: "es2025", props: []string{"escape"}}, }, - "Reflect": { + unique.Make("Reflect"): { {lib: "es2015", props: []string{"apply", "construct", "defineProperty", "deleteProperty", "get", "getOwnPropertyDescriptor", "getPrototypeOf", "has", "isExtensible", "ownKeys", "preventExtensions", "set", "setPrototypeOf"}}, }, - "ArrayConstructor": { + unique.Make("ArrayConstructor"): { {lib: "es2015", props: []string{"from", "of"}}, {lib: "es2026", props: []string{"fromAsync"}}, }, - "ObjectConstructor": { + unique.Make("ObjectConstructor"): { {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": { + unique.Make("NumberConstructor"): { {lib: "es2015", props: []string{"isFinite", "isInteger", "isNaN", "isSafeInteger", "parseFloat", "parseInt"}}, }, - "Math": { + unique.Make("Math"): { {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": { + unique.Make("Map"): { {lib: "es2015", props: []string{"entries", "keys", "values"}}, {lib: "es2026", props: []string{ "getOrInsert", "getOrInsertComputed", }}, }, - "MapConstructor": { + unique.Make("MapConstructor"): { {lib: "es2024", props: []string{"groupBy"}}, }, - "Set": { + unique.Make("Set"): { {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": { + unique.Make("PromiseConstructor"): { {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": { + unique.Make("Symbol"): { {lib: "es2015", props: []string{"for", "keyFor"}}, {lib: "es2019", props: []string{"description"}}, }, - "WeakMap": { + unique.Make("WeakMap"): { {lib: "es2015", props: []string{}}, {lib: "es2026", props: []string{ "getOrInsert", "getOrInsertComputed", }}, }, - "WeakSet": { + unique.Make("WeakSet"): { {lib: "es2015", props: []string{}}, }, - "String": { + unique.Make("String"): { {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": { + unique.Make("StringConstructor"): { {lib: "es2015", props: []string{"fromCodePoint", "raw"}}, }, - "DateTimeFormat": { + unique.Make("DateTimeFormat"): { {lib: "es2017", props: []string{"formatToParts"}}, }, - "Promise": { + unique.Make("Promise"): { {lib: "es2015", props: []string{}}, {lib: "es2018", props: []string{"finally"}}, }, - "RegExpMatchArray": { + unique.Make("RegExpMatchArray"): { {lib: "es2018", props: []string{"groups"}}, }, - "RegExpExecArray": { + unique.Make("RegExpExecArray"): { {lib: "es2018", props: []string{"groups"}}, }, - "Intl": { + unique.Make("Intl"): { {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": { + unique.Make("NumberFormat"): { {lib: "es2018", props: []string{"formatToParts"}}, }, - "SymbolConstructor": { + unique.Make("SymbolConstructor"): { {lib: "es2020", props: []string{"matchAll"}}, {lib: "esnext", props: []string{ "metadata", @@ -1604,82 +1605,82 @@ var getFeatureMap = sync.OnceValue(func() map[string][]FeatureMapEntry { "asyncDispose", }}, }, - "DataView": { + unique.Make("DataView"): { {lib: "es2020", props: []string{"setBigInt64", "setBigUint64", "getBigInt64", "getBigUint64"}}, {lib: "es2025", props: []string{"setFloat16", "getFloat16"}}, }, - "BigInt": { + unique.Make("BigInt"): { {lib: "es2020", props: []string{}}, }, - "RelativeTimeFormat": { + unique.Make("RelativeTimeFormat"): { {lib: "es2020", props: []string{"format", "formatToParts", "resolvedOptions"}}, }, - "Int8Array": { + unique.Make("Int8Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Uint8Array": { + unique.Make("Uint8Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, {lib: "es2026", props: []string{"toBase64", "setFromBase64", "toHex", "setFromHex"}}, }, - "Uint8ClampedArray": { + unique.Make("Uint8ClampedArray"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Int16Array": { + unique.Make("Int16Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Uint16Array": { + unique.Make("Uint16Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Int32Array": { + unique.Make("Int32Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Uint32Array": { + unique.Make("Uint32Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Float16Array": { + unique.Make("Float16Array"): { {lib: "es2025", props: []string{}}, }, - "Float32Array": { + unique.Make("Float32Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Float64Array": { + unique.Make("Float64Array"): { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "BigInt64Array": { + unique.Make("BigInt64Array"): { {lib: "es2020", props: []string{}}, {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "BigUint64Array": { + unique.Make("BigUint64Array"): { {lib: "es2020", props: []string{}}, {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - "Error": { + unique.Make("Error"): { {lib: "es2022", props: []string{"cause"}}, }, - "ErrorConstructor": { + unique.Make("ErrorConstructor"): { {lib: "es2026", props: []string{"isError"}}, }, - "Uint8ArrayConstructor": { + unique.Make("Uint8ArrayConstructor"): { {lib: "es2026", props: []string{"fromBase64", "fromHex"}}, }, - "DisposableStack": { + unique.Make("DisposableStack"): { {lib: "esnext", props: []string{}}, }, - "AsyncDisposableStack": { + unique.Make("AsyncDisposableStack"): { {lib: "esnext", props: []string{}}, }, - "Date": { + unique.Make("Date"): { {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() @@ -1769,7 +1770,7 @@ func introducesArgumentsExoticObject(node *ast.Node) bool { func symbolsToArray(symbols ast.SymbolTable) []*ast.Symbol { var result []*ast.Symbol for id, symbol := range symbols { - if !isReservedMemberName(id) { + if !isReservedMemberName(id.Value()) { result = append(result, symbol) } } diff --git a/tsc/internal/ls/autoimport/export.go b/tsc/internal/ls/autoimport/export.go index 4ed8512b05327..788a5f5aace98 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 != (ast.SymbolName{}) && 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..12e9b1edcfc9a 100644 --- a/tsc/internal/ls/autoimport/extract.go +++ b/tsc/internal/ls/autoimport/extract.go @@ -3,6 +3,7 @@ package autoimport import ( "slices" "sync/atomic" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -181,7 +182,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 +252,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()[unique.Make(prop.Name().Text())], moduleID, moduleFileName, syntax, file, checkerLease) if export != nil { export.through = name *exports = append(*exports, export) @@ -352,7 +353,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 = unique.Make(lsutil.ModuleSpecifierToValidIdentifier(fileNameForDefaultExportName(targetSymbol, moduleFileName, moduleID), false)) } } @@ -399,7 +400,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, unique.Make(name), ast.SymbolFlagsAll, nil, false, false) if local != nil && !ast.IsNonLocalAlias(local, ast.SymbolFlagsNone) { return local } @@ -450,9 +451,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 == (ast.SymbolName{}) || name == ast.EmptySymbolName || + name == unique.Make("_default") || 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 1333ef59cc134..2823eb96f91d0 100644 --- a/tsc/internal/ls/autoimport/fix.go +++ b/tsc/internal/ls/autoimport/fix.go @@ -7,6 +7,7 @@ import ( "slices" "strings" "unicode" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -589,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, @@ -603,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 = unique.Make(fmt.Sprintf("%c%s", unicode.ToUpper(rune(nameText[0])), nameText[1:])) } else { return nil } @@ -617,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, }, @@ -660,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, @@ -730,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, @@ -781,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..1c09c1ff4820d 100644 --- a/tsc/internal/ls/autoimport/import_adder.go +++ b/tsc/internal/ls/autoimport/import_adder.go @@ -5,6 +5,8 @@ import ( "fmt" "maps" "slices" + "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -32,13 +34,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 +177,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 +189,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 := unique.Make(fix.Name) compilerOptions := adder.view.program.Options() switch fix.Kind { @@ -201,7 +203,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 } @@ -214,14 +216,14 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.namedImports[symbolName] = &newImportBinding{ kind: lsproto.ImportKindNamed, - name: symbolName, + name: symbolName.Value(), addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), propertyName: existingFix.namedImport.propertyName, } } else { // Default import debug.Assert( - entry.defaultImport == nil || entry.defaultImport.name == symbolName, + entry.defaultImport == nil || unique.Make(entry.defaultImport.name) == symbolName, "(Add to Existing) Default import should be missing or match symbolName", ) var prevTypeOnly lsproto.AddAsTypeOnly @@ -230,7 +232,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.defaultImport = &newImportBinding{ kind: lsproto.ImportKindDefault, - name: symbolName, + name: symbolName.Value(), addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), } } @@ -245,7 +247,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { switch fix.ImportKind { case lsproto.ImportKindDefault: debug.Assert( - entry.defaultImport == nil || entry.defaultImport.name == symbolName, + entry.defaultImport == nil || unique.Make(entry.defaultImport.name) == symbolName, "(Add new) Default import should be missing or match symbolName", ) var prevTypeOnly lsproto.AddAsTypeOnly @@ -254,13 +256,13 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.defaultImport = &newImportBinding{ kind: lsproto.ImportKindDefault, - name: symbolName, + name: symbolName.Value(), addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), } 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 @@ -269,7 +271,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.namedImports[symbolName] = &newImportBinding{ kind: lsproto.ImportKindNamed, - name: symbolName, + name: symbolName.Value(), addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), // !!! propertyName } @@ -277,7 +279,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 @@ -286,30 +288,30 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.namedImports[symbolName] = &newImportBinding{ kind: lsproto.ImportKindCommonJS, - name: symbolName, + name: symbolName.Value(), addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), // !!! propertyName } } else { debug.Assert( - entry.namespaceLikeImport == nil || entry.namespaceLikeImport.name == symbolName, + entry.namespaceLikeImport == nil || unique.Make(entry.namespaceLikeImport.name) == symbolName, "Namespacelike import should be missing or match symbolName", ) entry.namespaceLikeImport = &newImportBinding{ kind: lsproto.ImportKindCommonJS, - name: symbolName, + name: symbolName.Value(), addAsTypeOnly: fix.AddAsTypeOnly, } } case lsproto.ImportKindNamespace: debug.Assert( - entry.namespaceLikeImport == nil || entry.namespaceLikeImport.name == symbolName, + entry.namespaceLikeImport == nil || unique.Make(entry.namespaceLikeImport.name) == symbolName, "Namespacelike import should be missing or match symbolName", ) entry.namespaceLikeImport = &newImportBinding{ kind: lsproto.ImportKindNamespace, - name: symbolName, + name: symbolName.Value(), addAsTypeOnly: fix.AddAsTypeOnly, } } @@ -469,13 +471,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..f30de9bcf56cb 100644 --- a/tsc/internal/ls/autoimport/index.go +++ b/tsc/internal/ls/autoimport/index.go @@ -4,13 +4,15 @@ import ( "strings" "unicode" "unicode/utf8" + "unique" + "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 @@ -36,10 +38,11 @@ func (idx *Index[T]) Find(name string, caseSensitive bool) []T { } var results []T + nameKey := unique.Make(name) for _, entryIndex := range candidates { entry := idx.entries[entryIndex] entryName := entry.Name() - if (caseSensitive && entryName == name) || (!caseSensitive && strings.EqualFold(entryName, name)) { + if (caseSensitive && entryName == nameKey) || (!caseSensitive && strings.EqualFold(entryName.Value(), name)) { results = append(results, entry) } } @@ -85,7 +88,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 +119,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..ef704f40bd131 100644 --- a/tsc/internal/ls/autoimport/index_test.go +++ b/tsc/internal/ls/autoimport/index_test.go @@ -1,7 +1,12 @@ package autoimport import ( + "slices" + "strings" "testing" + "unique" + + "github.com/microsoft/TypeScript/tsc/internal/ast" "gotest.tools/v3/assert" ) @@ -11,7 +16,22 @@ type testEntry struct { package_ string } -func (e *testEntry) Name() string { return e.name } +func (e *testEntry) Name() ast.SymbolName { return unique.Make(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(strings.Clone("fooBar"), true), []*testEntry{lower})) + assert.Assert(t, slices.Equal(idx.Find("FooBar", true), []*testEntry{upper})) + assert.Assert(t, slices.Equal(idx.Find("FOOBAR", false), []*testEntry{lower, upper})) + assert.Equal(t, len(idx.Find("FOOBAR", true)), 0) + assert.Assert(t, slices.Equal(idx.SearchWordPrefix("fb"), []*testEntry{lower, upper})) +} func TestIndexClone(t *testing.T) { t.Parallel() diff --git a/tsc/internal/ls/autoimport/util.go b/tsc/internal/ls/autoimport/util.go index 73b4461913afc..06f1f0bb19677 100644 --- a/tsc/internal/ls/autoimport/util.go +++ b/tsc/internal/ls/autoimport/util.go @@ -6,6 +6,7 @@ import ( "sync/atomic" "unicode" "unicode/utf8" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -114,31 +115,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 unique.Make(innerExpression.Text()) } 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 unique.Make(d.PropertyName().Text()) } continue } // GH#52694 if name := ast.GetNameOfDeclaration(d); name != nil && name.Kind == ast.KindIdentifier { - return name.Text() + return unique.Make(name.Text()) } 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..0dde88957e250 100644 --- a/tsc/internal/ls/autoimport/view.go +++ b/tsc/internal/ls/autoimport/view.go @@ -181,17 +181,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..e69f35af51f19 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) @@ -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..0623c6525afe2 100644 --- a/tsc/internal/ls/codeactions_importfixes.go +++ b/tsc/internal/ls/codeactions_importfixes.go @@ -4,6 +4,7 @@ import ( "context" "slices" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -258,7 +259,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 +287,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(unique.Make(jsxNamespace), location, ast.SymbolFlagsValue, false /* excludeGlobals */) if isUMDExportSymbol(parentSymbol) { return parentSymbol } @@ -333,7 +334,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() == unique.Make(symbolName) || export.IsRenameable()) { continue } @@ -354,7 +355,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(unique.Make(symbolName), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */) if symbol == nil { return nil } @@ -387,7 +388,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(unique.Make(symbolToken.Text()), symbolToken, ast.SymbolFlagsValue, false /* excludeGlobals */) if compSymbol == nil { result = append(result, symbolNameInfo{name: symbolToken.Text()}) } else if ch.GetTypeOnlyAliasDeclaration(compSymbol) != nil { @@ -395,7 +396,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(unique.Make(jsxNamespace), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); nsSymbol != nil { nsIsTypeOnly = ch.GetTypeOnlyAliasDeclaration(nsSymbol) != nil } result = append(result, symbolNameInfo{name: jsxNamespace, isTypeOnly: nsIsTypeOnly}) @@ -403,7 +404,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(unique.Make(symbolToken.Text()), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); sym != nil { tokenIsTypeOnly = ch.GetTypeOnlyAliasDeclaration(sym) != nil } return []symbolNameInfo{{name: symbolToken.Text(), isTypeOnly: tokenIsTypeOnly}} @@ -413,7 +414,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(unique.Make(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..0a935be3889df 100644 --- a/tsc/internal/ls/codeactions_missingmemberfixer.go +++ b/tsc/internal/ls/codeactions_missingmemberfixer.go @@ -325,7 +325,7 @@ func (f *missingMemberFixer) createSignatureDeclarationFromSignatures(signatures maxNonRestArgs := len(maxArgsSignature.Parameters()) - core.IfElse(maxArgsSignature.HasRestParameter(), 1, 0) parameterNames := make([]string, 0, len(maxArgsSignature.Parameters())) for _, symbol := range maxArgsSignature.Parameters() { - parameterNames = append(parameterNames, symbol.Name()) + parameterNames = append(parameterNames, symbol.Name().Value()) } parameters := createDummyParameters(f.changeTracker.NodeFactory, maxNonRestArgs, parameterNames, nil /*types*/, minArgumentCount, ast.IsInJSFile(enclosingDeclaration)) @@ -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 079360c8f495c..b68993000b8f2 100644 --- a/tsc/internal/ls/completions.go +++ b/tsc/internal/ls/completions.go @@ -9,6 +9,7 @@ import ( "sync" "unicode" "unicode/utf8" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -1050,7 +1051,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 +1327,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(unique.Make(element.PropertyNameOrName().Text())) } 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 +1367,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 unique.Make(el.AsImportAttribute().Name().Text()) }) 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 +1550,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(unique.Make(ast.SymbolNameText(symbol))) { symbolToSortTextMap[symbolId] = SortTextMemberDeclaredBySpreadAssignment } if symbol.Flags()&ast.SymbolFlagsOptional != 0 { @@ -3174,7 +3175,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 @@ -4255,15 +4256,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(unique.Make("self"), 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(unique.Make("global"), 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(unique.Make("globalThis"), ast.SymbolFlagsValue, nil /*diagnostic*/) if globalThisSymbol != nil && typeChecker.GetTypeOfSymbolAtLocation(globalThisSymbol, file.AsNode()) == t { return true } @@ -4319,7 +4320,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, unique.Make(name)) } return nil @@ -4490,13 +4491,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 && @@ -4534,7 +4535,7 @@ func filterObjectMembersList( } if existingName != "" { - existingMemberNames.Add(existingName) + existingMemberNames.Add(unique.Make(existingName)) } } @@ -4550,7 +4551,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 @@ -4704,7 +4705,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 && @@ -4730,13 +4731,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(unique.Make(ast.SymbolNameText(propertySymbol))) && len(propertySymbol.Declarations()) > 0 && checker.GetDeclarationModifierFlagsFromSymbol(propertySymbol)&ast.ModifierFlagsPrivate == 0 && !(propertySymbol.ValueDeclaration() != nil && ast.IsPrivateIdentifierClassElementDeclaration(propertySymbol.ValueDeclaration())) @@ -4813,9 +4814,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) { @@ -4823,7 +4824,7 @@ func filterJsxAttributes( } if attr.Kind == ast.KindJsxAttribute { - existingNames.Add(attr.Name().Text()) + existingNames.Add(unique.Make(attr.Name().Text())) } 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..583cb89a15e34 100644 --- a/tsc/internal/ls/definition.go +++ b/tsc/internal/ls/definition.go @@ -3,6 +3,7 @@ package ls import ( "context" "slices" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -340,7 +341,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, unique.Make(name)); prop != nil { result = append(result, prop.Declarations()...) } } @@ -485,9 +486,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), unique.Make(name)) } - return typeChecker.GetPropertyOfType(typeChecker.GetDeclaredTypeOfSymbol(base), name) + return typeChecker.GetPropertyOfType(typeChecker.GetDeclaredTypeOfSymbol(base), unique.Make(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..563bb1e0cbf43 100644 --- a/tsc/internal/ls/findallreferences.go +++ b/tsc/internal/ls/findallreferences.go @@ -7,6 +7,7 @@ import ( "slices" "strings" "sync" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -395,7 +396,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 +1394,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), unique.Make(node.Text())) != nil } return false } @@ -1964,8 +1965,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(unique.Make(symbolName)); ok { text = moduleName } else { text = symbolName diff --git a/tsc/internal/ls/importTracker.go b/tsc/internal/ls/importTracker.go index e4aa7f94dd940..57aa42a16b7ac 100644 --- a/tsc/internal/ls/importTracker.go +++ b/tsc/internal/ls/importTracker.go @@ -3,6 +3,7 @@ package ls import ( "context" "slices" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -357,7 +358,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 unique.Make(name) == exportSymbol.Name() || exportKind != ExportKindNamed && unique.Make(name) == ast.InternalSymbolNameDefault } // `import x = require("./x")` or `import * as x from "./x"`. @@ -385,7 +386,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 || unique.Make(name.Text()) == exportSymbol.Name() { // Search locally for `bar`. addSearch(name, checker.GetSymbolAtLocation(name)) } @@ -415,7 +416,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 unique.Make(firstIdentifier.Text()) == exportSymbol.Name() { singleReferences = append(singleReferences, firstIdentifier) } } else if exportKind == ExportKindExportEquals { @@ -448,7 +449,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 || unique.Make(name.Text()) == symbolNameNoDefault(exportSymbol)) { defaultImportAlias := checker.GetSymbolAtLocation(name) addSearch(name, defaultImportAlias) } @@ -583,7 +584,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() == unique.Make("export=") { importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker) if importedSymbol == nil { return nil @@ -593,7 +594,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 +700,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 unique.Make(name.Text()) } } - 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..a6c1c1b878120 100644 --- a/tsc/internal/ls/jsdoc.go +++ b/tsc/internal/ls/jsdoc.go @@ -3,6 +3,7 @@ package ls import ( "slices" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -190,7 +191,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, unique.Make(name.Text())); 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..3ec0e3619356b 100644 --- a/tsc/internal/ls/lsutil/utilities.go +++ b/tsc/internal/ls/lsutil/utilities.go @@ -3,6 +3,7 @@ package lsutil import ( "strings" "unicode" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -115,9 +116,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 = unique.Make(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..a4af8c2829465 100644 --- a/tsc/internal/ls/sourcedefinition.go +++ b/tsc/internal/ls/sourcedefinition.go @@ -4,6 +4,7 @@ import ( "context" "math" "slices" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -229,7 +230,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), unique.Make(node.Text())); prop != nil { declarations = prop.Declarations() } } diff --git a/tsc/internal/ls/string_completions.go b/tsc/internal/ls/string_completions.go index c453bb239d3a5..04b71f01b68b7 100644 --- a/tsc/internal/ls/string_completions.go +++ b/tsc/internal/ls/string_completions.go @@ -8,6 +8,7 @@ import ( "maps" "slices" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -396,8 +397,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 unique.Make(n.PropertyNameOrName().Text()) })...) uniques := core.Filter(exports, func(e *ast.Symbol) bool { return e.Name() != ast.InternalSymbolNameDefault && !existing.Has(e.Name()) @@ -518,11 +519,12 @@ func fromUnionableLiteralType( switch { case result.fromProperties != nil: result := result.fromProperties + alreadyUsedNames := collections.NewSetFromItems(core.Map(alreadyUsedTypes, unique.Make[string])...) 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 +931,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 +2030,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, unique.Make(editingArgument.AsJsxAttribute().Name().Text())) if propType != nil { t = propType } @@ -2089,7 +2091,7 @@ func (l *LanguageService) stringLiteralCompletionDetails( case completion.fromProperties != nil: properties := completion.fromProperties for _, symbol := range properties.symbols { - if symbol.Name() == name { + if symbol.Name() == unique.Make(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..257b91cd9ed68 100644 --- a/tsc/internal/ls/utilities.go +++ b/tsc/internal/ls/utilities.go @@ -5,6 +5,7 @@ import ( "iter" "slices" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -960,7 +961,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 +996,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, unique.Make(bindingElement.Name().Text())) } return nil } diff --git a/tsc/internal/printer/namegenerator.go b/tsc/internal/printer/namegenerator.go index 81078f087a3bd..9572e5ebacbd7 100644 --- a/tsc/internal/printer/namegenerator.go +++ b/tsc/internal/printer/namegenerator.go @@ -2,6 +2,7 @@ package printer import ( "fmt" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -366,7 +367,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[unique.Make(name)]; ok && local.Flags()&(ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias) != 0 { return false } } 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..bd0aa96f7d513 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -5,6 +5,7 @@ import ( "iter" "slices" "strings" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -2847,7 +2848,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[unique.Make(localName.Text())] = symbol oldEnclosing := tx.enclosingDeclaration tx.enclosingDeclaration = synthesizedNamespace @@ -3020,7 +3021,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() From 544fa3d8973815dcd5793dade2554226d65ac058 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 8 Oct 2026 14:18:51 -0700 Subject: [PATCH 02/14] Hoist fixed symbol names and preserve handle boundaries Known names and intermediate name operations should stay interned; repeated interning and string round trips defeat the canonical representation in frequently used lookup paths. --- tsc/internal/ast/symbol.go | 182 ++++++++++ tsc/internal/ast/symbol_test.go | 19 + tsc/internal/binder/binder.go | 12 +- tsc/internal/binder/nameresolver.go | 8 +- tsc/internal/checker/checker.go | 335 +++++++++--------- tsc/internal/checker/emitresolver.go | 6 +- tsc/internal/checker/flow.go | 6 +- tsc/internal/checker/grammarchecks.go | 8 +- tsc/internal/checker/jsx.go | 42 +-- tsc/internal/checker/nodebuilder_hover.go | 5 +- tsc/internal/checker/nodebuilderimpl.go | 58 +-- tsc/internal/checker/relater.go | 38 +- tsc/internal/checker/services.go | 56 +-- tsc/internal/checker/utilities.go | 124 +++---- tsc/internal/ls/autoimport/extract.go | 2 +- tsc/internal/ls/autoimport/fix.go | 36 +- tsc/internal/ls/autoimport/import_adder.go | 22 +- tsc/internal/ls/autoimport/index.go | 11 +- tsc/internal/ls/autoimport/index_test.go | 14 +- tsc/internal/ls/autoimport/view.go | 9 +- .../ls/codeactions_missingmemberfixer.go | 25 +- tsc/internal/ls/completions.go | 6 +- tsc/internal/ls/importTracker.go | 2 +- tsc/internal/printer/emitresolver.go | 2 +- .../transformers/declarations/transform.go | 4 +- 25 files changed, 621 insertions(+), 411 deletions(-) diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index b910707063acc..90bc2105939d1 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -174,6 +174,188 @@ var EmptySymbolName = unique.Make("") type SymbolTable map[SymbolName]*Symbol +// Fixed symbol names are interned once and shared by compiler consumers. +var ( + SymbolNameZero = unique.Make("0") + SymbolNameUnresolved = unique.Make("<>") + SymbolNameAbstractModuleSource = unique.Make("AbstractModuleSource") + SymbolNameArray = unique.Make("Array") + SymbolNameArrayBuffer = unique.Make("ArrayBuffer") + SymbolNameArrayConstructor = unique.Make("ArrayConstructor") + SymbolNameArrayLike = unique.Make("ArrayLike") + SymbolNameAsyncDisposable = unique.Make("AsyncDisposable") + SymbolNameAsyncDisposableStack = unique.Make("AsyncDisposableStack") + SymbolNameAsyncGenerator = unique.Make("AsyncGenerator") + SymbolNameAsyncGeneratorFunction = unique.Make("AsyncGeneratorFunction") + SymbolNameAsyncIterable = unique.Make("AsyncIterable") + SymbolNameAsyncIterableIterator = unique.Make("AsyncIterableIterator") + SymbolNameAsyncIterator = unique.Make("AsyncIterator") + SymbolNameAsyncIteratorObject = unique.Make("AsyncIteratorObject") + SymbolNameAtomics = unique.Make("Atomics") + SymbolNameAwaited = unique.Make("Awaited") + SymbolNameBigInt = unique.Make("BigInt") + SymbolNameBigInt64Array = unique.Make("BigInt64Array") + SymbolNameBigUint64Array = unique.Make("BigUint64Array") + SymbolNameBoolean = unique.Make("Boolean") + SymbolNameBuiltinIteratorReturn = unique.Make("BuiltinIteratorReturn") + SymbolNameCallableFunction = unique.Make("CallableFunction") + SymbolNameCapitalize = unique.Make("Capitalize") + SymbolNameClassAccessorDecoratorContext = unique.Make("ClassAccessorDecoratorContext") + SymbolNameClassAccessorDecoratorResult = unique.Make("ClassAccessorDecoratorResult") + SymbolNameClassAccessorDecoratorTarget = unique.Make("ClassAccessorDecoratorTarget") + SymbolNameClassDecoratorContext = unique.Make("ClassDecoratorContext") + SymbolNameClassFieldDecoratorContext = unique.Make("ClassFieldDecoratorContext") + SymbolNameClassGetterDecoratorContext = unique.Make("ClassGetterDecoratorContext") + SymbolNameClassMethodDecoratorContext = unique.Make("ClassMethodDecoratorContext") + SymbolNameClassSetterDecoratorContext = unique.Make("ClassSetterDecoratorContext") + SymbolNameDataView = unique.Make("DataView") + SymbolNameDate = unique.Make("Date") + SymbolNameDateTimeFormat = unique.Make("DateTimeFormat") + SymbolNameDisposable = unique.Make("Disposable") + SymbolNameDisposableStack = unique.Make("DisposableStack") + SymbolNameElement = unique.Make("Element") + SymbolNameElementAttributesProperty = unique.Make("ElementAttributesProperty") + SymbolNameElementChildrenAttribute = unique.Make("ElementChildrenAttribute") + SymbolNameElementClass = unique.Make("ElementClass") + SymbolNameElementType = unique.Make("ElementType") + SymbolNameError = unique.Make("Error") + SymbolNameErrorConstructor = unique.Make("ErrorConstructor") + SymbolNameEventTarget = unique.Make("EventTarget") + SymbolNameExtract = unique.Make("Extract") + SymbolNameFloat16Array = unique.Make("Float16Array") + SymbolNameFloat32Array = unique.Make("Float32Array") + SymbolNameFloat64Array = unique.Make("Float64Array") + SymbolNameFunction = unique.Make("Function") + SymbolNameGenerator = unique.Make("Generator") + SymbolNameIArguments = unique.Make("IArguments") + SymbolNameImportAttributes = unique.Make("ImportAttributes") + SymbolNameImportCallOptions = unique.Make("ImportCallOptions") + SymbolNameImportMeta = unique.Make("ImportMeta") + SymbolNameImportMetaExpression = unique.Make("ImportMetaExpression") + SymbolNameInt16Array = unique.Make("Int16Array") + SymbolNameInt32Array = unique.Make("Int32Array") + SymbolNameInt8Array = unique.Make("Int8Array") + SymbolNameIntl = unique.Make("Intl") + SymbolNameIntrinsicAttributes = unique.Make("IntrinsicAttributes") + SymbolNameIntrinsicClassAttributes = unique.Make("IntrinsicClassAttributes") + SymbolNameIntrinsicElements = unique.Make("IntrinsicElements") + SymbolNameIterable = unique.Make("Iterable") + SymbolNameIterableIterator = unique.Make("IterableIterator") + SymbolNameIterator = unique.Make("Iterator") + SymbolNameIteratorConstructor = unique.Make("IteratorConstructor") + SymbolNameIteratorObject = unique.Make("IteratorObject") + SymbolNameIteratorReturnResult = unique.Make("IteratorReturnResult") + SymbolNameIteratorYieldResult = unique.Make("IteratorYieldResult") + SymbolNameJSON = unique.Make("JSON") + SymbolNameJSX = unique.Make("JSX") + SymbolNameK = unique.Make("K") + SymbolNameLibraryManagedAttributes = unique.Make("LibraryManagedAttributes") + SymbolNameLowercase = unique.Make("Lowercase") + SymbolNameMap = unique.Make("Map") + SymbolNameMapConstructor = unique.Make("MapConstructor") + SymbolNameMath = unique.Make("Math") + SymbolNameNaN = unique.Make("NaN") + SymbolNameNewableFunction = unique.Make("NewableFunction") + SymbolNameNoInfer = unique.Make("NoInfer") + SymbolNameNode = unique.Make("Node") + SymbolNameNodeList = unique.Make("NodeList") + SymbolNameNonNullable = unique.Make("NonNullable") + SymbolNameNumber = unique.Make("Number") + SymbolNameNumberConstructor = unique.Make("NumberConstructor") + SymbolNameNumberFormat = unique.Make("NumberFormat") + SymbolNameObject = unique.Make("Object") + SymbolNameObjectConstructor = unique.Make("ObjectConstructor") + SymbolNameOmit = unique.Make("Omit") + SymbolNamePartial = unique.Make("Partial") + SymbolNamePick = unique.Make("Pick") + SymbolNamePromise = unique.Make("Promise") + SymbolNamePromiseConstructor = unique.Make("PromiseConstructor") + SymbolNamePromiseLike = unique.Make("PromiseLike") + SymbolNameRawJSON = unique.Make("RawJSON") + SymbolNameReadonly = unique.Make("Readonly") + SymbolNameReadonlyArray = unique.Make("ReadonlyArray") + SymbolNameReadonlyMap = unique.Make("ReadonlyMap") + SymbolNameReadonlySet = unique.Make("ReadonlySet") + SymbolNameRecord = unique.Make("Record") + SymbolNameReflect = unique.Make("Reflect") + SymbolNameRegExp = unique.Make("RegExp") + SymbolNameRegExpConstructor = unique.Make("RegExpConstructor") + SymbolNameRegExpExecArray = unique.Make("RegExpExecArray") + SymbolNameRegExpMatchArray = unique.Make("RegExpMatchArray") + SymbolNameRelativeTimeFormat = unique.Make("RelativeTimeFormat") + SymbolNameRequired = unique.Make("Required") + SymbolNameSet = unique.Make("Set") + SymbolNameSharedArrayBuffer = unique.Make("SharedArrayBuffer") + SymbolNameString = unique.Make("String") + SymbolNameStringConstructor = unique.Make("StringConstructor") + SymbolNameSymbol = unique.Make("Symbol") + SymbolNameSymbolConstructor = unique.Make("SymbolConstructor") + SymbolNameT = unique.Make("T") + SymbolNameTemplateStringsArray = unique.Make("TemplateStringsArray") + SymbolNameThisType = unique.Make("ThisType") + SymbolNameTypedPropertyDescriptor = unique.Make("TypedPropertyDescriptor") + SymbolNameUint16Array = unique.Make("Uint16Array") + SymbolNameUint32Array = unique.Make("Uint32Array") + SymbolNameUint8Array = unique.Make("Uint8Array") + SymbolNameUint8ArrayConstructor = unique.Make("Uint8ArrayConstructor") + SymbolNameUint8ClampedArray = unique.Make("Uint8ClampedArray") + SymbolNameUncapitalize = unique.Make("Uncapitalize") + SymbolNameUppercase = unique.Make("Uppercase") + SymbolNameWeakMap = unique.Make("WeakMap") + SymbolNameWeakSet = unique.Make("WeakSet") + SymbolNameESModule = unique.Make("__esModule") + SymbolNameUnderscoreDefault = unique.Make("_default") + SymbolNameAny = unique.Make("any") + SymbolNameArg = unique.Make("arg") + SymbolNameArgs = unique.Make("args") + SymbolNameArguments = unique.Make("arguments") + SymbolNameAsyncIteratorProperty = unique.Make("asyncIterator") + SymbolNameBind = unique.Make("bind") + SymbolNameBooleanKeyword = unique.Make("boolean") + SymbolNameCaller = unique.Make("caller") + SymbolNameChildren = unique.Make("children") + SymbolNameClass = unique.Make("class") + SymbolNameClassName = unique.Make("className") + SymbolNameConst = unique.Make("const") + SymbolNameContext = unique.Make("context") + SymbolNameDescriptor = unique.Make("descriptor") + SymbolNameDone = unique.Make("done") + SymbolNameExports = unique.Make("exports") + SymbolNameFor = unique.Make("for") + SymbolNameGetProperty = unique.Make("get") + SymbolNameGlobal = unique.Make("global") + SymbolNameGlobalThis = unique.Make("globalThis") + SymbolNameHasInstance = unique.Make("hasInstance") + SymbolNameHtmlFor = unique.Make("htmlFor") + SymbolNameIteratorProperty = unique.Make("iterator") + SymbolNameLength = unique.Make("length") + SymbolNameMeta = unique.Make("meta") + SymbolNameModule = unique.Make("module") + SymbolNameName = unique.Make("name") + SymbolNameNever = unique.Make("never") + SymbolNameNext = unique.Make("next") + SymbolNameNumberKeyword = unique.Make("number") + SymbolNameParameterIndex = unique.Make("parameterIndex") + SymbolNamePrivate = unique.Make("private") + SymbolNamePropertyKey = unique.Make("propertyKey") + SymbolNameProps = unique.Make("props") + SymbolNamePrototype = unique.Make("prototype") + SymbolNameRequire = unique.Make("require") + SymbolNameReturn = unique.Make("return") + SymbolNameSelf = unique.Make("self") + SymbolNameSetProperty = unique.Make("set") + SymbolNameStatic = unique.Make("static") + SymbolNameStringKeyword = unique.Make("string") + SymbolNameTarget = unique.Make("target") + SymbolNameThen = unique.Make("then") + SymbolNameThrow = unique.Make("throw") + SymbolNameUndefined = unique.Make("undefined") + SymbolNameUnknown = unique.Make("unknown") + SymbolNameValue = unique.Make("value") + SymbolNameWith = unique.Make("with") + SymbolNameWritable = unique.Make("writable") +) + const InternalSymbolNamePrefix = "\xFE" // Invalid UTF8 sequence, will never occur as IdentifierName var ( diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index c714e5227da4f..1312a200fc9b8 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -41,6 +41,25 @@ func TestSymbolNameInterning(t *testing.T) { assert.Assert(t, new(ast.SymbolWithData).Initialize().Name() == unique.Make("")) } +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 == unique.Make(strings.Clone(text))) + assert.Equal(t, name.Value(), text) + }) + } +} + func TestSymbolFieldsArePrivate(t *testing.T) { t.Parallel() for field := range reflect.TypeFor[ast.Symbol]().Fields() { diff --git a/tsc/internal/binder/binder.go b/tsc/internal/binder/binder.go index 0ff6ba5042742..4b5584710184c 100644 --- a/tsc/internal/binder/binder.go +++ b/tsc/internal/binder/binder.go @@ -968,7 +968,7 @@ 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, unique.Make("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.SymbolNameText(prototypeSymbol)) @@ -1614,8 +1614,8 @@ func (b *Binder) bindContainer(node *ast.Node, containerFlags ContainerFlags) { } } if b.file.CommonJSModuleIndicator != nil { - b.declareCommonJSVariable(unique.Make("module")) - b.declareCommonJSVariable(unique.Make("exports")) + b.declareCommonJSVariable(ast.SymbolNameModule) + b.declareCommonJSVariable(ast.SymbolNameExports) } } if ast.IsSourceFile(node) && ast.IsExternalOrCommonJSModule(node.AsSourceFile()) || ast.IsAmbientModule(node) { @@ -1632,13 +1632,13 @@ func (b *Binder) declareCommonJSVariable(name ast.SymbolName) { symbol := b.newSymbol(ast.SymbolFlagsFunctionScopedVariable|ast.SymbolFlagsModuleExports, name) symbol.SetDeclarations(b.newSingleDeclaration(b.file.AsNode())) symbol.SetValueDeclaration(symbol.Declarations()[0]) - if name == unique.Make("module") { - exportsProperty := b.newSymbol(ast.SymbolFlagsModuleExports|ast.SymbolFlagsProperty, unique.Make("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()[unique.Make("exports")] = exportsProperty + symbol.Members()[ast.SymbolNameExports] = exportsProperty } locals[name] = symbol } diff --git a/tsc/internal/binder/nameresolver.go b/tsc/internal/binder/nameresolver.go index d1dc1507cfa8a..4257771a50849 100644 --- a/tsc/internal/binder/nameresolver.go +++ b/tsc/internal/binder/nameresolver.go @@ -33,7 +33,7 @@ func (r *NameResolver) Resolve(location *ast.Node, name ast.SymbolName, meaning 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 == unique.Make("const") + nameIsConst := name == ast.SymbolNameConst loop: for location != nil { if nameIsConst && ast.IsConstAssertion(location) { @@ -236,12 +236,12 @@ loop: } } case ast.KindMethodDeclaration, ast.KindConstructor, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindFunctionDeclaration: - if meaning&ast.SymbolFlagsVariable != 0 && name == unique.Make("arguments") { + if meaning&ast.SymbolFlagsVariable != 0 && name == ast.SymbolNameArguments { result = r.argumentsSymbol() break loop } case ast.KindFunctionExpression: - if meaning&ast.SymbolFlagsVariable != 0 && name == unique.Make("arguments") { + if meaning&ast.SymbolFlagsVariable != 0 && name == ast.SymbolNameArguments { result = r.argumentsSymbol() break loop } @@ -445,7 +445,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(unique.Make("arguments")) + r.ArgumentsSymbol.SetName(ast.SymbolNameArguments) r.ArgumentsSymbol.SetFlags(ast.SymbolFlagsProperty | ast.SymbolFlagsTransient) } return r.ArgumentsSymbol diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index e34bfa56564f1..0d04ac4221b19 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -363,11 +363,11 @@ const ( ) var intrinsicTypeKinds = map[ast.SymbolName]IntrinsicTypeKind{ - unique.Make("Uppercase"): IntrinsicTypeKindUppercase, - unique.Make("Lowercase"): IntrinsicTypeKindLowercase, - unique.Make("Capitalize"): IntrinsicTypeKindCapitalize, - unique.Make("Uncapitalize"): IntrinsicTypeKindUncapitalize, - unique.Make("NoInfer"): IntrinsicTypeKindNoInfer, + ast.SymbolNameUppercase: IntrinsicTypeKindUppercase, + ast.SymbolNameLowercase: IntrinsicTypeKindLowercase, + ast.SymbolNameCapitalize: IntrinsicTypeKindCapitalize, + ast.SymbolNameUncapitalize: IntrinsicTypeKindUncapitalize, + ast.SymbolNameNoInfer: IntrinsicTypeKindNoInfer, } type MappedTypeModifiers uint32 @@ -992,14 +992,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, unique.Make("undefined")) - c.argumentsSymbol = c.newSymbol(ast.SymbolFlagsProperty, unique.Make("arguments")) - c.requireSymbol = c.newSymbol(ast.SymbolFlagsProperty, unique.Make("require")) - c.unknownSymbol = c.newSymbol(ast.SymbolFlagsProperty, unique.Make("unknown")) + 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, unique.Make("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 @@ -1078,7 +1078,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: unique.Make("<>"), 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) @@ -1100,57 +1100,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(unique.Make("Symbol"), 0 /*arity*/, false /*reportErrors*/) - c.getGlobalBigIntType = c.getGlobalTypeResolver(unique.Make("BigInt"), 0 /*arity*/, false /*reportErrors*/) - c.getGlobalImportMetaType = c.getGlobalTypeResolver(unique.Make("ImportMeta"), 0 /*arity*/, true /*reportErrors*/) - c.getGlobalImportAttributesType = c.getGlobalTypeResolver(unique.Make("ImportAttributes"), 0 /*arity*/, false /*reportErrors*/) - c.getGlobalImportAttributesTypeChecked = c.getGlobalTypeResolver(unique.Make("ImportAttributes"), 0 /*arity*/, true /*reportErrors*/) - c.getGlobalNonNullableTypeAliasOrNil = c.getGlobalTypeAliasResolver(unique.Make("NonNullable"), 1 /*arity*/, false /*reportErrors*/) - c.getGlobalExtractSymbol = c.getGlobalTypeAliasResolver(unique.Make("Extract"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalDisposableType = c.getGlobalTypeResolver(unique.Make("Disposable"), 0 /*arity*/, true /*reportErrors*/) - c.getGlobalAsyncDisposableType = c.getGlobalTypeResolver(unique.Make("AsyncDisposable"), 0 /*arity*/, true /*reportErrors*/) - c.getGlobalAwaitedSymbol = c.getGlobalTypeAliasResolver(unique.Make("Awaited"), 1 /*arity*/, true /*reportErrors*/) - c.getGlobalAwaitedSymbolOrNil = c.getGlobalTypeAliasResolver(unique.Make("Awaited"), 1 /*arity*/, false /*reportErrors*/) - c.getGlobalNaNSymbolOrNil = c.getGlobalValueSymbolResolver(unique.Make("NaN"), false /*reportErrors*/) - c.getGlobalRecordSymbol = c.getGlobalTypeAliasResolver(unique.Make("Record"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalTemplateStringsArrayType = c.getGlobalTypeResolver(unique.Make("TemplateStringsArray"), 0 /*arity*/, true /*reportErrors*/) - c.getGlobalESSymbolConstructorSymbolOrNil = c.getGlobalValueSymbolResolver(unique.Make("Symbol"), false /*reportErrors*/) - c.getGlobalESSymbolConstructorTypeSymbolOrNil = c.getGlobalTypeSymbolResolver(unique.Make("SymbolConstructor"), false /*reportErrors*/) - c.getGlobalImportCallOptionsType = c.getGlobalTypeResolver(unique.Make("ImportCallOptions"), 0 /*arity*/, false /*reportErrors*/) - c.getGlobalImportCallOptionsTypeChecked = c.getGlobalTypeResolver(unique.Make("ImportCallOptions"), 0 /*arity*/, true /*reportErrors*/) - c.getGlobalPromiseType = c.getGlobalTypeResolver(unique.Make("Promise"), 1 /*arity*/, false /*reportErrors*/) - c.getGlobalPromiseTypeChecked = c.getGlobalTypeResolver(unique.Make("Promise"), 1 /*arity*/, true /*reportErrors*/) - c.getGlobalPromiseLikeType = c.getGlobalTypeResolver(unique.Make("PromiseLike"), 1 /*arity*/, true /*reportErrors*/) - c.getGlobalAbstractModuleSourceType = c.getGlobalTypeResolver(unique.Make("AbstractModuleSource"), 0 /*arity*/, true /*reportErrors*/) - c.getGlobalPromiseConstructorSymbol = c.getGlobalValueSymbolResolver(unique.Make("Promise"), true /*reportErrors*/) - c.getGlobalPromiseConstructorSymbolOrNil = c.getGlobalValueSymbolResolver(unique.Make("Promise"), false /*reportErrors*/) - c.getGlobalOmitSymbol = c.getGlobalTypeAliasResolver(unique.Make("Omit"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalNoInferSymbolOrNil = c.getGlobalTypeAliasResolver(unique.Make("NoInfer"), 1 /*arity*/, false /*reportErrors*/) - c.getGlobalIteratorType = c.getGlobalTypeResolver(unique.Make("Iterator"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIterableType = c.getGlobalTypeResolver(unique.Make("Iterable"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIterableTypeChecked = c.getGlobalTypeResolver(unique.Make("Iterable"), 3 /*arity*/, true /*reportErrors*/) - c.getGlobalIterableIteratorType = c.getGlobalTypeResolver(unique.Make("IterableIterator"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIterableIteratorTypeChecked = c.getGlobalTypeResolver(unique.Make("IterableIterator"), 3 /*arity*/, true /*reportErrors*/) - c.getGlobalIteratorObjectType = c.getGlobalTypeResolver(unique.Make("IteratorObject"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalGeneratorType = c.getGlobalTypeResolver(unique.Make("Generator"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIteratorType = c.getGlobalTypeResolver(unique.Make("AsyncIterator"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIterableType = c.getGlobalTypeResolver(unique.Make("AsyncIterable"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIterableTypeChecked = c.getGlobalTypeResolver(unique.Make("AsyncIterable"), 3 /*arity*/, true /*reportErrors*/) - c.getGlobalAsyncIterableIteratorType = c.getGlobalTypeResolver(unique.Make("AsyncIterableIterator"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncIterableIteratorTypeChecked = c.getGlobalTypeResolver(unique.Make("AsyncIterableIterator"), 3 /*arity*/, true /*reportErrors*/) - c.getGlobalAsyncIteratorObjectType = c.getGlobalTypeResolver(unique.Make("AsyncIteratorObject"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalAsyncGeneratorType = c.getGlobalTypeResolver(unique.Make("AsyncGenerator"), 3 /*arity*/, false /*reportErrors*/) - c.getGlobalIteratorYieldResultType = c.getGlobalTypeResolver(unique.Make("IteratorYieldResult"), 1 /*arity*/, false /*reportErrors*/) - c.getGlobalIteratorReturnResultType = c.getGlobalTypeResolver(unique.Make("IteratorReturnResult"), 1 /*arity*/, false /*reportErrors*/) - c.getGlobalTypedPropertyDescriptorType = c.getGlobalTypeResolver(unique.Make("TypedPropertyDescriptor"), 1 /*arity*/, true /*reportErrors*/) - c.getGlobalClassDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassDecoratorContext"), 1 /*arity*/, true /*reportErrors*/) - c.getGlobalClassMethodDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassMethodDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassGetterDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassGetterDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassSetterDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassSetterDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassAccessorDecoratorContextType = c.getGlobalTypeResolver(unique.Make("ClassAccessorDecoratorContext"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassAccessorDecoratorTargetType = c.getGlobalTypeResolver(unique.Make("ClassAccessorDecoratorTarget"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassAccessorDecoratorResultType = c.getGlobalTypeResolver(unique.Make("ClassAccessorDecoratorResult"), 2 /*arity*/, true /*reportErrors*/) - c.getGlobalClassFieldDecoratorContextType = c.getGlobalTypeResolver(unique.Make("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() @@ -1300,7 +1300,7 @@ func (c *Checker) initializeClosures() { func (c *Checker) initializeIterationResolvers() { c.syncIterationTypesResolver = &IterationTypesResolver{ - iteratorSymbolName: unique.Make("iterator"), + iteratorSymbolName: ast.SymbolNameIteratorProperty, getGlobalIteratorType: c.getGlobalIteratorType, getGlobalIterableType: c.getGlobalIterableType, getGlobalIterableTypeChecked: c.getGlobalIterableTypeChecked, @@ -1317,7 +1317,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: unique.Make("asyncIterator"), + iteratorSymbolName: ast.SymbolNameAsyncIteratorProperty, getGlobalIteratorType: c.getGlobalAsyncIteratorType, getGlobalIterableType: c.getGlobalAsyncIterableType, getGlobalIterableTypeChecked: c.getGlobalAsyncIterableTypeChecked, @@ -1342,7 +1342,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[unique.Make("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")) } @@ -1385,31 +1385,31 @@ func (c *Checker) initializeChecker() { } c.addUndefinedToGlobalsOrErrorOnRedeclaration() c.valueSymbolLinks.Get(c.undefinedSymbol).resolvedType = c.undefinedWideningType - c.valueSymbolLinks.Get(c.argumentsSymbol).resolvedType = c.getGlobalType(unique.Make("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(unique.Make("Array"), 1 /*arity*/, true /*reportErrors*/) - c.globalObjectType = c.getGlobalType(unique.Make("Object"), 0 /*arity*/, true /*reportErrors*/) - c.globalFunctionType = c.getGlobalType(unique.Make("Function"), 0 /*arity*/, true /*reportErrors*/) - c.globalCallableFunctionType = c.getGlobalStrictFunctionType(unique.Make("CallableFunction")) - c.globalNewableFunctionType = c.getGlobalStrictFunctionType(unique.Make("NewableFunction")) - c.globalStringType = c.getGlobalType(unique.Make("String"), 0 /*arity*/, true /*reportErrors*/) - c.globalNumberType = c.getGlobalType(unique.Make("Number"), 0 /*arity*/, true /*reportErrors*/) - c.globalBooleanType = c.getGlobalType(unique.Make("Boolean"), 0 /*arity*/, true /*reportErrors*/) - c.globalRegExpType = c.getGlobalType(unique.Make("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(unique.Make("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(unique.Make("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) @@ -1700,15 +1700,15 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast. } func (c *Checker) checkAndReportErrorForExportingPrimitiveType(errorLocation *ast.Node, name ast.SymbolName) bool { - if isPrimitiveTypeName(name.Value()) && errorLocation.Parent.Kind == ast.KindExportSpecifier { + 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.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 ast.SymbolName, meaning ast.SymbolFlags) bool { @@ -1734,7 +1734,7 @@ func (c *Checker) checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocatio func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags) bool { if meaning&ast.SymbolFlagsValue != 0 { - if isPrimitiveTypeName(name.Value()) { + if isPrimitiveTypeName(name) { grandparent := errorLocation.Parent.Parent if grandparent != nil && grandparent.Parent != nil && ast.IsHeritageClause(grandparent) { heritageKind := grandparent.AsHeritageClause().Token @@ -1760,10 +1760,10 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsValue(errorLocation *ast.Node if isExportAssignmentExpressionName(errorLocation) { return true } - if isES2015OrLaterConstructorName(name.Value()) { + 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.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.Value(), core.IfElse(name == unique.Make("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.Value()) } @@ -1774,8 +1774,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 { @@ -2636,7 +2636,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), unique.Make("prototype")) + proto := c.getPropertyOfType(c.getTypeOfSymbol(symbol), ast.SymbolNamePrototype) if proto != nil { t = c.getTypeOfSymbol(proto) } @@ -3262,7 +3262,7 @@ 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() == unique.Make("prototype") { + 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, @@ -4475,7 +4475,7 @@ func (c *Checker) checkClassForStaticPropertyNameConflicts(node *ast.Node) { if isStaticMember && memberNameNode != nil { memberName, _ := c.getEffectivePropertyNameForPropertyNameNode(memberNameNode) switch memberName { - case unique.Make("name"), unique.Make("length"), unique.Make("caller"), unique.Make("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, @@ -5626,7 +5626,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), unique.Make("with")) + return c.getTypeOfPropertyOfType(c.checkExpressionCached(options), ast.SymbolNameWith) } return nil } @@ -6735,21 +6735,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, unique.Make("next"), errorNode, diagnosticOutput), - c.getIterationTypesOfMethod(t, r, unique.Make("return"), errorNode, diagnosticOutput), - c.getIterationTypesOfMethod(t, r, unique.Make("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 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 != unique.Make("next") { + if method == nil && methodName != ast.SymbolNameNext { return IterationTypes{} } var methodType *Type - if method != nil && !(methodName == unique.Make("next") && method.Flags()&ast.SymbolFlagsOptional != 0) { - if methodName == unique.Make("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) @@ -6765,7 +6765,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes } if len(methodSignatures) == 0 { if errorNode != nil { - diagnostic := core.IfElse(methodName == unique.Make("next"), resolver.mustHaveANextMethodDiagnostic, resolver.mustBeAMethodDiagnostic) + diagnostic := core.IfElse(methodName == ast.SymbolNameNext, resolver.mustHaveANextMethodDiagnostic, resolver.mustBeAMethodDiagnostic) c.reportDiagnostic(NewDiagnosticForNode(errorNode, diagnostic, methodName.Value()), diagnosticOutput) } return IterationTypes{} @@ -6786,7 +6786,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 == unique.Make("next") { + if methodName == ast.SymbolNameNext { nextType = getMappedType(typeParameters[2], mapper) } return IterationTypes{getMappedType(typeParameters[0], mapper), getMappedType(typeParameters[1], mapper), nextType} @@ -6796,7 +6796,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes var methodParameterTypes []*Type var methodReturnTypes []*Type for _, signature := range methodSignatures { - if methodName != unique.Make("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)) @@ -6805,17 +6805,17 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes // `return()` method, respectively. var returnTypes []*Type var nextType *Type - if methodName != unique.Make("throw") { + if methodName != ast.SymbolNameThrow { var methodParameterType *Type if methodParameterTypes != nil { methodParameterType = c.getUnionType(methodParameterTypes) } else { methodParameterType = c.unknownType } - if methodName == unique.Make("next") { + if methodName == ast.SymbolNameNext { // The value of `next(value)` is *not* awaited by async generators nextType = methodParameterType - } else if methodName == unique.Make("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) @@ -6865,12 +6865,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, unique.Make("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, unique.Make("value") /* as __String */) + returnType = c.getTypeOfPropertyOfType(returnIteratorResult, ast.SymbolNameValue /* as __String */) } if yieldType == nil && returnType == nil { return IterationTypes{} @@ -6895,7 +6895,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, unique.Make("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) } @@ -6919,7 +6919,7 @@ func (c *Checker) getIterationDiagnosticDetails(use IterationUse, inputType *Typ if yieldType != nil { return diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, false } - if inputType.symbol != nil && isES2015OrLaterIterable(inputType.symbol.Name().Value()) { + if inputType.symbol != nil && isES2015OrLaterIterable(inputType.symbol.Name()) { return diagnostics.Type_0_can_only_be_iterated_through_when_using_the_downlevelIteration_flag_or_with_a_target_of_es2015_or_higher, true } if allowsStrings { @@ -6928,9 +6928,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 @@ -7892,8 +7892,8 @@ func (c *Checker) getUniqueTypeParameters(context *InferenceContext, typeParamet for _, tp := range typeParameters { name := tp.symbol.Name() if hasTypeParameterByName(context.inferredTypeParameters, name) || hasTypeParameterByName(result, name) { - newName := getUniqueTypeParameterName(core.Concatenate(context.inferredTypeParameters, result), name.Value()) - symbol := c.newSymbol(ast.SymbolFlagsTypeParameter, unique.Make(newName)) + newName := getUniqueTypeParameterName(core.Concatenate(context.inferredTypeParameters, result), name) + symbol := c.newSymbol(ast.SymbolFlagsTypeParameter, newName) newTypeParameter := c.newTypeParameter(symbol) newTypeParameter.AsTypeParameter().target = tp oldTypeParameters = append(oldTypeParameters, tp) @@ -7918,14 +7918,15 @@ func hasTypeParameterByName(typeParameters []*Type, name ast.SymbolName) bool { }) } -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) - if !hasTypeParameterByName(typeParameters, unique.Make(augmentedName)) { + augmentedName := unique.Make(baseText + strconv.Itoa(index)) + if !hasTypeParameterByName(typeParameters, augmentedName) { return augmentedName } index++ @@ -8499,7 +8500,7 @@ func (c *Checker) checkImportCallExpression(node *ast.Node) *Type { } } } - importAttributesType = c.getTypeOfPropertyOfType(optionsType, unique.Make("with")) + importAttributesType = c.getTypeOfPropertyOfType(optionsType, ast.SymbolNameWith) } if ast.IsSourcePhaseImportCall(node) { return c.createPromiseReturnType(node, c.getGlobalAbstractModuleSourceType()) @@ -8604,7 +8605,7 @@ func (c *Checker) isSymbolOrSymbolForCall(node *ast.Node) bool { if globalESSymbol == nil { return false } - return globalESSymbol == c.resolveName(left, unique.Make("Symbol"), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) + return globalESSymbol == c.resolveName(left, ast.SymbolNameSymbol, ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) } /** @@ -11900,7 +11901,7 @@ func hasCommonDomTypeName(t *Type) bool { return false } name := t.symbol.Name() - return name == unique.Make("EventTarget") || name == unique.Make("Node") || name == unique.Make("Element") || strings.HasPrefix(name.Value(), "HTML") && strings.HasSuffix(name.Value(), "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 { @@ -14105,8 +14106,8 @@ func (c *Checker) isReadonlyAssignmentDeclaration(node *ast.Node) bool { return false } propertyDescriptorType := c.checkExpressionCached(node.Arguments()[2]) - if valueType := c.getTypeOfPropertyOfType(propertyDescriptorType, unique.Make("value")); valueType != nil { - if writableProp := c.getPropertyOfType(propertyDescriptorType, unique.Make("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()) @@ -14117,7 +14118,7 @@ func (c *Checker) isReadonlyAssignmentDeclaration(node *ast.Node) bool { } return true } - return c.getTypeOfPropertyOfType(propertyDescriptorType, unique.Make("set")) == nil + return c.getTypeOfPropertyOfType(propertyDescriptorType, ast.SymbolNameSetProperty) == nil } func (c *Checker) isReadonlySymbol(symbol *ast.Symbol) bool { @@ -15160,7 +15161,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, unique.Make("__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 @@ -15176,7 +15177,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, unique.Make("__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 { @@ -17014,7 +17015,7 @@ func (c *Checker) getTypeOfVariableOrParameterOrPropertyWorker(symbol *ast.Symbo return c.reportCircularityError(symbol) } if symbol.Flags()&ast.SymbolFlagsModuleExports != 0 { - if symbol.Name() == unique.Make("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) @@ -18609,15 +18610,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, unique.Make("value")); valueType != nil { + if valueType := c.getTypeOfPropertyOfType(objectLiteralType, ast.SymbolNameValue); valueType != nil { return valueType } - if getFunc := c.getTypeOfPropertyOfType(objectLiteralType, unique.Make("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, unique.Make("set")); setFunc != nil { + if setFunc := c.getTypeOfPropertyOfType(objectLiteralType, ast.SymbolNameSetProperty); setFunc != nil { if setSig := c.getSingleCallSignature(setFunc); setSig != nil { return c.getTypeOfFirstParameterOfSignature(setSig) } @@ -19484,7 +19485,7 @@ func (c *Checker) getApplicableIndexInfo(t *Type, keyType *Type) *IndexInfo { } func (c *Checker) getApplicableIndexInfoForName(t *Type, name ast.SymbolName) *IndexInfo { - if isLateBoundName(name.Value()) { + if isLateBoundName(name) { return c.getApplicableIndexInfo(t, c.esSymbolType) } return c.getApplicableIndexInfo(t, c.getStringLiteralType(name.Value())) @@ -21814,26 +21815,26 @@ 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 = unique.Make("arg" + strconv.Itoa(i)) } - paramSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable|core.IfElse(isOptional && !isRestParam, ast.SymbolFlagsOptional, 0), unique.Make(paramName), + paramSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable|core.IfElse(isOptional && !isRestParam, ast.SymbolFlagsOptional, 0), paramName, core.IfElse(isRestParam, ast.CheckFlagsRestParameter, core.IfElse(isOptional, ast.CheckFlagsOptionalParameter, 0))) links := c.valueSymbolLinks.Get(paramSymbol) if isRestParam { @@ -21844,7 +21845,7 @@ func (c *Checker) combineUnionOrIntersectionParameters(left *Signature, right *S params[i] = paramSymbol } if needsExtraRestElement { - restParamSymbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, unique.Make("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 { @@ -22103,7 +22104,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name a } } else if isUnion { var indexInfo *IndexInfo - if !isLateBoundName(name.Value()) { + if !isLateBoundName(name) { indexInfo = c.getApplicableIndexInfoForName(t, name) } if indexInfo != nil { @@ -22711,7 +22712,7 @@ func (c *Checker) isDeclarationContainedBy(symbol *ast.Symbol, container *ast.Sy } func (c *Checker) isNamedMember(symbol *ast.Symbol, id ast.SymbolName) bool { - return !isReservedMemberName(id.Value()) && c.symbolIsValue(symbol) + return !isReservedMemberName(id) && c.symbolIsValue(symbol) } func (c *Checker) symbolIsValue(symbol *ast.Symbol) bool { @@ -24233,11 +24234,11 @@ func (c *Checker) isEmptyLiteralType(t *Type) bool { } func (c *Checker) isTupleLikeType(t *Type) bool { - if isTupleType(t) || c.getPropertyOfType(t, unique.Make("0")) != nil { + if isTupleType(t) || c.getPropertyOfType(t, ast.SymbolNameZero) != nil { return true } if c.isArrayLikeType(t) { - if lengthType := c.getTypeOfPropertyOfType(t, unique.Make("length")); lengthType != nil { + if lengthType := c.getTypeOfPropertyOfType(t, ast.SymbolNameLength); lengthType != nil { return everyType(lengthType, func(t *Type) bool { return t.flags&TypeFlagsNumberLiteral != 0 }) } } @@ -24555,7 +24556,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() == unique.Make("BuiltinIteratorReturn") { + if t == c.intrinsicMarkerType && symbol.Name() == ast.SymbolNameBuiltinIteratorReturn { t = c.getBuiltinIteratorReturnType() } } else { @@ -25383,9 +25384,9 @@ func (c *Checker) getGlobalStrictFunctionType(name ast.SymbolName) *Type { func (c *Checker) getGlobalImportMetaExpressionType() *Type { if c.deferredGlobalImportMetaExpressionType == nil { // Create a synthetic type `ImportMetaExpression { meta: MetaProperty }` - symbol := c.newSymbol(ast.SymbolFlagsNone, unique.Make("ImportMetaExpression")) + symbol := c.newSymbol(ast.SymbolFlagsNone, ast.SymbolNameImportMetaExpression) importMetaType := c.getGlobalImportMetaType() - metaPropertySymbol := c.newSymbolEx(ast.SymbolFlagsProperty, unique.Make("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}) @@ -25497,7 +25498,7 @@ func (c *Checker) createTupleTargetType(elementInfos []TupleElementInfo, readonl } } fixedLength := len(members) - lengthSymbol := c.newSymbolEx(ast.SymbolFlagsProperty, unique.Make("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 { @@ -28477,7 +28478,7 @@ func (c *Checker) expandSignatureParametersWithTupleMembers(signature *Signature case flags&ElementFlagsOptional != 0: checkFlags = ast.CheckFlagsOptionalParameter } - symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, unique.Make(associatedNames[i]), checkFlags) + symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, associatedNames[i], checkFlags) links := c.valueSymbolLinks.Get(symbol) if flags&ElementFlagsRest != 0 { links.resolvedType = c.createArrayType(t) @@ -28489,10 +28490,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 @@ -28508,7 +28509,7 @@ func (c *Checker) getUniqAssociatedNamesFromTupleType(t *TypeReference, restSymb counters[name] = 0 } counters[name]++ - candidateName := name + "_" + strconv.Itoa(counters[name]) + candidateName := unique.Make(name.Value() + "_" + strconv.Itoa(counters[name])) if counters[candidateName] == 0 { names[i] = candidateName break @@ -29700,7 +29701,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, unique.Make("then")) + thenFunction := c.getTypeOfPropertyOfType(t, ast.SymbolNameThen) // TODO: GH#18217 if IsTypeAny(thenFunction) { return nil @@ -30942,7 +30943,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(unique.Make("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)) { @@ -30965,9 +30966,9 @@ func (c *Checker) getLegacyDecoratorCallSignature(decorator *ast.Node) *Signatur keyType = c.getClassElementPropertyKeyType(node.Parent) } indexType := c.getNumberLiteralType(jsnum.Number(index)) - targetParam := c.newParameter(unique.Make("target"), targetType) - keyParam := c.newParameter(unique.Make("propertyKey"), keyType) - indexParam := c.newParameter(unique.Make("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) { @@ -30976,9 +30977,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(unique.Make("target"), targetType) + targetParam := c.newParameter(ast.SymbolNameTarget, targetType) keyType := c.getClassElementPropertyKeyType(node) - keyParam := c.newParameter(unique.Make("propertyKey"), keyType) + keyParam := c.newParameter(ast.SymbolNamePropertyKey, keyType) returnType := c.voidType if !ast.IsPropertyDeclaration(node) { returnType = c.newTypedPropertyDescriptorType(c.getTypeOfNode(node)) @@ -30986,7 +30987,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(unique.Make("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})) @@ -31214,9 +31215,9 @@ func (c *Checker) getClassMemberDecoratorContextOverrideType(nameType *Type, isP return overrideType } members := make(ast.SymbolTable) - members[unique.Make("name")] = c.newProperty(unique.Make("name"), nameType) - members[unique.Make("private")] = c.newProperty(unique.Make("private"), core.IfElse(isPrivate, c.trueType, c.falseType)) - members[unique.Make("static")] = c.newProperty(unique.Make("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 @@ -31259,16 +31260,16 @@ func (c *Checker) newClassAccessorDecoratorResultType(thisType *Type, valueType } func (c *Checker) newClassFieldDecoratorInitializerMutatorType(thisType *Type, valueType *Type) *Type { - thisParam := c.newParameter(unique.Make("this"), thisType) - valueParam := c.newParameter(unique.Make("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(unique.Make("target"), targetType) - contextParam := c.newParameter(unique.Make("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) } @@ -31284,7 +31285,7 @@ func (c *Checker) newGetterFunctionType(t *Type) *Type { } func (c *Checker) newSetterFunctionType(t *Type) *Type { - valueParam := c.newParameter(unique.Make("value"), t) + valueParam := c.newParameter(ast.SymbolNameValue, t) return c.newFunctionType(nil, nil /*thisParameter*/, []*ast.Symbol{valueParam}, c.voidType) } @@ -31917,7 +31918,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.getMember(unique.Make("bind")) != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) + return len(resolved.getSignatures()) != 0 || resolved.getMember(ast.SymbolNameBind) != nil && c.isTypeSubtypeOf(t, c.globalFunctionType) } func (c *Checker) getTypeWithFacts(t *Type, include TypeFacts) *Type { @@ -32224,7 +32225,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, unique.Make("then")) + thenFunction := c.getTypeOfPropertyOfType(t, ast.SymbolNameThen) return thenFunction != nil && len(c.getSignaturesOfType(c.getTypeWithFacts(thenFunction, TypeFactsNEUndefinedOrNull), SignatureKindCall)) != 0 } @@ -32413,7 +32414,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().getMember(unique.Make("meta")) + return c.getGlobalImportMetaExpressionType().AsObjectType().getMember(ast.SymbolNameMeta) } // no other meta properties are valid syntax, thus no others should have symbols return nil diff --git a/tsc/internal/checker/emitresolver.go b/tsc/internal/checker/emitresolver.go index 34f13c2ce0560..8de3b02535109 100644 --- a/tsc/internal/checker/emitresolver.go +++ b/tsc/internal/checker/emitresolver.go @@ -299,7 +299,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(unique.Make("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 @@ -604,11 +604,11 @@ 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() - symbol := r.checker.resolveName(location, unique.Make(name), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) + symbol := r.checker.resolveName(location, name, ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) return symbol != nil } diff --git a/tsc/internal/checker/flow.go b/tsc/internal/checker/flow.go index a6c93ba15c2f2..ccc779beea053 100644 --- a/tsc/internal/checker/flow.go +++ b/tsc/internal/checker/flow.go @@ -769,7 +769,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, unique.Make("prototype")) + prototypeProperty := c.getPropertyOfType(identifierType, ast.SymbolNamePrototype) if prototypeProperty == nil { return t } @@ -965,7 +965,7 @@ func (c *Checker) getNarrowedTypeWorker(t *Type, candidate *Type, assumeTrue boo } func (c *Checker) getInstanceType(constructorType *Type) *Type { - prototypePropertyType := c.getTypeOfPropertyOfType(constructorType, unique.Make("prototype")) + prototypePropertyType := c.getTypeOfPropertyOfType(constructorType, ast.SymbolNamePrototype) if prototypePropertyType != nil && !IsTypeAny(prototypePropertyType) { return prototypePropertyType } @@ -2093,7 +2093,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(unique.Make("hasInstance")) + hasInstancePropertyName := c.getPropertyNameForKnownSymbolName(ast.SymbolNameHasInstance) if c.allTypesAssignableToKind(t, TypeFlagsNonPrimitive) { hasInstanceProperty := c.getPropertyOfType(t, hasInstancePropertyName) if hasInstanceProperty != nil { diff --git a/tsc/internal/checker/grammarchecks.go b/tsc/internal/checker/grammarchecks.go index 9198a55c3b736..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 { @@ -1111,9 +1111,9 @@ func (c *Checker) checkGrammarObjectLiteralExpression(node *ast.ObjectLiteralExp continue } - existingKind := seen[effectiveName.Value()] + existingKind := seen[effectiveName] if existingKind == 0 { - seen[effectiveName.Value()] = currentKind + seen[effectiveName] = currentKind } else { if (currentKind&DeclarationMeaningMethod != 0) && (existingKind&DeclarationMeaningMethod != 0) { c.grammarErrorOnNode(name, diagnostics.Duplicate_identifier_0, scanner.GetTextOfNode(name)) @@ -1121,7 +1121,7 @@ func (c *Checker) checkGrammarObjectLiteralExpression(node *ast.ObjectLiteralExp c.grammarErrorOnNode(name, diagnostics.An_object_literal_cannot_have_multiple_properties_with_the_same_name, scanner.GetTextOfNode(name)) } else if (currentKind&DeclarationMeaningGetOrSetAccessor != 0) && (existingKind&DeclarationMeaningGetOrSetAccessor != 0) { if existingKind != DeclarationMeaningGetOrSetAccessor && currentKind != existingKind { - seen[effectiveName.Value()] = currentKind | existingKind + seen[effectiveName] = currentKind | existingKind } else { return c.grammarErrorOnNode(name, diagnostics.An_object_literal_cannot_have_multiple_get_Slashset_accessors_with_the_same_name) } diff --git a/tsc/internal/checker/jsx.go b/tsc/internal/checker/jsx.go index 2563d004874cc..ce5d452c8393e 100644 --- a/tsc/internal/checker/jsx.go +++ b/tsc/internal/checker/jsx.go @@ -52,16 +52,16 @@ var JsxNames = struct { IntrinsicClassAttributes ast.SymbolName LibraryManagedAttributes ast.SymbolName }{ - JSX: unique.Make("JSX"), - IntrinsicElements: unique.Make("IntrinsicElements"), - ElementClass: unique.Make("ElementClass"), - ElementAttributesPropertyNameContainer: unique.Make("ElementAttributesProperty"), - ElementChildrenAttributeNameContainer: unique.Make("ElementChildrenAttribute"), - Element: unique.Make("Element"), - ElementType: unique.Make("ElementType"), - IntrinsicAttributes: unique.Make("IntrinsicAttributes"), - IntrinsicClassAttributes: unique.Make("IntrinsicClassAttributes"), - LibraryManagedAttributes: unique.Make("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 { @@ -308,7 +308,7 @@ 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 = unique.Make("children") + childrenPropName = ast.SymbolNameChildren } childrenNameType := c.getStringLiteralType(childrenPropName.Value()) childrenTargetType := c.getIndexedAccessType(target, childrenNameType) @@ -487,10 +487,10 @@ func (c *Checker) getSuggestedSymbolForNonexistentJSXAttribute(name ast.SymbolNa properties := c.getPropertiesOfType(containingType) var jsxSpecific *ast.Symbol switch name { - case unique.Make("for"): - jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return x.Name() == unique.Make("htmlFor") }) - case unique.Make("class"): - jsxSpecific = core.Find(properties, func(x *ast.Symbol) bool { return x.Name() == unique.Make("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 @@ -950,7 +950,7 @@ func (c *Checker) getJsxPropsTypeFromClassType(sig *Signature, context *ast.Node case ast.EmptySymbolName: attributesType = c.getReturnTypeOfSignature(sig) default: - attributesType = c.getJsxPropsTypeForSignatureFromMember(sig, forcedLookupLocation.Value()) + 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.Value()) @@ -987,7 +987,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, @@ -1000,7 +1000,7 @@ func (c *Checker) getJsxPropsTypeForSignatureFromMember(sig *Signature, forcedLo if IsTypeAny(instance) { return instance } - propType := c.getTypeOfPropertyOfType(instance, unique.Make(forcedLookupLocation)) + propType := c.getTypeOfPropertyOfType(instance, forcedLookupLocation) if propType == nil { return nil } @@ -1013,7 +1013,7 @@ func (c *Checker) getJsxPropsTypeForSignatureFromMember(sig *Signature, forcedLo if IsTypeAny(instanceType) { return instanceType } - return c.getTypeOfPropertyOfType(instanceType, unique.Make(forcedLookupLocation)) + return c.getTypeOfPropertyOfType(instanceType, forcedLookupLocation) } func (c *Checker) getJsxManagedAttributesFromLocatedAttributes(context *ast.Node, ns *ast.Symbol, attributesType *Type) *Type { @@ -1078,7 +1078,7 @@ func (c *Checker) getJsxElementPropertiesName(jsxNamespace *ast.Symbol) ast.Symb 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 unique.Make("children") + return ast.SymbolNameChildren } return c.getNameFromJsxElementAttributesContainer(JsxNames.ElementChildrenAttributeNameContainer, jsxNamespace) } @@ -1178,7 +1178,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, unique.Make("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) } diff --git a/tsc/internal/checker/nodebuilder_hover.go b/tsc/internal/checker/nodebuilder_hover.go index a105f5f200f8b..7333d6525bc05 100644 --- a/tsc/internal/checker/nodebuilder_hover.go +++ b/tsc/internal/checker/nodebuilder_hover.go @@ -2,7 +2,6 @@ package checker import ( "fmt" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -153,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() != unique.Make("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) @@ -598,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() == unique.Make("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 87e56f9972fb8..d0850f2979386 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -775,20 +775,20 @@ func (b *NodeBuilderImpl) createAccessFromSymbolChain(chain []*ast.Symbol, index if exports != nil { // avoid exhaustive iteration in the common case res, ok := exports[symbol.Name()] - if symbol.Name() != ast.InternalSymbolNameExportEquals && !isLateBoundName(symbol.Name().Value()) && ok && res != nil && b.ch.getSymbolIfSameReference(res, symbol) != nil { + if symbol.Name() != ast.InternalSymbolNameExportEquals && !isLateBoundName(symbol.Name()) && ok && res != nil && b.ch.getSymbolIfSameReference(res, symbol) != nil { 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.Value()) && name != ast.InternalSymbolNameExportEquals { - results[ex] = name.Value() + if b.ch.getSymbolIfSameReference(ex, symbol) != nil && !isLateBoundName(name) && name != ast.InternalSymbolNameExportEquals { + results[ex] = name // break // must collect all results and sort them - exports are randomly iterated } } resultSymbols := slices.Collect(maps.Keys(results)) if len(resultSymbols) > 0 { b.ch.sortSymbols(resultSymbols) - symbolName = results[resultSymbols[0]] + symbolName = results[resultSymbols[0]].Value() } } } @@ -1505,30 +1505,30 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi } } if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 { - rawText := result.Text() - i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(unique.Make(rawText)) - text := rawText + rawName := unique.Make(result.Text()) + i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(rawName) + name := rawName for true { - if !b.ctx.typeParameterNamesByText.Has(unique.Make(text)) && !b.typeParameterShadowsOtherTypeParameterInScope(unique.Make(text), typeParameter) { + if !b.ctx.typeParameterNamesByText.Has(name) && !b.typeParameterShadowsOtherTypeParameterInScope(name, typeParameter) { break } i++ - text = fmt.Sprintf("%s_%d", rawText, i) + name = unique.Make(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(unique.Make(rawText), i) + b.ctx.typeParameterNamesByTextNextNameCount.Set(rawName, i) b.ctx.typeParameterNames.Set(typeParameter.id, result.AsIdentifier()) - b.ctx.typeParameterNamesByText.Add(unique.Make(text)) + b.ctx.typeParameterNamesByText.Add(name) } return result.AsIdentifier() @@ -1569,7 +1569,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, unique.Make("T")), + b.ch.newSymbol(ast.SymbolFlagsTypeParameter, ast.SymbolNameT), ) name := b.typeParameterToName(newConstraintParam) target := t.Target() @@ -1584,7 +1584,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, unique.Make("T")), + b.ch.newSymbol(ast.SymbolFlagsTypeParameter, ast.SymbolNameT), ) name := b.typeParameterToName(newParam) newTypeVariable = b.f.NewTypeReferenceNode(name.AsNode(), nil) @@ -2001,13 +2001,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 { @@ -2016,15 +2016,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 = unique.Make(fmt.Sprintf("%s_%d", names[i].Value(), counter)) _, ok := uniqueNames[name] if ok { counter++ @@ -2061,7 +2061,7 @@ func (c *Checker) getExpandedParameters(sig *Signature, skipUnionExpanding bool) case flags&ElementFlagsOptional != 0: checkFlags = ast.CheckFlagsOptionalParameter } - symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, unique.Make(name), checkFlags) + symbol := c.newSymbolEx(ast.SymbolFlagsFunctionScopedVariable, name, checkFlags) links := c.valueSymbolLinks.Get(symbol) if flags&ElementFlagsRest != 0 { links.resolvedType = c.createArrayType(t) @@ -2602,7 +2602,7 @@ func (b *NodeBuilderImpl) addPropertyToElementList(propertySymbol *ast.Symbol, t } saveEnclosingDeclaration := b.ctx.enclosingDeclaration b.ctx.enclosingDeclaration = nil - if isLateBoundName(propertySymbol.Name().Value()) { + if isLateBoundName(propertySymbol.Name()) { if len(propertySymbol.Declarations()) > 0 { decl := propertySymbol.Declarations()[0] if b.ch.hasLateBindableName(decl) { @@ -2669,7 +2669,7 @@ func (b *NodeBuilderImpl) addPropertyToElementList(propertySymbol *ast.Symbol, t b.setCommentRange(fakeGetterDeclaration, propDeclaration) typeElements = append(typeElements, fakeGetterDeclaration) - setterParam := b.ch.newSymbol(ast.SymbolFlagsFunctionScopedVariable, unique.Make("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{ @@ -3044,7 +3044,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, unique.Make("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 @@ -3134,7 +3134,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]), ) @@ -3532,7 +3532,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { if !b.shouldExpandType(t, true /*isAlias*/) { sym := t.alias.Symbol() typeArgumentNodes := b.mapToTypeNodes(t.alias.TypeArguments(), false /*isBareList*/) - if isReservedMemberName(sym.Name().Value()) && sym.Flags()&ast.SymbolFlagsClass == 0 { + if isReservedMemberName(sym.Name()) && sym.Flags()&ast.SymbolFlagsClass == 0 { return b.f.NewTypeReferenceNode(b.f.NewIdentifier(""), typeArgumentNodes) } if typeArgumentNodes != nil && len(typeArgumentNodes.Nodes) == 1 && sym == b.ch.globalArrayType.symbol { @@ -3681,7 +3681,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { if !b.ch.isNoInferType(t) { return typeNode } - noInferSymbol := b.ch.getGlobalTypeAliasSymbol(unique.Make("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/relater.go b/tsc/internal/checker/relater.go index 20d8809d97a3d..48ec8677a4abb 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -667,7 +667,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, unique.Make("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) @@ -723,7 +723,7 @@ func (c *Checker) isKnownProperty(targetType *Type, name ast.SymbolName, isCompa // we should remove this exception. if c.getPropertyOfObjectType(targetType, name) != nil || c.getApplicableIndexInfoForName(targetType, name) != nil || - isLateBoundName(name.Value()) && c.getIndexInfoOfType(targetType, c.stringType) != nil || + isLateBoundName(name) && c.getIndexInfoOfType(targetType, c.stringType) != nil || isComparingJsxAttributes && isHyphenatedJsxName(name.Value()) { // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true @@ -1617,7 +1617,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 } @@ -1963,10 +1963,10 @@ 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().Value() + return signature.parameters[pos].Name() } restParameter := signature.parameters[paramCount] restType := c.getTypeOfSymbol(restParameter) @@ -1974,26 +1974,24 @@ func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) stri index := pos - paramCount return c.getTupleElementLabel(restType.TargetTupleType().elementInfos[index], restParameter, index) } - return restParameter.Name().Value() + 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 unique.Make(elementInfo.labeledDeclaration.Name().Text()) } 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().Value() - } else { - rootName = "arg" + rootName = restSymbol.Name() } - return rootName + "_" + strconv.Itoa(index) + return unique.Make(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: @@ -2011,9 +2009,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 unique.Make(name) } - return name + "_" + strconv.Itoa(index) + return unique.Make(name + "_" + strconv.Itoa(index)) } // given // (...[x]: [number]) => ... @@ -2027,9 +2025,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 unique.Make(name) } - return name + "_n" + return unique.Make(name + "_n") case ast.KindArrayBindingPattern: if hasDotDotDotToken(node) { elements := node.Name().Elements() @@ -2047,7 +2045,7 @@ func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index i } } } - return "arg_" + strconv.Itoa(index) + return unique.Make("arg_" + strconv.Itoa(index)) } func (c *Checker) getTypePredicateOfSignature(sig *Signature) *TypePredicate { @@ -4290,7 +4288,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.Value()) || name == unique.Make("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) diff --git a/tsc/internal/checker/services.go b/tsc/internal/checker/services.go index 207dba6664232..4740c8cb9fc5e 100644 --- a/tsc/internal/checker/services.go +++ b/tsc/internal/checker/services.go @@ -133,10 +133,10 @@ 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.Value()) { - cb(exportedSymbol, key.Value()) + if !isReservedMemberName(key) { + cb(exportedSymbol, key) } } @@ -157,7 +157,7 @@ func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb } for name, symbol := range c.resolveStructuredTypeMembers(reducedType).getMembers() { if c.isNamedMember(symbol, name) { - cb(symbol, name.Value()) + cb(symbol, name) } } } @@ -825,13 +825,13 @@ 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).Value() + name = getPropertyNameFromType(nameType) } var expected *Type - if name != "" { - expected = c.getTypeOfPropertyOfType(contextualType, unique.Make(name)) + if name != ast.EmptySymbolName { + expected = c.getTypeOfPropertyOfType(contextualType, name) } return expected != nil && isLiteralType(expected) && !c.isTypeAssignableTo(c.getTypeOfNode(property), expected) }) @@ -978,26 +978,26 @@ func (c *Checker) GetContextualTypeForArrayLiteralAtPosition(contextualArrayType } var knownGenericTypeNames = map[ast.SymbolName]struct{}{ - unique.Make("Array"): {}, - unique.Make("ArrayLike"): {}, - unique.Make("ReadonlyArray"): {}, - unique.Make("Promise"): {}, - unique.Make("PromiseLike"): {}, - unique.Make("Iterable"): {}, - unique.Make("IterableIterator"): {}, - unique.Make("AsyncIterable"): {}, - unique.Make("Set"): {}, - unique.Make("WeakSet"): {}, - unique.Make("ReadonlySet"): {}, - unique.Make("Map"): {}, - unique.Make("WeakMap"): {}, - unique.Make("ReadonlyMap"): {}, - unique.Make("Partial"): {}, - unique.Make("Required"): {}, - unique.Make("Readonly"): {}, - unique.Make("Pick"): {}, - unique.Make("Omit"): {}, - unique.Make("NonNullable"): {}, + 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 { diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index 7820f34634860..ccf90169c2009 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -1096,7 +1096,7 @@ func isVariableDeclarationInVariableStatement(node *ast.Node) bool { } func IsKnownSymbol(symbol *ast.Symbol) bool { - return isLateBoundName(symbol.Name().Value()) + return isLateBoundName(symbol.Name()) } func IsPrivateIdentifierSymbol(symbol *ast.Symbol) bool { @@ -1106,7 +1106,8 @@ func IsPrivateIdentifierSymbol(symbol *ast.Symbol) bool { 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] == '@' } @@ -1415,29 +1416,29 @@ type FeatureMapEntry struct { var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { return map[ast.SymbolName][]FeatureMapEntry{ - unique.Make("Array"): { + 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"}}, }, - unique.Make("Iterator"): { + ast.SymbolNameIterator: { {lib: "es2015", props: []string{}}, }, - unique.Make("IteratorConstructor"): { + ast.SymbolNameIteratorConstructor: { {lib: "es2026", props: []string{"concat"}}, }, - unique.Make("RawJSON"): { + ast.SymbolNameRawJSON: { {lib: "es2026", props: []string{}}, }, - unique.Make("JSON"): { + ast.SymbolNameJSON: { {lib: "es2026", props: []string{"isRawJSON", "rawJSON"}}, }, - unique.Make("AsyncIterator"): { + ast.SymbolNameAsyncIterator: { {lib: "es2015", props: []string{}}, }, - unique.Make("ArrayBuffer"): { + ast.SymbolNameArrayBuffer: { {lib: "es2024", props: []string{ "maxByteLength", "resizable", @@ -1447,7 +1448,7 @@ var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { "transferToFixedLength", }}, }, - unique.Make("Atomics"): { + ast.SymbolNameAtomics: { {lib: "es2017", props: []string{ "add", "and", @@ -1466,7 +1467,7 @@ var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { "waitAsync", }}, }, - unique.Make("SharedArrayBuffer"): { + ast.SymbolNameSharedArrayBuffer: { {lib: "es2017", props: []string{ "byteLength", "slice", @@ -1477,59 +1478,59 @@ var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { "grow", }}, }, - unique.Make("AsyncIterable"): { + ast.SymbolNameAsyncIterable: { {lib: "es2018", props: []string{}}, }, - unique.Make("AsyncIterableIterator"): { + ast.SymbolNameAsyncIterableIterator: { {lib: "es2018", props: []string{}}, }, - unique.Make("AsyncGenerator"): { + ast.SymbolNameAsyncGenerator: { {lib: "es2018", props: []string{}}, }, - unique.Make("AsyncGeneratorFunction"): { + ast.SymbolNameAsyncGeneratorFunction: { {lib: "es2018", props: []string{}}, }, - unique.Make("RegExp"): { + ast.SymbolNameRegExp: { {lib: "es2015", props: []string{"flags", "sticky", "unicode"}}, {lib: "es2018", props: []string{"dotAll"}}, {lib: "es2024", props: []string{"unicodeSets"}}, }, - unique.Make("RegExpConstructor"): { + ast.SymbolNameRegExpConstructor: { {lib: "es2025", props: []string{"escape"}}, }, - unique.Make("Reflect"): { + ast.SymbolNameReflect: { {lib: "es2015", props: []string{"apply", "construct", "defineProperty", "deleteProperty", "get", "getOwnPropertyDescriptor", "getPrototypeOf", "has", "isExtensible", "ownKeys", "preventExtensions", "set", "setPrototypeOf"}}, }, - unique.Make("ArrayConstructor"): { + ast.SymbolNameArrayConstructor: { {lib: "es2015", props: []string{"from", "of"}}, {lib: "es2026", props: []string{"fromAsync"}}, }, - unique.Make("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"}}, }, - unique.Make("NumberConstructor"): { + ast.SymbolNameNumberConstructor: { {lib: "es2015", props: []string{"isFinite", "isInteger", "isNaN", "isSafeInteger", "parseFloat", "parseInt"}}, }, - unique.Make("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"}}, }, - unique.Make("Map"): { + ast.SymbolNameMap: { {lib: "es2015", props: []string{"entries", "keys", "values"}}, {lib: "es2026", props: []string{ "getOrInsert", "getOrInsertComputed", }}, }, - unique.Make("MapConstructor"): { + ast.SymbolNameMapConstructor: { {lib: "es2024", props: []string{"groupBy"}}, }, - unique.Make("Set"): { + ast.SymbolNameSet: { {lib: "es2015", props: []string{"entries", "keys", "values"}}, {lib: "es2025", props: []string{ "union", @@ -1541,28 +1542,28 @@ var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { "isDisjointFrom", }}, }, - unique.Make("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"}}, }, - unique.Make("Symbol"): { + ast.SymbolNameSymbol: { {lib: "es2015", props: []string{"for", "keyFor"}}, {lib: "es2019", props: []string{"description"}}, }, - unique.Make("WeakMap"): { + ast.SymbolNameWeakMap: { {lib: "es2015", props: []string{}}, {lib: "es2026", props: []string{ "getOrInsert", "getOrInsertComputed", }}, }, - unique.Make("WeakSet"): { + ast.SymbolNameWeakSet: { {lib: "es2015", props: []string{}}, }, - unique.Make("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"}}, @@ -1571,33 +1572,33 @@ var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { {lib: "es2022", props: []string{"at"}}, {lib: "es2024", props: []string{"isWellFormed", "toWellFormed"}}, }, - unique.Make("StringConstructor"): { + ast.SymbolNameStringConstructor: { {lib: "es2015", props: []string{"fromCodePoint", "raw"}}, }, - unique.Make("DateTimeFormat"): { + ast.SymbolNameDateTimeFormat: { {lib: "es2017", props: []string{"formatToParts"}}, }, - unique.Make("Promise"): { + ast.SymbolNamePromise: { {lib: "es2015", props: []string{}}, {lib: "es2018", props: []string{"finally"}}, }, - unique.Make("RegExpMatchArray"): { + ast.SymbolNameRegExpMatchArray: { {lib: "es2018", props: []string{"groups"}}, }, - unique.Make("RegExpExecArray"): { + ast.SymbolNameRegExpExecArray: { {lib: "es2018", props: []string{"groups"}}, }, - unique.Make("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"}}, }, - unique.Make("NumberFormat"): { + ast.SymbolNameNumberFormat: { {lib: "es2018", props: []string{"formatToParts"}}, }, - unique.Make("SymbolConstructor"): { + ast.SymbolNameSymbolConstructor: { {lib: "es2020", props: []string{"matchAll"}}, {lib: "esnext", props: []string{ "metadata", @@ -1605,82 +1606,82 @@ var getFeatureMap = sync.OnceValue(func() map[ast.SymbolName][]FeatureMapEntry { "asyncDispose", }}, }, - unique.Make("DataView"): { + ast.SymbolNameDataView: { {lib: "es2020", props: []string{"setBigInt64", "setBigUint64", "getBigInt64", "getBigUint64"}}, {lib: "es2025", props: []string{"setFloat16", "getFloat16"}}, }, - unique.Make("BigInt"): { + ast.SymbolNameBigInt: { {lib: "es2020", props: []string{}}, }, - unique.Make("RelativeTimeFormat"): { + ast.SymbolNameRelativeTimeFormat: { {lib: "es2020", props: []string{"format", "formatToParts", "resolvedOptions"}}, }, - unique.Make("Int8Array"): { + ast.SymbolNameInt8Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("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"}}, }, - unique.Make("Uint8ClampedArray"): { + ast.SymbolNameUint8ClampedArray: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("Int16Array"): { + ast.SymbolNameInt16Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("Uint16Array"): { + ast.SymbolNameUint16Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("Int32Array"): { + ast.SymbolNameInt32Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("Uint32Array"): { + ast.SymbolNameUint32Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("Float16Array"): { + ast.SymbolNameFloat16Array: { {lib: "es2025", props: []string{}}, }, - unique.Make("Float32Array"): { + ast.SymbolNameFloat32Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("Float64Array"): { + ast.SymbolNameFloat64Array: { {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("BigInt64Array"): { + ast.SymbolNameBigInt64Array: { {lib: "es2020", props: []string{}}, {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("BigUint64Array"): { + ast.SymbolNameBigUint64Array: { {lib: "es2020", props: []string{}}, {lib: "es2022", props: []string{"at"}}, {lib: "es2023", props: []string{"findLastIndex", "findLast", "toReversed", "toSorted", "toSpliced", "with"}}, }, - unique.Make("Error"): { + ast.SymbolNameError: { {lib: "es2022", props: []string{"cause"}}, }, - unique.Make("ErrorConstructor"): { + ast.SymbolNameErrorConstructor: { {lib: "es2026", props: []string{"isError"}}, }, - unique.Make("Uint8ArrayConstructor"): { + ast.SymbolNameUint8ArrayConstructor: { {lib: "es2026", props: []string{"fromBase64", "fromHex"}}, }, - unique.Make("DisposableStack"): { + ast.SymbolNameDisposableStack: { {lib: "esnext", props: []string{}}, }, - unique.Make("AsyncDisposableStack"): { + ast.SymbolNameAsyncDisposableStack: { {lib: "esnext", props: []string{}}, }, - unique.Make("Date"): { + ast.SymbolNameDate: { {lib: "esnext", props: []string{"toTemporalInstant"}}, }, } @@ -1754,7 +1755,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] != '#' } @@ -1770,7 +1772,7 @@ func introducesArgumentsExoticObject(node *ast.Node) bool { func symbolsToArray(symbols ast.SymbolTable) []*ast.Symbol { var result []*ast.Symbol for id, symbol := range symbols { - if !isReservedMemberName(id.Value()) { + if !isReservedMemberName(id) { result = append(result, symbol) } } diff --git a/tsc/internal/ls/autoimport/extract.go b/tsc/internal/ls/autoimport/extract.go index 12e9b1edcfc9a..5731bb013a4c5 100644 --- a/tsc/internal/ls/autoimport/extract.go +++ b/tsc/internal/ls/autoimport/extract.go @@ -453,7 +453,7 @@ func getSyntax(symbol *ast.Symbol) ExportSyntax { func isUnusableName(name ast.SymbolName) bool { return name == (ast.SymbolName{}) || name == ast.EmptySymbolName || - name == unique.Make("_default") || + 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 2823eb96f91d0..299f14bea6bf2 100644 --- a/tsc/internal/ls/autoimport/fix.go +++ b/tsc/internal/ls/autoimport/fix.go @@ -32,7 +32,7 @@ import ( type newImportBinding struct { kind lsproto.ImportKind propertyName string - name string + name ast.SymbolName addAsTypeOnly lsproto.AddAsTypeOnly } @@ -84,12 +84,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 := unique.Make(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 // } @@ -195,8 +196,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 := unique.Make(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, @@ -216,10 +218,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: @@ -240,7 +242,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 { @@ -253,7 +255,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) @@ -376,7 +378,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 { @@ -387,7 +389,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)) } @@ -398,7 +400,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 { @@ -407,7 +409,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, @@ -447,7 +449,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, )) } @@ -456,7 +458,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...) @@ -476,7 +478,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) diff --git a/tsc/internal/ls/autoimport/import_adder.go b/tsc/internal/ls/autoimport/import_adder.go index 1c09c1ff4820d..6fea18017ca1b 100644 --- a/tsc/internal/ls/autoimport/import_adder.go +++ b/tsc/internal/ls/autoimport/import_adder.go @@ -216,14 +216,14 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.namedImports[symbolName] = &newImportBinding{ kind: lsproto.ImportKindNamed, - name: symbolName.Value(), + name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), propertyName: existingFix.namedImport.propertyName, } } else { // Default import debug.Assert( - entry.defaultImport == nil || unique.Make(entry.defaultImport.name) == symbolName, + entry.defaultImport == nil || entry.defaultImport.name == symbolName, "(Add to Existing) Default import should be missing or match symbolName", ) var prevTypeOnly lsproto.AddAsTypeOnly @@ -232,7 +232,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.defaultImport = &newImportBinding{ kind: lsproto.ImportKindDefault, - name: symbolName.Value(), + name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), } } @@ -247,7 +247,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { switch fix.ImportKind { case lsproto.ImportKindDefault: debug.Assert( - entry.defaultImport == nil || unique.Make(entry.defaultImport.name) == symbolName, + entry.defaultImport == nil || entry.defaultImport.name == symbolName, "(Add new) Default import should be missing or match symbolName", ) var prevTypeOnly lsproto.AddAsTypeOnly @@ -256,7 +256,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.defaultImport = &newImportBinding{ kind: lsproto.ImportKindDefault, - name: symbolName.Value(), + name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), } @@ -271,7 +271,7 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.namedImports[symbolName] = &newImportBinding{ kind: lsproto.ImportKindNamed, - name: symbolName.Value(), + name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), // !!! propertyName } @@ -288,30 +288,30 @@ func (adder *importAdder) AddImportFix(fix *Fix) { } entry.namedImports[symbolName] = &newImportBinding{ kind: lsproto.ImportKindCommonJS, - name: symbolName.Value(), + name: symbolName, addAsTypeOnly: reduceAddAsTypeOnlyValues(prevTypeOnly, fix.AddAsTypeOnly), // !!! propertyName } } else { debug.Assert( - entry.namespaceLikeImport == nil || unique.Make(entry.namespaceLikeImport.name) == symbolName, + entry.namespaceLikeImport == nil || entry.namespaceLikeImport.name == symbolName, "Namespacelike import should be missing or match symbolName", ) entry.namespaceLikeImport = &newImportBinding{ kind: lsproto.ImportKindCommonJS, - name: symbolName.Value(), + name: symbolName, addAsTypeOnly: fix.AddAsTypeOnly, } } case lsproto.ImportKindNamespace: debug.Assert( - entry.namespaceLikeImport == nil || unique.Make(entry.namespaceLikeImport.name) == symbolName, + entry.namespaceLikeImport == nil || entry.namespaceLikeImport.name == symbolName, "Namespacelike import should be missing or match symbolName", ) entry.namespaceLikeImport = &newImportBinding{ kind: lsproto.ImportKindNamespace, - name: symbolName.Value(), + name: symbolName, addAsTypeOnly: fix.AddAsTypeOnly, } } diff --git a/tsc/internal/ls/autoimport/index.go b/tsc/internal/ls/autoimport/index.go index f30de9bcf56cb..3f21c54eb2910 100644 --- a/tsc/internal/ls/autoimport/index.go +++ b/tsc/internal/ls/autoimport/index.go @@ -4,7 +4,6 @@ import ( "strings" "unicode" "unicode/utf8" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -23,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 } @@ -38,11 +38,10 @@ func (idx *Index[T]) Find(name string, caseSensitive bool) []T { } var results []T - nameKey := unique.Make(name) for _, entryIndex := range candidates { entry := idx.entries[entryIndex] entryName := entry.Name() - if (caseSensitive && entryName == nameKey) || (!caseSensitive && strings.EqualFold(entryName.Value(), name)) { + if (caseSensitive && entryName == name) || (!caseSensitive && strings.EqualFold(entryName.Value(), nameText)) { results = append(results, entry) } } diff --git a/tsc/internal/ls/autoimport/index_test.go b/tsc/internal/ls/autoimport/index_test.go index ef704f40bd131..e3b434ab1b323 100644 --- a/tsc/internal/ls/autoimport/index_test.go +++ b/tsc/internal/ls/autoimport/index_test.go @@ -26,10 +26,12 @@ func TestIndexFind(t *testing.T) { idx.insertAsWords(lower) idx.insertAsWords(upper) - assert.Assert(t, slices.Equal(idx.Find(strings.Clone("fooBar"), true), []*testEntry{lower})) - assert.Assert(t, slices.Equal(idx.Find("FooBar", true), []*testEntry{upper})) - assert.Assert(t, slices.Equal(idx.Find("FOOBAR", false), []*testEntry{lower, upper})) - assert.Equal(t, len(idx.Find("FOOBAR", true)), 0) + assert.Assert(t, slices.Equal(idx.Find(unique.Make(strings.Clone("fooBar")), true), []*testEntry{lower})) + assert.Assert(t, slices.Equal(idx.Find(upper.Name(), true), []*testEntry{upper})) + query := unique.Make(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})) } @@ -56,12 +58,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/view.go b/tsc/internal/ls/autoimport/view.go index 0dde88957e250..0a038b7abd502 100644 --- a/tsc/internal/ls/autoimport/view.go +++ b/tsc/internal/ls/autoimport/view.go @@ -3,6 +3,7 @@ package autoimport import ( "slices" "unicode" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -78,14 +79,18 @@ const ( ) func (v *View) Search(query string, kind QueryKind) []*Export { + var queryName ast.SymbolName + if kind != QueryKindWordPrefix { + queryName = unique.Make(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") } diff --git a/tsc/internal/ls/codeactions_missingmemberfixer.go b/tsc/internal/ls/codeactions_missingmemberfixer.go index 0a935be3889df..b8ade7d29654e 100644 --- a/tsc/internal/ls/codeactions_missingmemberfixer.go +++ b/tsc/internal/ls/codeactions_missingmemberfixer.go @@ -2,6 +2,7 @@ package ls import ( "strconv" + "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -111,7 +112,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{unique.Make(parameter.Name().Text())}, []*ast.TypeNode{f.createTypeNode(t, enclosingDeclaration, flags, nodeBuilder, idToSymbol)}, 1, ast.IsInJSFile(enclosingDeclaration)), nil /*type*/, nil /*fullSignature*/, f.createBody(body, quotePreference, signatureOnly), ), ) @@ -323,16 +324,16 @@ 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().Value()) + parameterNames = append(parameterNames, symbol.Name()) } parameters := createDummyParameters(f.changeTracker.NodeFactory, maxNonRestArgs, parameterNames, nil /*types*/, minArgumentCount, ast.IsInJSFile(enclosingDeclaration)) 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 +449,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 = unique.Make("arg" + strconv.Itoa(i)) } count := parameterNameCounts[parameterName] parameterNameCounts[parameterName] = count + 1 if count > 0 { - parameterName += strconv.Itoa(count) + parameterName = unique.Make(parameterName.Value() + strconv.Itoa(count)) } var questionToken *ast.QuestionToken @@ -481,7 +482,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) } diff --git a/tsc/internal/ls/completions.go b/tsc/internal/ls/completions.go index b68993000b8f2..41339490dba8b 100644 --- a/tsc/internal/ls/completions.go +++ b/tsc/internal/ls/completions.go @@ -4256,15 +4256,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(unique.Make("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(unique.Make("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(unique.Make("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 } diff --git a/tsc/internal/ls/importTracker.go b/tsc/internal/ls/importTracker.go index 57aa42a16b7ac..b27ab50b483bf 100644 --- a/tsc/internal/ls/importTracker.go +++ b/tsc/internal/ls/importTracker.go @@ -584,7 +584,7 @@ func getImportOrExportSymbol(node *ast.Node, symbol *ast.Symbol, checker *checke return nil } // Similarly, skip past the symbol for 'export =' - if importedSymbol.Name() == unique.Make("export=") { + if importedSymbol.Name() == ast.InternalSymbolNameExportEquals { importedSymbol = getExportEqualsLocalSymbol(importedSymbol, checker) if importedSymbol == nil { return nil 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/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index bd0aa96f7d513..caf0837392f6f 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -1194,7 +1194,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, unique.Make(nameText)) { // create a unique name that shares the same text as its' base nameNode = tx.Factory().NewUniqueNameEx(nameText, printer.AutoGenerateOptions{Flags: printer.GeneratedIdentifierFlagsOptimistic}) } else { @@ -2812,7 +2812,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, unique.Make(property)) && !ast.IsNonContextualKeyword(scanner.StringToToken(exportName.Text())) { // use exportName as localName if there won't be any conflicts or keyword issues localName = exportName } From 407198d378bfb2fc3fcfcfd578d07391331341a8 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 8 Oct 2026 14:52:03 -0700 Subject: [PATCH 03/14] Encapsulate interned names in a named SymbolName type Symbol names need their own constructor and representation boundary, without exposing generic string handles throughout the compiler. Give name serialization a lossless escaped spelling and distinguish unset names from valid empty names. --- tools/scripts/tsc/generate-enums.ts | 4 +- tsc/internal/api/session.go | 9 +- .../api/session_symbolresponse_test.go | 7 +- tsc/internal/ast/symbol.go | 480 ++++++++++-------- tsc/internal/ast/symbol_test.go | 139 +++-- tsc/internal/ast/utilities.go | 9 +- tsc/internal/binder/binder.go | 27 +- tsc/internal/binder/binder_test.go | 13 +- tsc/internal/binder/nameresolver.go | 8 +- tsc/internal/binder/referenceresolver.go | 6 +- tsc/internal/checker/checker.go | 183 ++++--- tsc/internal/checker/emitresolver.go | 7 +- tsc/internal/checker/emitsupport.go | 3 +- tsc/internal/checker/flow.go | 23 +- tsc/internal/checker/inference.go | 5 +- tsc/internal/checker/jsx.go | 21 +- tsc/internal/checker/nodebuilderimpl.go | 13 +- tsc/internal/checker/nodebuilderscopes.go | 4 +- tsc/internal/checker/pseudotypenodebuilder.go | 4 +- tsc/internal/checker/relater.go | 29 +- tsc/internal/checker/services.go | 13 +- tsc/internal/checker/symbolaccessibility.go | 3 +- tsc/internal/checker/types_test.go | 45 +- tsc/internal/checker/utilities.go | 5 +- tsc/internal/ls/autoimport/export.go | 2 +- tsc/internal/ls/autoimport/extract.go | 9 +- tsc/internal/ls/autoimport/fix.go | 7 +- tsc/internal/ls/autoimport/import_adder.go | 3 +- tsc/internal/ls/autoimport/index_test.go | 7 +- tsc/internal/ls/autoimport/util.go | 7 +- tsc/internal/ls/autoimport/view.go | 3 +- tsc/internal/ls/codeactions_importfixes.go | 15 +- .../ls/codeactions_missingmemberfixer.go | 7 +- tsc/internal/ls/completions.go | 15 +- tsc/internal/ls/definition.go | 7 +- tsc/internal/ls/findallreferences.go | 5 +- tsc/internal/ls/importTracker.go | 11 +- tsc/internal/ls/jsdoc.go | 3 +- tsc/internal/ls/lsutil/utilities.go | 3 +- tsc/internal/ls/sourcedefinition.go | 3 +- tsc/internal/ls/string_completions.go | 9 +- tsc/internal/ls/utilities.go | 3 +- tsc/internal/printer/namegenerator.go | 3 +- .../transformers/declarations/transform.go | 7 +- 44 files changed, 648 insertions(+), 541 deletions(-) diff --git a/tools/scripts/tsc/generate-enums.ts b/tools/scripts/tsc/generate-enums.ts index 260a7d720b632..7232166e5198d 100644 --- a/tools/scripts/tsc/generate-enums.ts +++ b/tools/scripts/tsc/generate-enums.ts @@ -278,12 +278,12 @@ function translateGoNumericExpression(expression: string, prefix: string): strin } /** - * Resolve a Go string expression, optionally interned with `unique.Make`, + * 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\((.*)\)$/, "$1"); + 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)) { diff --git a/tsc/internal/api/session.go b/tsc/internal/api/session.go index 731a79b1217fe..476404d575776 100644 --- a/tsc/internal/api/session.go +++ b/tsc/internal/api/session.go @@ -14,7 +14,6 @@ import ( "sync" "sync/atomic" "time" - "unique" "github.com/microsoft/TypeScript/tsc/internal/api/encoder" "github.com/microsoft/TypeScript/tsc/internal/api/requestfilesystem" @@ -2904,7 +2903,7 @@ func (s *Session) handleResolveName(ctx context.Context, params *ResolveNamePara return nil, err } - symbol := setup.checker.ResolveName(unique.Make(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 } @@ -4606,7 +4605,7 @@ func (s *Session) handleGetPropertyOfType(ctx context.Context, params *GetProper return nil, err } - prop := setup.checker.GetPropertyOfType(t, unique.Make(params.Name)) + prop := setup.checker.GetPropertyOfType(t, ast.MakeSymbolName(params.Name)) if prop == nil { return nil, nil } @@ -4627,7 +4626,7 @@ func (s *Session) handleGetTypeOfPropertyOfType(ctx context.Context, params *Get return nil, err } - return setup.sd.newTypeResponse(setup.projectID, setup.checker.GetTypeOfPropertyOfType(t, unique.Make(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. @@ -4898,7 +4897,7 @@ func (s *Session) handleGetMemberInModuleExports(ctx context.Context, params *Ge return nil, nil } - member := setup.checker.TryGetMemberInModuleExports(unique.Make(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 727a40858771f..85d353c6c00d7 100644 --- a/tsc/internal/api/session_symbolresponse_test.go +++ b/tsc/internal/api/session_symbolresponse_test.go @@ -4,7 +4,6 @@ import ( "strconv" "strings" "testing" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -63,7 +62,7 @@ func TestTransientSymbolWithFileDeclarationIsSnapshotOwned(t *testing.T) { class := sourceFile.Statements.Nodes[0] symbol := ast.NewSymbol() symbol.SetFlags(ast.SymbolFlagsClass | ast.SymbolFlagsTransient) - symbol.SetName(unique.Make("C")) + symbol.SetName(ast.MakeSymbolName("C")) symbol.SetDeclarations([]*ast.Node{class}) sd := newTestSnapshotData() @@ -87,7 +86,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()[unique.Make("property")] + member := class.Members()[ast.MakeSymbolName("property")] response := newFileSymbolResponse(member) assert.DeepEqual(t, response.Parent, reference) } @@ -111,6 +110,6 @@ func TestContentMappedSymbolsAreSnapshotOwned(t *testing.T) { assert.NilError(t, err) assert.Equal(t, resolved, class) - reference := newSymbolReference(class.Members()[unique.Make("property")]) + reference := newSymbolReference(class.Members()[ast.MakeSymbolName("property")]) assert.Equal(t, reference.File, "") } diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index 90bc2105939d1..1c085d4f09cd0 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -1,12 +1,16 @@ package ast import ( + "bytes" + "errors" "strings" "sync/atomic" + "unicode/utf8" "unique" "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 @@ -167,218 +171,284 @@ func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags { // 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 = unique.Handle[string] +type SymbolName unique.Handle[string] + +func MakeSymbolName(text string) SymbolName { + return SymbolName(unique.Make(text)) +} + +func (name SymbolName) Value() string { + return unique.Handle[string](name).Value() +} + +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 = unique.Make("") +var EmptySymbolName = MakeSymbolName("") type SymbolTable map[SymbolName]*Symbol // Fixed symbol names are interned once and shared by compiler consumers. var ( - SymbolNameZero = unique.Make("0") - SymbolNameUnresolved = unique.Make("<>") - SymbolNameAbstractModuleSource = unique.Make("AbstractModuleSource") - SymbolNameArray = unique.Make("Array") - SymbolNameArrayBuffer = unique.Make("ArrayBuffer") - SymbolNameArrayConstructor = unique.Make("ArrayConstructor") - SymbolNameArrayLike = unique.Make("ArrayLike") - SymbolNameAsyncDisposable = unique.Make("AsyncDisposable") - SymbolNameAsyncDisposableStack = unique.Make("AsyncDisposableStack") - SymbolNameAsyncGenerator = unique.Make("AsyncGenerator") - SymbolNameAsyncGeneratorFunction = unique.Make("AsyncGeneratorFunction") - SymbolNameAsyncIterable = unique.Make("AsyncIterable") - SymbolNameAsyncIterableIterator = unique.Make("AsyncIterableIterator") - SymbolNameAsyncIterator = unique.Make("AsyncIterator") - SymbolNameAsyncIteratorObject = unique.Make("AsyncIteratorObject") - SymbolNameAtomics = unique.Make("Atomics") - SymbolNameAwaited = unique.Make("Awaited") - SymbolNameBigInt = unique.Make("BigInt") - SymbolNameBigInt64Array = unique.Make("BigInt64Array") - SymbolNameBigUint64Array = unique.Make("BigUint64Array") - SymbolNameBoolean = unique.Make("Boolean") - SymbolNameBuiltinIteratorReturn = unique.Make("BuiltinIteratorReturn") - SymbolNameCallableFunction = unique.Make("CallableFunction") - SymbolNameCapitalize = unique.Make("Capitalize") - SymbolNameClassAccessorDecoratorContext = unique.Make("ClassAccessorDecoratorContext") - SymbolNameClassAccessorDecoratorResult = unique.Make("ClassAccessorDecoratorResult") - SymbolNameClassAccessorDecoratorTarget = unique.Make("ClassAccessorDecoratorTarget") - SymbolNameClassDecoratorContext = unique.Make("ClassDecoratorContext") - SymbolNameClassFieldDecoratorContext = unique.Make("ClassFieldDecoratorContext") - SymbolNameClassGetterDecoratorContext = unique.Make("ClassGetterDecoratorContext") - SymbolNameClassMethodDecoratorContext = unique.Make("ClassMethodDecoratorContext") - SymbolNameClassSetterDecoratorContext = unique.Make("ClassSetterDecoratorContext") - SymbolNameDataView = unique.Make("DataView") - SymbolNameDate = unique.Make("Date") - SymbolNameDateTimeFormat = unique.Make("DateTimeFormat") - SymbolNameDisposable = unique.Make("Disposable") - SymbolNameDisposableStack = unique.Make("DisposableStack") - SymbolNameElement = unique.Make("Element") - SymbolNameElementAttributesProperty = unique.Make("ElementAttributesProperty") - SymbolNameElementChildrenAttribute = unique.Make("ElementChildrenAttribute") - SymbolNameElementClass = unique.Make("ElementClass") - SymbolNameElementType = unique.Make("ElementType") - SymbolNameError = unique.Make("Error") - SymbolNameErrorConstructor = unique.Make("ErrorConstructor") - SymbolNameEventTarget = unique.Make("EventTarget") - SymbolNameExtract = unique.Make("Extract") - SymbolNameFloat16Array = unique.Make("Float16Array") - SymbolNameFloat32Array = unique.Make("Float32Array") - SymbolNameFloat64Array = unique.Make("Float64Array") - SymbolNameFunction = unique.Make("Function") - SymbolNameGenerator = unique.Make("Generator") - SymbolNameIArguments = unique.Make("IArguments") - SymbolNameImportAttributes = unique.Make("ImportAttributes") - SymbolNameImportCallOptions = unique.Make("ImportCallOptions") - SymbolNameImportMeta = unique.Make("ImportMeta") - SymbolNameImportMetaExpression = unique.Make("ImportMetaExpression") - SymbolNameInt16Array = unique.Make("Int16Array") - SymbolNameInt32Array = unique.Make("Int32Array") - SymbolNameInt8Array = unique.Make("Int8Array") - SymbolNameIntl = unique.Make("Intl") - SymbolNameIntrinsicAttributes = unique.Make("IntrinsicAttributes") - SymbolNameIntrinsicClassAttributes = unique.Make("IntrinsicClassAttributes") - SymbolNameIntrinsicElements = unique.Make("IntrinsicElements") - SymbolNameIterable = unique.Make("Iterable") - SymbolNameIterableIterator = unique.Make("IterableIterator") - SymbolNameIterator = unique.Make("Iterator") - SymbolNameIteratorConstructor = unique.Make("IteratorConstructor") - SymbolNameIteratorObject = unique.Make("IteratorObject") - SymbolNameIteratorReturnResult = unique.Make("IteratorReturnResult") - SymbolNameIteratorYieldResult = unique.Make("IteratorYieldResult") - SymbolNameJSON = unique.Make("JSON") - SymbolNameJSX = unique.Make("JSX") - SymbolNameK = unique.Make("K") - SymbolNameLibraryManagedAttributes = unique.Make("LibraryManagedAttributes") - SymbolNameLowercase = unique.Make("Lowercase") - SymbolNameMap = unique.Make("Map") - SymbolNameMapConstructor = unique.Make("MapConstructor") - SymbolNameMath = unique.Make("Math") - SymbolNameNaN = unique.Make("NaN") - SymbolNameNewableFunction = unique.Make("NewableFunction") - SymbolNameNoInfer = unique.Make("NoInfer") - SymbolNameNode = unique.Make("Node") - SymbolNameNodeList = unique.Make("NodeList") - SymbolNameNonNullable = unique.Make("NonNullable") - SymbolNameNumber = unique.Make("Number") - SymbolNameNumberConstructor = unique.Make("NumberConstructor") - SymbolNameNumberFormat = unique.Make("NumberFormat") - SymbolNameObject = unique.Make("Object") - SymbolNameObjectConstructor = unique.Make("ObjectConstructor") - SymbolNameOmit = unique.Make("Omit") - SymbolNamePartial = unique.Make("Partial") - SymbolNamePick = unique.Make("Pick") - SymbolNamePromise = unique.Make("Promise") - SymbolNamePromiseConstructor = unique.Make("PromiseConstructor") - SymbolNamePromiseLike = unique.Make("PromiseLike") - SymbolNameRawJSON = unique.Make("RawJSON") - SymbolNameReadonly = unique.Make("Readonly") - SymbolNameReadonlyArray = unique.Make("ReadonlyArray") - SymbolNameReadonlyMap = unique.Make("ReadonlyMap") - SymbolNameReadonlySet = unique.Make("ReadonlySet") - SymbolNameRecord = unique.Make("Record") - SymbolNameReflect = unique.Make("Reflect") - SymbolNameRegExp = unique.Make("RegExp") - SymbolNameRegExpConstructor = unique.Make("RegExpConstructor") - SymbolNameRegExpExecArray = unique.Make("RegExpExecArray") - SymbolNameRegExpMatchArray = unique.Make("RegExpMatchArray") - SymbolNameRelativeTimeFormat = unique.Make("RelativeTimeFormat") - SymbolNameRequired = unique.Make("Required") - SymbolNameSet = unique.Make("Set") - SymbolNameSharedArrayBuffer = unique.Make("SharedArrayBuffer") - SymbolNameString = unique.Make("String") - SymbolNameStringConstructor = unique.Make("StringConstructor") - SymbolNameSymbol = unique.Make("Symbol") - SymbolNameSymbolConstructor = unique.Make("SymbolConstructor") - SymbolNameT = unique.Make("T") - SymbolNameTemplateStringsArray = unique.Make("TemplateStringsArray") - SymbolNameThisType = unique.Make("ThisType") - SymbolNameTypedPropertyDescriptor = unique.Make("TypedPropertyDescriptor") - SymbolNameUint16Array = unique.Make("Uint16Array") - SymbolNameUint32Array = unique.Make("Uint32Array") - SymbolNameUint8Array = unique.Make("Uint8Array") - SymbolNameUint8ArrayConstructor = unique.Make("Uint8ArrayConstructor") - SymbolNameUint8ClampedArray = unique.Make("Uint8ClampedArray") - SymbolNameUncapitalize = unique.Make("Uncapitalize") - SymbolNameUppercase = unique.Make("Uppercase") - SymbolNameWeakMap = unique.Make("WeakMap") - SymbolNameWeakSet = unique.Make("WeakSet") - SymbolNameESModule = unique.Make("__esModule") - SymbolNameUnderscoreDefault = unique.Make("_default") - SymbolNameAny = unique.Make("any") - SymbolNameArg = unique.Make("arg") - SymbolNameArgs = unique.Make("args") - SymbolNameArguments = unique.Make("arguments") - SymbolNameAsyncIteratorProperty = unique.Make("asyncIterator") - SymbolNameBind = unique.Make("bind") - SymbolNameBooleanKeyword = unique.Make("boolean") - SymbolNameCaller = unique.Make("caller") - SymbolNameChildren = unique.Make("children") - SymbolNameClass = unique.Make("class") - SymbolNameClassName = unique.Make("className") - SymbolNameConst = unique.Make("const") - SymbolNameContext = unique.Make("context") - SymbolNameDescriptor = unique.Make("descriptor") - SymbolNameDone = unique.Make("done") - SymbolNameExports = unique.Make("exports") - SymbolNameFor = unique.Make("for") - SymbolNameGetProperty = unique.Make("get") - SymbolNameGlobal = unique.Make("global") - SymbolNameGlobalThis = unique.Make("globalThis") - SymbolNameHasInstance = unique.Make("hasInstance") - SymbolNameHtmlFor = unique.Make("htmlFor") - SymbolNameIteratorProperty = unique.Make("iterator") - SymbolNameLength = unique.Make("length") - SymbolNameMeta = unique.Make("meta") - SymbolNameModule = unique.Make("module") - SymbolNameName = unique.Make("name") - SymbolNameNever = unique.Make("never") - SymbolNameNext = unique.Make("next") - SymbolNameNumberKeyword = unique.Make("number") - SymbolNameParameterIndex = unique.Make("parameterIndex") - SymbolNamePrivate = unique.Make("private") - SymbolNamePropertyKey = unique.Make("propertyKey") - SymbolNameProps = unique.Make("props") - SymbolNamePrototype = unique.Make("prototype") - SymbolNameRequire = unique.Make("require") - SymbolNameReturn = unique.Make("return") - SymbolNameSelf = unique.Make("self") - SymbolNameSetProperty = unique.Make("set") - SymbolNameStatic = unique.Make("static") - SymbolNameStringKeyword = unique.Make("string") - SymbolNameTarget = unique.Make("target") - SymbolNameThen = unique.Make("then") - SymbolNameThrow = unique.Make("throw") - SymbolNameUndefined = unique.Make("undefined") - SymbolNameUnknown = unique.Make("unknown") - SymbolNameValue = unique.Make("value") - SymbolNameWith = unique.Make("with") - SymbolNameWritable = unique.Make("writable") + 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 var ( - InternalSymbolNameCall = unique.Make(InternalSymbolNamePrefix + "call") // Call signatures - InternalSymbolNameConstructor = unique.Make(InternalSymbolNamePrefix + "constructor") // Constructor implementations - InternalSymbolNameNew = unique.Make(InternalSymbolNamePrefix + "new") // Constructor signatures - InternalSymbolNameIndex = unique.Make(InternalSymbolNamePrefix + "index") // Index signatures - InternalSymbolNameExportStar = unique.Make(InternalSymbolNamePrefix + "export") // Module export * declarations - InternalSymbolNameGlobal = unique.Make(InternalSymbolNamePrefix + "global") // Global self-reference - InternalSymbolNameMissing = unique.Make(InternalSymbolNamePrefix + "missing") // Indicates missing symbol - InternalSymbolNameType = unique.Make(InternalSymbolNamePrefix + "type") // Anonymous type literal symbol - InternalSymbolNameObject = unique.Make(InternalSymbolNamePrefix + "object") // Anonymous object literal declaration - InternalSymbolNameJSXAttributes = unique.Make(InternalSymbolNamePrefix + "jsxAttributes") // Anonymous JSX attributes object literal declaration - InternalSymbolNameClass = unique.Make(InternalSymbolNamePrefix + "class") // Unnamed class expression - InternalSymbolNameFunction = unique.Make(InternalSymbolNamePrefix + "function") // Unnamed function expression - InternalSymbolNameComputed = unique.Make(InternalSymbolNamePrefix + "computed") // Computed property name declaration with dynamic name - InternalSymbolNameAssignmentDeclaration = unique.Make(InternalSymbolNamePrefix + "assignment") // Assignment declarations - InternalSymbolNameInstantiationExpression = unique.Make(InternalSymbolNamePrefix + "instantiationExpression") // Instantiation expressions - InternalSymbolNameImportAttributes = unique.Make(InternalSymbolNamePrefix + "importAttributes") - InternalSymbolNameExportEquals = unique.Make("export=") // Export assignment symbol - InternalSymbolNameDefault = unique.Make("default") // Default export symbol (technically not wholly internal, but included here for usability) - InternalSymbolNameThis = unique.Make("this") - InternalSymbolNameModuleExports = unique.Make("module.exports") + 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") ) // SymbolNameText returns a display name, preserving private identifier spelling. @@ -416,3 +486,13 @@ func EscapeSymbolName(symbolName SymbolName) 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 1312a200fc9b8..04377b181dde5 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -5,10 +5,10 @@ import ( "runtime" "strings" "testing" - "unique" "unsafe" "github.com/microsoft/TypeScript/tsc/internal/ast" + "github.com/microsoft/TypeScript/tsc/internal/json" "gotest.tools/v3/assert" ) @@ -17,11 +17,11 @@ func TestSymbolNameInterning(t *testing.T) { for _, text := range []string{"", "name", "__call", "\xFEcall", "#private", "\"module\"", "\u03C0"} { t.Run(text, func(t *testing.T) { t.Parallel() - name := unique.Make(text) - otherName := unique.Make(strings.Clone(text)) + name := ast.MakeSymbolName(text) + otherName := ast.MakeSymbolName(strings.Clone(text)) symbol := ast.NewSymbol() symbol.SetName(name) - var storedName unique.Handle[string] = symbol.Name() + storedName := symbol.Name() assert.Assert(t, storedName == otherName) assert.Equal(t, storedName.Value(), text) @@ -32,13 +32,14 @@ func TestSymbolNameInterning(t *testing.T) { shared := ast.NewSymbol() shared.SetSymbolData(symbol) assert.Assert(t, shared.Name() == otherName) - shared.SetName(unique.Make(text + "other")) + shared.SetName(ast.MakeSymbolName(text + "other")) assert.Assert(t, symbol.Name() == shared.Name()) }) } - assert.Assert(t, ast.InternalSymbolNameCall != unique.Make("__call")) - assert.Assert(t, ast.NewSymbol().Name() == unique.Make("")) - assert.Assert(t, new(ast.SymbolWithData).Initialize().Name() == unique.Make("")) + 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 TestPreinternedSymbolNames(t *testing.T) { @@ -54,12 +55,82 @@ func TestPreinternedSymbolNames(t *testing.T) { } { t.Run(text, func(t *testing.T) { t.Parallel() - assert.Assert(t, name == unique.Make(strings.Clone(text))) + 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() { @@ -88,12 +159,12 @@ func TestSymbolAccessors(t *testing.T) { parent := ast.NewSymbol() exportSymbol := ast.NewSymbol() declarations := []*ast.Node{declaration} - members := ast.SymbolTable{unique.Make("member"): member} - exports := ast.SymbolTable{unique.Make("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(unique.Make("C")) + symbol.SetName(ast.MakeSymbolName("C")) symbol.SetDeclarations(declarations) symbol.SetValueDeclaration(declaration) symbol.SetMembers(members, &arena) @@ -106,8 +177,8 @@ func TestSymbolAccessors(t *testing.T) { 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()[unique.Make("member")], member) - assert.Equal(t, symbol.Exports()[unique.Make("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) @@ -115,14 +186,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()[unique.Make("added")] = export - assert.Equal(t, members[unique.Make("added")], export) - symbol.Exports()[unique.Make("added")] = member - assert.Equal(t, exports[unique.Make("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(unique.Make("")) + symbol.SetName(ast.MakeSymbolName("")) symbol.SetDeclarations(nil) symbol.SetValueDeclaration(nil) symbol.SetMembers(nil, &arena) @@ -149,14 +220,14 @@ func TestSymbolTableInitialization(t *testing.T) { export := ast.NewSymbol() members := ast.GetMembers(symbol, &arena) - members[unique.Make("member")] = member - assert.Equal(t, symbol.Members()[unique.Make("member")], member) - assert.Equal(t, ast.GetMembers(symbol, &arena)[unique.Make("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[unique.Make("export")] = export - assert.Equal(t, symbol.Exports()[unique.Make("export")], export) - assert.Equal(t, ast.GetExports(symbol, &arena)[unique.Make("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) @@ -192,12 +263,12 @@ func TestSymbolSharedExtraData(t *testing.T) { alias.SetSymbolData(symbol) member := ast.NewSymbol() export := ast.NewSymbol() - alias.SetMembers(ast.SymbolTable{unique.Make("member"): member}, &arena) - symbol.SetExports(ast.SymbolTable{unique.Make("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()[unique.Make("member")], member) - assert.Equal(t, alias.Exports()[unique.Make("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) @@ -205,14 +276,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)[unique.Make("new")] = export - ast.GetExports(symbol, &arena)[unique.Make("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{unique.Make("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()[unique.Make("new")], export) - assert.Equal(t, alias.Exports()[unique.Make("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/utilities.go b/tsc/internal/ast/utilities.go index 9b4ffbdc399cc..45e599f3664a7 100644 --- a/tsc/internal/ast/utilities.go +++ b/tsc/internal/ast/utilities.go @@ -6,7 +6,6 @@ import ( "strings" "sync" "sync/atomic" - "unique" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/debug" @@ -2668,7 +2667,7 @@ func GetNamespaceDeclarationNode(node *Node) *Node { } func ModuleExportNameIsDefault(node *Node) bool { - return unique.Make(node.Text()) == InternalSymbolNameDefault + return MakeSymbolName(node.Text()) == InternalSymbolNameDefault } func IsDefaultImport(node *Node /*ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration*/) bool { @@ -3288,18 +3287,18 @@ func GetPropertyNameForPropertyNameNode(name *Node) SymbolName { switch name.Kind { case KindIdentifier, KindPrivateIdentifier, KindStringLiteral, KindNoSubstitutionTemplateLiteral, KindNumericLiteral, KindBigIntLiteral, KindJsxNamespacedName: - return unique.Make(name.Text()) + return MakeSymbolName(name.Text()) case KindComputedPropertyName: nameExpression := name.Expression() if IsStringOrNumericLiteralLike(nameExpression) { - return unique.Make(nameExpression.Text()) + return MakeSymbolName(nameExpression.Text()) } if IsSignedNumericLiteral(nameExpression) { text := nameExpression.AsPrefixUnaryExpression().Operand.Text() if nameExpression.AsPrefixUnaryExpression().Operator == KindMinusToken { text = "-" + text } - return unique.Make(text) + return MakeSymbolName(text) } return InternalSymbolNameMissing } diff --git a/tsc/internal/binder/binder.go b/tsc/internal/binder/binder.go index 4b5584710184c..47946e236ba69 100644 --- a/tsc/internal/binder/binder.go +++ b/tsc/internal/binder/binder.go @@ -4,7 +4,6 @@ import ( "slices" "strconv" "sync" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -312,10 +311,10 @@ func (b *Binder) getDeclarationName(node *ast.Node) ast.SymbolName { } if pattern := core.TryParsePattern(moduleName); pattern.IsValid() && pattern.StarIndex >= 0 { if attributes := node.AsModuleDeclaration().Attributes; attributes != nil { - return unique.Make(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 unique.Make("\"" + moduleName + "\"") + return ast.MakeSymbolName("\"" + moduleName + "\"") } if ast.IsPrivateIdentifier(name) { // containingClass exists because private names only allowed inside classes @@ -327,17 +326,17 @@ func (b *Binder) getDeclarationName(node *ast.Node) ast.SymbolName { return GetSymbolNameForPrivateIdentifier(containingClass.Symbol(), name.Text()) } if ast.IsPropertyNameLiteral(name) || ast.IsJsxNamespacedName(name) { - return unique.Make(name.Text()) + return ast.MakeSymbolName(name.Text()) } 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 unique.Make(nameExpression.Text()) + return ast.MakeSymbolName(nameExpression.Text()) } if ast.IsSignedNumericLiteral(nameExpression) { unaryExpression := nameExpression.AsPrefixUnaryExpression() - return unique.Make(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") } @@ -373,7 +372,7 @@ func (b *Binder) getDisplayName(node *ast.Node) string { } func GetSymbolNameForPrivateIdentifier(containingClassSymbol *ast.Symbol, description string) ast.SymbolName { - return unique.Make(ast.InternalSymbolNamePrefix + "#" + strconv.Itoa(int(ast.GetSymbolId(containingClassSymbol))) + "@" + description) + 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 { @@ -771,7 +770,7 @@ func (b *Binder) bindSourceFileIfExternalModule() { } func (b *Binder) bindSourceFileAsExternalModule() { - b.bindAnonymousDeclaration(b.file.AsNode(), ast.SymbolFlagsValueModule, unique.Make("\""+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) { @@ -920,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 = unique.Make(node.AsFunctionExpression().Name().Text()) + bindingName = ast.MakeSymbolName(node.AsFunctionExpression().Name().Text()) } b.bindAnonymousDeclaration(node, ast.SymbolFlagsFunction, bindingName) } @@ -954,7 +953,7 @@ func (b *Binder) bindClassLikeDeclaration(node *ast.Node) { case ast.KindClassExpression: nameText := ast.InternalSymbolNameClass if name != nil { - nameText = unique.Make(name.Text()) + nameText = ast.MakeSymbolName(name.Text()) } b.bindAnonymousDeclaration(node, ast.SymbolFlagsClass, nameText) } @@ -1204,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, unique.Make("__"+strconv.Itoa(index))) + b.bindAnonymousDeclaration(node, ast.SymbolFlagsFunctionScopedVariable, ast.MakeSymbolName("__"+strconv.Itoa(index))) } else { b.declareSymbolAndAddToSymbolTable(node, ast.SymbolFlagsFunctionScopedVariable, ast.SymbolFlagsParameterExcludes) } @@ -1274,19 +1273,19 @@ 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(unique.Make(node.Text()), container) + return b.lookupName(ast.MakeSymbolName(node.Text()), container) } if node.Expression().Kind == ast.KindThisKeyword { if _, symbolTable := b.getThisClassAndSymbolTable(); symbolTable != nil { if name := ast.GetElementOrPropertyAccessName(node); name != nil { - return symbolTable[unique.Make(name.Text())] + return symbolTable[ast.MakeSymbolName(name.Text())] } } 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()[unique.Make(name.Text())] + return symbol.Exports()[ast.MakeSymbolName(name.Text())] } } return nil diff --git a/tsc/internal/binder/binder_test.go b/tsc/internal/binder/binder_test.go index a5340ad1ea15a..a5d756f80207b 100644 --- a/tsc/internal/binder/binder_test.go +++ b/tsc/internal/binder/binder_test.go @@ -3,7 +3,6 @@ package binder import ( "runtime" "testing" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -35,7 +34,7 @@ export class Second { #value = 2; } }, text, core.ScriptKindTS) BindSourceFile(file) - name := unique.Make("named") + name := ast.MakeSymbolName("named") local := file.Locals[name] exported := file.Symbol.Exports()[name] assert.Assert(t, local != nil && exported != nil) @@ -44,16 +43,16 @@ export class Second { #value = 2; } assert.Equal(t, len(exported.Declarations()), 2) assert.Equal(t, local.ExportSymbol(), exported) - members := file.Symbol.Exports()[unique.Make("Shape")].Members() - for _, name := range []ast.SymbolName{ast.InternalSymbolNameCall, unique.Make("__call"), unique.Make("literal"), unique.Make("0")} { + 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[unique.Make("__call")]) - assert.Assert(t, file.Symbol.Exports()[unique.Make("renamed")].Name() == unique.Make("renamed")) + 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()[unique.Make("Second")] + second := file.Symbol.Exports()[ast.MakeSymbolName("Second")] firstPrivate := GetSymbolNameForPrivateIdentifier(first, "#value") secondPrivate := GetSymbolNameForPrivateIdentifier(second, "#value") assert.Assert(t, firstPrivate != secondPrivate) diff --git a/tsc/internal/binder/nameresolver.go b/tsc/internal/binder/nameresolver.go index 4257771a50849..99e97bf1f28b2 100644 --- a/tsc/internal/binder/nameresolver.go +++ b/tsc/internal/binder/nameresolver.go @@ -1,8 +1,6 @@ package binder import ( - "unique" - "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/diagnostics" @@ -198,7 +196,7 @@ loop: } if ast.IsClassExpression(location) && meaning&ast.SymbolFlagsClass != 0 { className := location.Name() - if className != nil && name == unique.Make(className.Text()) { + if className != nil && name == ast.MakeSymbolName(className.Text()) { result = location.Symbol() break loop } @@ -247,7 +245,7 @@ loop: } if meaning&ast.SymbolFlagsFunction != 0 { functionName := location.AsFunctionExpression().Name() - if functionName != nil && name == unique.Make(functionName.Text()) { + if functionName != nil && name == ast.MakeSymbolName(functionName.Text()) { result = location.Symbol() break loop } @@ -297,7 +295,7 @@ loop: case ast.KindInferType: if meaning&ast.SymbolFlagsTypeParameter != 0 { parameterName := location.AsInferTypeNode().TypeParameter.AsTypeParameterDeclaration().Name() - if parameterName != nil && name == unique.Make(parameterName.Text()) { + if parameterName != nil && name == ast.MakeSymbolName(parameterName.Text()) { result = location.AsInferTypeNode().TypeParameter.Symbol() break loop } diff --git a/tsc/internal/binder/referenceresolver.go b/tsc/internal/binder/referenceresolver.go index 8bce7e8a58ad2..f3ccd529ae728 100644 --- a/tsc/internal/binder/referenceresolver.go +++ b/tsc/internal/binder/referenceresolver.go @@ -1,8 +1,6 @@ package binder import ( - "unique" - "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/diagnostics" @@ -94,7 +92,7 @@ func (r *referenceResolver) getReferencedValueSymbol(reference *ast.IdentifierNo } if r.hooks.ResolveName != nil { - return r.hooks.ResolveName(location, unique.Make(reference.Text()), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) + return r.hooks.ResolveName(location, ast.MakeSymbolName(reference.Text()), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } if r.resolver == nil { @@ -103,7 +101,7 @@ func (r *referenceResolver) getReferencedValueSymbol(reference *ast.IdentifierNo } } - return r.resolver.Resolve(location, unique.Make(reference.Text()), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) + return r.resolver.Resolve(location, ast.MakeSymbolName(reference.Text()), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/) } func (r *referenceResolver) isTypeOnlyAliasDeclaration(symbol *ast.Symbol) bool { diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 0d04ac4221b19..3bbdb36909846 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -12,7 +12,6 @@ import ( "strings" "sync" "sync/atomic" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -1219,7 +1218,7 @@ func (c *Checker) getGlobalTypeSymbolResolver(name ast.SymbolName, reportErrors 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(unique.Make(name), arity, reportErrors) + return c.getGlobalType(ast.MakeSymbolName(name), arity, reportErrors) }) }) } @@ -1501,8 +1500,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)[unique.Make(moduleName.Text())] = merged - ast.GetSymbolTable(&c.patternAmbientModuleAugmentationTargets)[unique.Make(moduleName.Text())] = mainModule + ast.GetSymbolTable(&c.patternAmbientModuleAugmentations)[ast.MakeSymbolName(moduleName.Text())] = merged + ast.GetSymbolTable(&c.patternAmbientModuleAugmentationTargets)[ast.MakeSymbolName(moduleName.Text())] = 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 @@ -1603,7 +1602,7 @@ func (c *Checker) checkAndReportErrorForInvalidInitializer(errorLocation *ast.No } func (c *Checker) checkAndReportErrorForMissingPrefix(errorLocation *ast.Node, name ast.SymbolName) bool { - if !ast.IsIdentifier(errorLocation) || unique.Make(errorLocation.Text()) != name || isTypeReferenceIdentifier(errorLocation) || IsInTypeQuery(errorLocation) { + if !ast.IsIdentifier(errorLocation) || ast.MakeSymbolName(errorLocation.Text()) != name || isTypeReferenceIdentifier(errorLocation) || IsInTypeQuery(errorLocation) { return false } container := c.getThisContainer(errorLocation, false /*includeArrowFunctions*/, false /*includeClassComputedPropertyName*/) @@ -1651,8 +1650,8 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name ast.Symb return } declarationName := name - if errorLocation != nil && ast.IsIdentifier(errorLocation) && unique.Make(errorLocation.Text()) == name { - declarationName = unique.Make(scanner.DeclarationNameToString(errorLocation)) // use escape sequences from original file + if errorLocation != nil && ast.IsIdentifier(errorLocation) && ast.MakeSymbolName(errorLocation.Text()) == name { + declarationName = ast.MakeSymbolName(scanner.DeclarationNameToString(errorLocation)) // use escape sequences from original file } // Report missing lib first suggestedLib := c.getSuggestedLibForNonExistentName(name) @@ -1686,7 +1685,7 @@ 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), unique.Make(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.Value(), propName) return true @@ -1827,8 +1826,8 @@ var primitiveTypeAliasSuggestions = sync.OnceValue(func() ast.SymbolTable { } { sym := ast.NewSymbol() sym.SetFlags(ast.SymbolFlagsTypeAlias | ast.SymbolFlagsTransient) - sym.SetName(unique.Make(e.primitive)) - result[unique.Make(e.builtin)] = sym + sym.SetName(ast.MakeSymbolName(e.primitive)) + result[ast.MakeSymbolName(e.builtin)] = sym } return result }) @@ -2644,7 +2643,7 @@ func (c *Checker) resolveJSDocMemberName(name *ast.Node) *ast.Symbol { if t == nil { t = c.getDeclaredTypeOfSymbol(symbol) } - return c.getPropertyOfType(t, unique.Make(name.AsQualifiedName().Right.Text())) + return c.getPropertyOfType(t, ast.MakeSymbolName(name.AsQualifiedName().Right.Text())) } } } @@ -3194,7 +3193,7 @@ func (c *Checker) checkIfTypePredicateVariableIsDeclaredInBindingPattern(pattern if name == nil { continue } - if ast.IsIdentifier(name) && unique.Make(name.Text()) == predicateVariableName { + if ast.IsIdentifier(name) && ast.MakeSymbolName(name.Text()) == predicateVariableName { c.error(predicateVariableNode, diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName.Value()) return true } @@ -4529,7 +4528,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 unique.Make(source.Name().Text()) != target.symbol.Name() { + if ast.MakeSymbolName(source.Name().Text()) != target.symbol.Name() { return false } // If the type parameter node does not have an identical constraintNode as the resolved @@ -4847,7 +4846,7 @@ func (c *Checker) checkMemberForOverrideModifierWorker(node *ast.Node, staticTyp if prop != nil && baseProp == nil && memberHasOverrideModifier { if errorNode != nil { - suggestion := c.getSuggestedSymbolForNonexistentClassMember(unique.Make(ast.SymbolNameText(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 { @@ -5606,7 +5605,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, unique.Make(attribute.Name().Text())) + member := c.newSymbol(ast.SymbolFlagsProperty, ast.MakeSymbolName(attribute.Name().Text())) c.valueSymbolLinks.Get(member).resolvedType = c.getRegularTypeOfLiteralType(c.checkExpressionCached(attribute.AsImportAttribute().Value)) members[member.Name()] = member } @@ -5749,7 +5748,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, unique.Make(exportedName.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false) + symbol := c.resolveName(exportedName, ast.MakeSymbolName(exportedName.Text()), 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 { @@ -6199,7 +6198,7 @@ func (c *Checker) checkVarDeclaredNamesNotShadowed(node *ast.Node) { if !ast.IsIdentifier(name) { panic("Identifier expected") } - localDeclarationSymbol := c.resolveName(node, unique.Make(name.Text()), ast.SymbolFlagsVariable, nil /*nameNotFoundMessage*/, false /*isUse*/, false) + localDeclarationSymbol := c.resolveName(node, ast.MakeSymbolName(name.Text()), 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) @@ -6957,7 +6956,7 @@ 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()[unique.Make(node.PropertyNameOrName().Text())]; alreadyExportedSymbol == target { + if alreadyExportedSymbol := sourceSymbol.Exports()[ast.MakeSymbolName(node.PropertyNameOrName().Text())]; 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().Value())) } @@ -6966,7 +6965,7 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { } else { identifierText := symbol.Name() if ast.IsIdentifier(errorNode) { - identifierText = unique.Make(errorNode.Text()) + identifierText = ast.MakeSymbolName(errorNode.Text()) } specifierText := "..." if importDeclaration := ast.FindAncestor(node, func(n *ast.Node) bool { @@ -7092,7 +7091,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[unique.Make(node.Name().Text())] != IntrinsicTypeKindUnknown) { + len(typeParameters) == 1 && intrinsicTypeKinds[ast.MakeSymbolName(node.Name().Text())] != 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, @@ -7790,7 +7789,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, unique.Make(ast.GetFirstIdentifier(node).Text()), ast.SymbolFlagsAlias, nil, false, true) == nil { + if c.compilerOptions.IsolatedModules.IsTrue() || c.compilerOptions.VerbatimModuleSyntax.IsTrue() && ok && c.resolveName(node, ast.MakeSymbolName(ast.GetFirstIdentifier(node).Text()), 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()) @@ -7925,7 +7924,7 @@ func getUniqueTypeParameterName(typeParameters []*Type, baseName ast.SymbolName) } index := 1 for { - augmentedName := unique.Make(baseText + strconv.Itoa(index)) + augmentedName := ast.MakeSymbolName(baseText + strconv.Itoa(index)) if !hasTypeParameterByName(typeParameters, augmentedName) { return augmentedName } @@ -8051,7 +8050,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(unique.Make(node.Text()), node) + links.resolvedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(ast.MakeSymbolName(node.Text()), node) } return links.resolvedSymbol } @@ -10053,7 +10052,7 @@ func (c *Checker) isPromiseResolveArityError(node *ast.Node) bool { if !ast.IsCallExpression(node) || !ast.IsIdentifier(node.Expression()) { return false } - symbol := c.resolveName(node.Expression(), unique.Make(node.Expression().Text()), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) + symbol := c.resolveName(node.Expression(), ast.MakeSymbolName(node.Expression().Text()), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, false /*isUse*/, false) if symbol == nil { return false } @@ -11516,7 +11515,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l c.checkExternalEmitHelpers(node, ExternalEmitHelpersClassPrivateFieldGet) } } - lexicallyScopedSymbol := c.lookupSymbolForPrivateIdentifierDeclaration(unique.Make(right.Text()), right) + lexicallyScopedSymbol := c.lookupSymbolForPrivateIdentifierDeclaration(ast.MakeSymbolName(right.Text()), 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()) } @@ -11560,14 +11559,14 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l } return apparentType } - prop = c.getPropertyOfTypeEx(apparentType, unique.Make(right.Text()), isConstEnumObjectType(apparentType) /*skipObjectFunctionPropertyAugment*/, node.Kind == ast.KindQualifiedName /*includeTypeOnlyMembers*/) + prop = c.getPropertyOfTypeEx(apparentType, ast.MakeSymbolName(right.Text()), 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, unique.Make(right.Text())) + indexInfo = c.getApplicableIndexInfoForName(apparentType, ast.MakeSymbolName(right.Text())) } if indexInfo == nil { isUncheckedJS := c.isUncheckedJSSuggestion(node, leftType.symbol, true /*excludeClasses*/) @@ -11575,7 +11574,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l return c.anyType } if leftType.symbol == c.globalThisSymbol { - globalSymbol := c.globalThisSymbol.Exports()[unique.Make(right.Text())] + globalSymbol := c.globalThisSymbol.Exports()[ast.MakeSymbolName(right.Text())] 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 { @@ -11785,19 +11784,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, unique.Make(propNode.Text())) == nil && c.getApplicableIndexInfoForName(subtype, unique.Make(propNode.Text())) == nil { + if c.getPropertyOfType(subtype, ast.MakeSymbolName(propNode.Text())) == nil && c.getApplicableIndexInfoForName(subtype, ast.MakeSymbolName(propNode.Text())) == nil { diagnostic = NewDiagnosticChainForNode(diagnostic, propNode, diagnostics.Property_0_does_not_exist_on_type_1, scanner.DeclarationNameToString(propNode), c.TypeToString(subtype)) break } } } - if c.typeHasStaticProperty(unique.Make(propNode.Text()), containingType) { + if c.typeHasStaticProperty(ast.MakeSymbolName(propNode.Text()), 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, unique.Make(propNode.Text())) != nil { + if promisedType != nil && c.getPropertyOfType(promisedType, ast.MakeSymbolName(propNode.Text())) != 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 { @@ -11854,7 +11853,7 @@ func (c *Checker) getSuggestedSymbolForNonexistentProperty(name *ast.Node, conta return c.isValidPropertyAccessForCompletions(parent, containingType, prop) }) } - return c.getSpellingSuggestionForName(unique.Make(name.Text()), slices.Values(props), ast.SymbolFlagsValue) + return c.getSpellingSuggestionForName(ast.MakeSymbolName(name.Text()), slices.Values(props), ast.SymbolFlagsValue) } // Checks if an existing property access is valid for completions purposes. @@ -13017,7 +13016,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()), unique.Make(left.Name().Text())) + target := c.getTypeOfPropertyOfType(c.getTypeOfExpression(left.Expression()), ast.MakeSymbolName(left.Name().Text())) 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 } @@ -13617,7 +13616,7 @@ func (c *Checker) checkDeprecatedProperty(name *ast.Node, contextualType *Type) if contextualType == nil { return } - prop := c.getPropertyOfType(contextualType, unique.Make(name.Text())) + prop := c.getPropertyOfType(contextualType, ast.MakeSymbolName(name.Text())) if prop == nil || len(prop.Declarations()) == 0 { return } @@ -14167,7 +14166,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, unique.Make(node.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, + symbol = c.resolveName(node, ast.MakeSymbolName(node.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, c.getCannotFindNameDiagnosticForName(node), !ast.IsWriteOnlyAccess(node), false /*excludeGlobals*/) } links.resolvedSymbol = core.OrElse(symbol, c.unknownSymbol) @@ -14184,7 +14183,7 @@ func (c *Checker) getReferencedValueOrAliasSymbol(reference *ast.Node) *ast.Symb if resolvedSymbol != nil && resolvedSymbol != c.unknownSymbol { return resolvedSymbol } - return c.resolveName(reference, unique.Make(reference.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias, nil, false /*isUse*/, false /*excludeGlobals*/) + return c.resolveName(reference, ast.MakeSymbolName(reference.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue|ast.SymbolFlagsAlias, nil, false /*isUse*/, false /*excludeGlobals*/) } func (c *Checker) getCannotFindNameDiagnosticForName(node *ast.Node) *diagnostics.Message { @@ -14811,7 +14810,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, unique.Make(node.Name().Text())) + symbol := c.newSymbol(ast.SymbolFlagsFunctionScopedVariable, ast.MakeSymbolName(node.Name().Text())) symbol.SetDeclarations(alias.Declarations()) c.valueSymbolLinks.Get(symbol).resolvedType = c.getGlobalAbstractModuleSourceType() links.immediateTarget = symbol @@ -15002,9 +15001,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), unique.Make(nameText), true /*skipObjectFunctionPropertyAugment*/, false /*includeTypeOnlyMembers*/) + symbolFromVariable = c.getPropertyOfTypeEx(c.getTypeOfSymbol(targetSymbol), ast.MakeSymbolName(nameText), true /*skipObjectFunctionPropertyAugment*/, false /*includeTypeOnlyMembers*/) } else { - symbolFromVariable = c.getPropertyOfVariable(targetSymbol, unique.Make(nameText)) + symbolFromVariable = c.getPropertyOfVariable(targetSymbol, ast.MakeSymbolName(nameText)) } // if symbolFromVariable is export - get its final target symbolFromVariable = c.resolveSymbolEx(symbolFromVariable, dontResolveAlias) @@ -15013,8 +15012,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, unique.Make(nameText), specifier, dontResolveAlias) - if symbolFromModule == nil && unique.Make(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) @@ -15030,7 +15029,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) && unique.Make(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) @@ -15215,7 +15214,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[unique.Make(name.Text())] + localSymbol = locals[ast.MakeSymbolName(name.Text())] } exports := moduleSymbol.Exports() if localSymbol != nil { @@ -15798,8 +15797,8 @@ func (c *Checker) tryResolvePatternAmbientModule(resolvedSymbol *ast.Symbol, mod }) if len(candidates) > 0 { - augmentation := c.patternAmbientModuleAugmentations[unique.Make(moduleReference)] - augmentationTarget := c.patternAmbientModuleAugmentationTargets[unique.Make(moduleReference)] + augmentation := c.patternAmbientModuleAugmentations[ast.MakeSymbolName(moduleReference)] + augmentationTarget := c.patternAmbientModuleAugmentationTargets[ast.MakeSymbolName(moduleReference)] if len(candidates) == 1 { mergedCandidate := c.getMergedSymbol(candidates[0].Symbol) @@ -15942,7 +15941,7 @@ func (c *Checker) tryFindAmbientModule(moduleName string, withAugmentations bool if tspath.IsExternalModuleNameRelative(moduleName) { return nil } - symbol := c.getSymbol(c.globals, unique.Make("\""+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) @@ -16096,7 +16095,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(), unique.Make(node.Expression().Text()), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + resolvedRequire := c.resolveName(node.Expression(), ast.MakeSymbolName(node.Expression().Text()), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if resolvedRequire == c.requireSymbol { return true } @@ -16206,19 +16205,19 @@ func (c *Checker) resolveEntityName(name *ast.Node, meaning ast.SymbolFlags, ign resolveLocation = name } if meaning == ast.SymbolFlagsNamespace { - symbol = c.getMergedSymbol(c.resolveName(resolveLocation, unique.Make(name.Text()), meaning, nil, true /*isUse*/, false /*excludeGlobals*/)) + symbol = c.getMergedSymbol(c.resolveName(resolveLocation, ast.MakeSymbolName(name.Text()), meaning, nil, true /*isUse*/, false /*excludeGlobals*/)) if symbol == nil { - alias := c.getMergedSymbol(c.resolveName(resolveLocation, unique.Make(name.Text()), ast.SymbolFlagsAlias, nil, true /*isUse*/, false /*excludeGlobals*/)) + alias := c.getMergedSymbol(c.resolveName(resolveLocation, ast.MakeSymbolName(name.Text()), 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, unique.Make(name.Text()), meaning, message, true /*isUse*/, false /*excludeGlobals*/) + c.resolveName(resolveLocation, ast.MakeSymbolName(name.Text()), meaning, message, true /*isUse*/, false /*excludeGlobals*/) } } else { - symbol = c.getMergedSymbol(c.resolveName(resolveLocation, unique.Make(name.Text()), meaning, message, true /*isUse*/, false /*excludeGlobals*/)) + symbol = c.getMergedSymbol(c.resolveName(resolveLocation, ast.MakeSymbolName(name.Text()), meaning, message, true /*isUse*/, false /*excludeGlobals*/)) } case ast.KindQualifiedName: qualified := name.AsQualifiedName() @@ -16266,10 +16265,10 @@ func (c *Checker) resolveQualifiedName(name *ast.Node, left *ast.Node, right *as } } text := right.Text() - symbol := c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(namespace), unique.Make(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)), unique.Make(text), meaning)) + symbol = c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(c.resolveAlias(namespace)), ast.MakeSymbolName(text), meaning)) } if symbol == nil { if !ignoreErrors { @@ -16291,7 +16290,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), unique.Make(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()) @@ -16307,14 +16306,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, unique.Make(id.Text()), ast.SymbolFlagsValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + symbol := c.resolveName(id, ast.MakeSymbolName(id.Text()), 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, unique.Make(n.Parent.AsQualifiedName().Right.Text())) + symbol = c.getPropertyOfType(t, ast.MakeSymbolName(n.Parent.AsQualifiedName().Right.Text())) if symbol == nil { return nil } @@ -16324,7 +16323,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(unique.Make(name.Text()), maps.Values(c.getExportsOfModule(targetModule)), ast.SymbolFlagsModuleMember) + return c.getSpellingSuggestionForName(ast.MakeSymbolName(name.Text()), maps.Values(c.getExportsOfModule(targetModule)), ast.SymbolFlagsModuleMember) } func (c *Checker) getFullyQualifiedName(symbol *ast.Symbol, containingLocation *ast.Node) string { @@ -16460,7 +16459,7 @@ func (c *Checker) lateBindMember(parent *ast.Symbol, earlySymbols ast.SymbolTabl } name := memberName if t.flags&TypeFlagsUniqueESSymbol != 0 { - name = unique.Make(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.Value()) @@ -18732,7 +18731,7 @@ func (c *Checker) reportImplicitAny(declaration *ast.Node, t *Type, wideningKind originalKeywordKind := scanner.IdentifierToKeywordKind(name) if (ast.IsCallSignatureDeclaration(declaration.Parent) || ast.IsMethodSignatureDeclaration(declaration.Parent) || ast.IsFunctionTypeNode(declaration.Parent)) && slices.Contains(declaration.Parent.Parameters(), declaration) && - (ast.IsTypeNodeKind(originalKeywordKind) || c.resolveName(declaration, unique.Make(name.Text), ast.SymbolFlagsType, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) != nil) { + (ast.IsTypeNodeKind(originalKeywordKind) || c.resolveName(declaration, ast.MakeSymbolName(name.Text), ast.SymbolFlagsType, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) != nil) { newName := fmt.Sprintf("arg%v", slices.Index(declaration.Parent.Parameters(), declaration)) typeName := scanner.DeclarationNameToString(param.Name()) + core.IfElse(param.DotDotDotToken != nil, "[]", "") c.errorOrSuggestion(c.noImplicitAny, declaration, diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName) @@ -19170,10 +19169,10 @@ func (c *Checker) tryGetNameFromType(t *Type) (name ast.SymbolName, ok bool) { return t.AsUniqueESSymbolType().name, true case t.flags&TypeFlagsStringLiteral != 0: s := getStringLiteralValue(t) - return unique.Make(s), true + return ast.MakeSymbolName(s), true case t.flags&TypeFlagsNumberLiteral != 0: s := getNumberLiteralValue(t).String() - return unique.Make(s), true + return ast.MakeSymbolName(s), true default: return ast.EmptySymbolName, false } @@ -21142,7 +21141,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, unique.Make(param.Name().Text()), int32(i), trueType) + return c.newTypePredicate(TypePredicateKindIdentifier, ast.MakeSymbolName(param.Name().Text()), int32(i), trueType) } } return nil @@ -21832,7 +21831,7 @@ func (c *Checker) combineUnionOrIntersectionParameters(left *Signature, right *S paramName = leftName } if paramName == ast.EmptySymbolName { - paramName = unique.Make("arg" + strconv.Itoa(i)) + 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))) @@ -23647,7 +23646,7 @@ func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type { b.WriteString(symbol.Name().Value()) b.WriteByte('@') b.WriteString(strconv.FormatUint(uint64(ast.GetSymbolId(symbol)), 10)) - uniqueType = c.newUniqueESSymbolType(symbol, unique.Make(b.String())) + uniqueType = c.newUniqueESSymbolType(symbol, ast.MakeSymbolName(b.String())) c.uniqueESSymbolTypes[symbol] = uniqueType } return uniqueType @@ -23816,10 +23815,10 @@ func (c *Checker) getUnresolvedSymbolForEntityName(name *ast.Node) *ast.Symbol { } else { path = text } - result := c.unresolvedSymbols[unique.Make(path)] + result := c.unresolvedSymbols[ast.MakeSymbolName(path)] if result == nil { - result = c.newSymbolEx(ast.SymbolFlagsTypeAlias, unique.Make(text), ast.CheckFlagsUnresolved) - c.unresolvedSymbols[unique.Make(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 } @@ -24254,7 +24253,7 @@ func (c *Checker) isArrayOrTupleOrIntersection(t *Type) bool { } func (c *Checker) getTupleElementType(t *Type, index int) *Type { - propType := c.getTypeOfPropertyOfType(t, unique.Make(strconv.Itoa(index))) + propType := c.getTypeOfPropertyOfType(t, ast.MakeSymbolName(strconv.Itoa(index))) if propType != nil { return propType } @@ -24731,7 +24730,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(unique.Make(expr.Text()), ast.SymbolFlagsValue, nil /*diagnostic*/)) { + if ast.IsInfinityOrNaNString(expr.Text()) && (symbol == c.getGlobalSymbol(ast.MakeSymbolName(expr.Text()), 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. @@ -24762,7 +24761,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()[unique.Make(name)] + member := rootSymbol.Exports()[ast.MakeSymbolName(name)] if member != nil { if location != nil { return c.evaluateEnumMember(expr, member, location) @@ -25308,9 +25307,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), unique.Make(current.Text()), false /*skipObjectFunctionPropertyAugment*/, true /*includeTypeOnlyMembers*/) + symbolFromVariable = c.getPropertyOfTypeEx(c.getTypeOfSymbol(mergedResolvedSymbol), ast.MakeSymbolName(current.Text()), false /*skipObjectFunctionPropertyAugment*/, true /*includeTypeOnlyMembers*/) } else { - symbolFromModule = c.getSymbol(c.getExportsOfSymbol(mergedResolvedSymbol), unique.Make(current.Text()), meaning) + symbolFromModule = c.getSymbol(c.getExportsOfSymbol(mergedResolvedSymbol), ast.MakeSymbolName(current.Text()), meaning) if symbolFromModule == nil { // a CommonJS module might have typedefs exported alongside an export= // !!! @@ -25318,7 +25317,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()), unique.Make(current.Text()), meaning) + symbolFromModule = c.getSymbol(c.getExportsOfSymbol(immediateModuleSymbol.Parent()), ast.MakeSymbolName(current.Text()), meaning) } } } @@ -25490,7 +25489,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), unique.Make(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 @@ -27966,7 +27965,7 @@ func (c *Checker) getSuggestionForNonexistentProperty(name ast.SymbolName, conta 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, unique.Make(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)) @@ -28509,7 +28508,7 @@ func (c *Checker) getUniqAssociatedNamesFromTupleType(t *TypeReference, restSymb counters[name] = 0 } counters[name]++ - candidateName := unique.Make(name.Value() + "_" + strconv.Itoa(counters[name])) + candidateName := ast.MakeSymbolName(name.Value() + "_" + strconv.Itoa(counters[name])) if counters[candidateName] == 0 { names[i] = candidateName break @@ -29204,7 +29203,7 @@ func (c *Checker) markPropertyAliasReferenced(location *ast.Node /*PropertyAcces } var lexicallyScopedSymbol *ast.Symbol if ast.IsPrivateIdentifier(right) { - lexicallyScopedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(unique.Make(right.Text()), right) + lexicallyScopedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(ast.MakeSymbolName(right.Text()), right) } assignmentKind := getAssignmentTargetKind(location) var apparentType *Type @@ -29218,7 +29217,7 @@ func (c *Checker) markPropertyAliasReferenced(location *ast.Node /*PropertyAcces prop = c.getPrivateIdentifierPropertyOfType(apparentType, lexicallyScopedSymbol) } } else { - prop = c.getPropertyOfType(apparentType, unique.Make(right.Text())) + prop = c.getPropertyOfType(apparentType, ast.MakeSymbolName(right.Text())) } } if !(prop != nil && (isConstEnumOrConstEnumOnlyModule(prop) || prop.Flags()&ast.SymbolFlagsEnumMember != 0 && location.Parent.Kind == ast.KindEnumMember)) { @@ -29269,7 +29268,7 @@ func (c *Checker) markJsxAliasReferenced(node *ast.Node /*JsxOpeningLikeElement if !shouldFactoryRefErr { flags &^= ast.SymbolFlagsEnum } - jsxFactorySym = c.resolveName(jsxFactoryLocation, unique.Make(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 @@ -29290,7 +29289,7 @@ func (c *Checker) markJsxAliasReferenced(node *ast.Node /*JsxOpeningLikeElement if !shouldFactoryRefErr { flags &^= ast.SymbolFlagsEnum } - c.resolveName(jsxFactoryLocation, unique.Make(localJsxNamespace), flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) + c.resolveName(jsxFactoryLocation, ast.MakeSymbolName(localJsxNamespace), flags, jsxFactoryRefErr, true /*isUse*/, false /*excludeGlobals*/) } } } @@ -29307,7 +29306,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, unique.Make(exportedName.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + symbol := c.resolveName(exportedName, ast.MakeSymbolName(exportedName.Text()), 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 { @@ -29343,7 +29342,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), unique.Make(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 { @@ -29615,7 +29614,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, unique.Make(rootName.Text()), meaning, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + rootSymbol := c.resolveName(rootName, ast.MakeSymbolName(rootName.Text()), meaning, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) if rootSymbol != nil && rootSymbol.Flags()&ast.SymbolFlagsAlias != 0 { if c.canCollectSymbolAliasAccessibilityData && @@ -30633,7 +30632,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), unique.Make(left.Name().Text())) + return c.getTypeOfPropertyOfContextualType(c.getTypeFromTypeNode(typeNode), ast.MakeSymbolName(left.Name().Text())) } nameType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) if isTypeUsableAsPropertyName(nameType) { @@ -30658,7 +30657,7 @@ func (c *Checker) getContextualTypeForAssignmentExpression(binary *ast.BinaryExp symbol = c.getPropertyOfType(thisType, binder.GetSymbolNameForPrivateIdentifier(thisType.symbol, name.Text())) } } else { - symbol = c.getPropertyOfType(thisType, unique.Make(name.Text())) + symbol = c.getPropertyOfType(thisType, ast.MakeSymbolName(name.Text())) } } else { propType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) @@ -30783,7 +30782,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, unique.Make(strconv.Itoa(index))) + propType := c.getTypeOfPropertyOfContextualType(t, ast.MakeSymbolName(strconv.Itoa(index))) if propType != nil { return propType } @@ -30809,7 +30808,7 @@ func (c *Checker) getContextualTypeForSubstitutionExpression(template *ast.Node, } func (c *Checker) getContextualImportAttributeType(node *ast.Node) *Type { - return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), unique.Make(node.Name().Text())) + return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), ast.MakeSymbolName(node.Name().Text())) } // Returns the effective arguments for an expression that works like a function invocation. @@ -32400,7 +32399,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, unique.Make(node.Text())); propertyDeclaration != nil { + if propertyDeclaration := c.getPropertyOfType(typeOfPattern, ast.MakeSymbolName(node.Text())); propertyDeclaration != nil { return propertyDeclaration } } else if ast.IsMetaProperty(parent) && parent.Name() == node { @@ -32485,7 +32484,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy } if objectType != nil { - return c.getPropertyOfType(objectType, unique.Make(node.Text())) + return c.getPropertyOfType(objectType, ast.MakeSymbolName(node.Text())) } return nil case ast.KindDefaultKeyword, ast.KindFunctionKeyword, ast.KindEqualsGreaterThanToken, ast.KindClassKeyword: @@ -32637,8 +32636,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), unique.Make(name.Text()), meaning)); result == nil { - result = c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), unique.Make(name.Text())) + if result = c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(symbol), ast.MakeSymbolName(name.Text()), meaning)); result == nil { + result = c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), ast.MakeSymbolName(name.Text())) } } } @@ -32913,7 +32912,7 @@ func (c *Checker) containsArgumentsReference(node *ast.Node) bool { } switch node.Kind { case ast.KindIdentifier: - return unique.Make(node.Text()) == c.argumentsSymbol.Name() && c.IsArgumentsSymbol(c.getResolvedSymbol(node)) + return ast.MakeSymbolName(node.Text()) == 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 8de3b02535109..ae6f4dff4ab78 100644 --- a/tsc/internal/checker/emitresolver.go +++ b/tsc/internal/checker/emitresolver.go @@ -4,7 +4,6 @@ import ( "maps" "slices" "sync" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -173,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, unique.Make(node.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) + exportSymbol = r.checker.resolveName(node, ast.MakeSymbolName(node.Text()), 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) } @@ -194,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, unique.Make(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) + importSymbol := r.checker.resolveName(declaration, ast.MakeSymbolName(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsType|ast.SymbolFlagsNamespace|ast.SymbolFlagsAlias /*nameNotFoundMessage*/, nil /*isUse*/, false, false) nextSymbol = importSymbol } } @@ -792,7 +791,7 @@ func (r *EmitResolver) CreateLateBoundIndexSignatures(container *ast.Node, enclo } firstIdentifier := ast.GetFirstIdentifier(c.Name().Expression()) - name := r.checker.resolveName(firstIdentifier, unique.Make(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) + name := r.checker.resolveName(firstIdentifier, ast.MakeSymbolName(firstIdentifier.Text()), 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 0338a6b232675..84372fcc4dc61 100644 --- a/tsc/internal/checker/emitsupport.go +++ b/tsc/internal/checker/emitsupport.go @@ -3,7 +3,6 @@ package checker import ( "maps" "slices" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -165,7 +164,7 @@ func (c *Checker) isEntityNameVisible(entityName *ast.Node, enclosingDeclaration meaning := getMeaningOfEntityNameReference(entityName) firstIdentifier := ast.GetFirstIdentifier(entityName) - symbol := c.resolveName(enclosingDeclaration, unique.Make(firstIdentifier.Text()), meaning, nil, false, false) + symbol := c.resolveName(enclosingDeclaration, ast.MakeSymbolName(firstIdentifier.Text()), 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/flow.go b/tsc/internal/checker/flow.go index ccc779beea053..dc1b598e3c91e 100644 --- a/tsc/internal/checker/flow.go +++ b/tsc/internal/checker/flow.go @@ -5,7 +5,6 @@ import ( "slices" "strconv" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -459,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 == unique.Make(argument.Text()) { + if accessedName, ok := c.getAccessedPropertyName(f.reference); ok && ast.IsStringLiteralLike(argument) && accessedName == ast.MakeSymbolName(argument.Text()) { return c.getTypeWithFacts(t, core.IfElse(assumeTrue, TypeFactsNEUndefined, TypeFactsEQUndefined)) } } @@ -1640,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 unique.Make(source.AsQualifiedName().Right.Text()) == targetPropertyName && c.isMatchingReference(source.AsQualifiedName().Left, target.Expression()) + return ast.MakeSymbolName(source.AsQualifiedName().Right.Text()) == targetPropertyName && c.isMatchingReference(source.AsQualifiedName().Left, target.Expression()) } } case ast.KindBinaryExpression: @@ -1727,7 +1726,7 @@ func (c *Checker) writeFlowCacheKey(b *keyBuilder, node *ast.Node, declaredType func (c *Checker) getAccessedPropertyName(access *ast.Node) (ast.SymbolName, bool) { if ast.IsPropertyAccessExpression(access) { - return unique.Make(access.Name().Text()), true + return ast.MakeSymbolName(access.Name().Text()), true } if ast.IsElementAccessExpression(access) { return c.tryGetElementAccessExpressionName(access.AsElementAccessExpression()) @@ -1736,7 +1735,7 @@ func (c *Checker) getAccessedPropertyName(access *ast.Node) (ast.SymbolName, boo return c.getDestructuringPropertyName(access) } if ast.IsParameterDeclaration(access) { - return unique.Make(strconv.Itoa(slices.Index(access.Parent.Parameters(), access))), true + return ast.MakeSymbolName(strconv.Itoa(slices.Index(access.Parent.Parameters(), access))), true } return ast.EmptySymbolName, false } @@ -1744,7 +1743,7 @@ func (c *Checker) getAccessedPropertyName(access *ast.Node) (ast.SymbolName, boo func (c *Checker) tryGetElementAccessExpressionName(node *ast.ElementAccessExpression) (ast.SymbolName, bool) { switch { case ast.IsStringOrNumericLiteralLike(node.ArgumentExpression): - return unique.Make(node.ArgumentExpression.Text()), true + return ast.MakeSymbolName(node.ArgumentExpression.Text()), true case ast.IsEntityNameExpression(node.ArgumentExpression): return c.tryGetNameFromEntityNameExpression(node.ArgumentExpression) } @@ -1775,7 +1774,7 @@ func (c *Checker) tryGetNameFromEntityNameExpression(node *ast.Node) (ast.Symbol } } else if ast.IsEnumMember(declaration) { name, ok := ast.TryGetTextOfPropertyName(declaration.Name()) - return unique.Make(name), ok + return ast.MakeSymbolName(name), ok } } return ast.EmptySymbolName, false @@ -1786,7 +1785,7 @@ func tryGetNameFromType(t *Type) (ast.SymbolName, bool) { case t.flags&TypeFlagsUniqueESSymbol != 0: return t.AsUniqueESSymbolType().name, true case t.flags&TypeFlagsStringOrNumberLiteral != 0: - return unique.Make(evaluator.AnyToString(t.AsLiteralType().value)), true + return ast.MakeSymbolName(evaluator.AnyToString(t.AsLiteralType().value)), true } return ast.EmptySymbolName, false } @@ -1800,7 +1799,7 @@ func (c *Checker) getDestructuringPropertyName(node *ast.Node) (ast.SymbolName, return c.getLiteralPropertyNameText(node.Name()) } if ast.IsArrayLiteralExpression(parent) || ast.IsArrayBindingPattern(parent) { - return unique.Make(strconv.Itoa(slices.Index(parent.Elements(), node))), true + return ast.MakeSymbolName(strconv.Itoa(slices.Index(parent.Elements(), node))), true } return ast.EmptySymbolName, false } @@ -1808,7 +1807,7 @@ func (c *Checker) getDestructuringPropertyName(node *ast.Node) (ast.SymbolName, func (c *Checker) getLiteralPropertyNameText(name *ast.Node) (ast.SymbolName, bool) { t := c.getLiteralTypeFromPropertyName(name) if t.flags&(TypeFlagsStringLiteral|TypeFlagsNumberLiteral) != 0 { - return unique.Make(evaluator.AnyToString(t.AsLiteralType().value)), true + return ast.MakeSymbolName(evaluator.AnyToString(t.AsLiteralType().value)), true } return ast.EmptySymbolName, false } @@ -2114,7 +2113,7 @@ func (c *Checker) getPropertyNameForKnownSymbolName(symbolName ast.SymbolName) a return getPropertyNameFromType(uniqueType) } } - return unique.Make(ast.InternalSymbolNamePrefix + "@" + symbolName.Value()) + return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "@" + symbolName.Value()) } // We require the dotted function name in an assertion expression to be comprised of identifiers @@ -2141,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, unique.Make(name.Text())) + prop = c.getPropertyOfType(t, ast.MakeSymbolName(name.Text())) } if prop != nil { return c.getExplicitTypeOfSymbol(prop, diagnostic) diff --git a/tsc/internal/checker/inference.go b/tsc/internal/checker/inference.go index e148d1b7ef91c..39344d1967784 100644 --- a/tsc/internal/checker/inference.go +++ b/tsc/internal/checker/inference.go @@ -2,7 +2,6 @@ package checker import ( "slices" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -1245,13 +1244,13 @@ func (c *Checker) createEmptyObjectTypeFromStringLiteral(t *Type) *Type { continue } name := getStringLiteralValue(t) - literalProp := c.newSymbol(ast.SymbolFlagsProperty, unique.Make(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[unique.Make(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 ce5d452c8393e..5635a7dac5ae3 100644 --- a/tsc/internal/checker/jsx.go +++ b/tsc/internal/checker/jsx.go @@ -4,7 +4,6 @@ import ( "iter" "math" "slices" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" @@ -222,7 +221,7 @@ func (c *Checker) getContextualTypeForJsxAttribute(attribute *ast.Node, contextF if attributesType == nil || IsTypeAny(attributesType) { return nil } - return c.getTypeOfPropertyOfContextualType(attributesType, unique.Make(attribute.Name().Text())) + return c.getTypeOfPropertyOfContextualType(attributesType, ast.MakeSymbolName(attribute.Name().Text())) } return c.getContextualType(attribute.Parent, contextFlags) } @@ -518,13 +517,13 @@ func (c *Checker) getJSXFragmentType(node *ast.Node) *Type { if !shouldModuleRefErr { flags &^= ast.SymbolFlagsEnum } - jsxFactorySymbol = c.resolveName(node, unique.Make(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() == unique.Make(ReactNames.Fragment) { + if jsxFactorySymbol.Name() == ast.MakeSymbolName(ReactNames.Fragment) { links.jsxFragmentType = c.getTypeOfSymbol(jsxFactorySymbol) return links.jsxFragmentType } @@ -534,7 +533,7 @@ func (c *Checker) getJSXFragmentType(node *ast.Node) *Type { } reactExports := c.getExportsOfSymbol(resolvedAlias) - typeSymbol := c.getSymbol(reactExports, unique.Make(ReactNames.Fragment), ast.SymbolFlagsBlockScopedVariable) + typeSymbol := c.getSymbol(reactExports, ast.MakeSymbolName(ReactNames.Fragment), ast.SymbolFlagsBlockScopedVariable) if typeSymbol != nil { links.jsxFragmentType = c.getTypeOfSymbol(typeSymbol) } else { @@ -755,7 +754,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme if allAttributesTable != nil { allAttributesTable[attributeSymbol.Name()] = attributeSymbol } - if unique.Make(attributeDecl.Name().Text()) == jsxChildrenPropertyName { + if ast.MakeSymbolName(attributeDecl.Name().Text()) == jsxChildrenPropertyName { explicitlySpecifyChildrenAttribute = true } if contextualType != nil && checkMode&CheckModeInferential != 0 && checkMode&CheckModeSkipContextSensitive == 0 && c.isContextSensitive(attributeDecl) { @@ -1141,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, unique.Make(stringLiteralTypeName)) + intrinsicProp := c.getPropertyOfType(intrinsicElementsType, ast.MakeSymbolName(stringLiteralTypeName)) if intrinsicProp != nil { return c.getTypeOfSymbol(intrinsicProp) } @@ -1198,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), unique.Make(node.TagName().Text())) + indexInfo := c.getApplicableIndexInfoForName(c.getJsxType(JsxNames.IntrinsicElements, node), ast.MakeSymbolName(node.TagName().Text())) if indexInfo != nil { links.resolvedJsxElementAttributesType = indexInfo.valueType return links.resolvedJsxElementAttributesType @@ -1225,7 +1224,7 @@ func (c *Checker) getIntrinsicTagSymbol(node *ast.Node) *ast.Symbol { panic("Invalid tag name") } propName := tagName.Text() - intrinsicProp := c.getPropertyOfType(intrinsicElementsType, unique.Make(propName)) + intrinsicProp := c.getPropertyOfType(intrinsicElementsType, ast.MakeSymbolName(propName)) if intrinsicProp != nil { c.jsxElementLinks.Get(node).jsxFlags |= JsxFlagsIntrinsicNamedElement links.resolvedSymbol = intrinsicProp @@ -1238,7 +1237,7 @@ func (c *Checker) getIntrinsicTagSymbol(node *ast.Node) *ast.Symbol { links.resolvedSymbol = indexSymbol return links.resolvedSymbol } - if c.getTypeOfPropertyOrIndexSignatureOfType(intrinsicElementsType, unique.Make(propName)) != nil { + if c.getTypeOfPropertyOrIndexSignatureOfType(intrinsicElementsType, ast.MakeSymbolName(propName)) != nil { c.jsxElementLinks.Get(node).jsxFlags |= JsxFlagsIntrinsicIndexedElement links.resolvedSymbol = intrinsicElementsType.symbol return links.resolvedSymbol @@ -1314,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, unique.Make(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/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index d0850f2979386..d66920310b4e7 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -5,7 +5,6 @@ import ( "maps" "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -411,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(unique.Make(typeNode.AsTypeReferenceNode().TypeName.Text()), seenName{t, len(result) - 1}) + seenNames.Add(ast.MakeSymbolName(typeNode.AsTypeReferenceNode().TypeName.Text()), seenName{t, len(result) - 1}) } } } @@ -1505,7 +1504,7 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi } } if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 { - rawName := unique.Make(result.Text()) + rawName := ast.MakeSymbolName(result.Text()) i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(rawName) name := rawName @@ -1514,7 +1513,7 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi break } i++ - name = unique.Make(fmt.Sprintf("%s_%d", rawName.Value(), i)) + name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", rawName.Value(), i)) } if name != rawName { @@ -2024,7 +2023,7 @@ func (c *Checker) getExpandedParameters(sig *Signature, skipUnionExpanding bool) } var name ast.SymbolName for true { - name = unique.Make(fmt.Sprintf("%s_%d", names[i].Value(), counter)) + name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", names[i].Value(), counter)) _, ok := uniqueNames[name] if ok { counter++ @@ -2450,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, unique.Make(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) + name := b.ch.resolveName(enclosingDeclaration, ast.MakeSymbolName(firstIdentifier.Text()), 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, unique.Make(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) + fallback := b.ch.resolveName(firstIdentifier, ast.MakeSymbolName(firstIdentifier.Text()), ast.SymbolFlagsValue|ast.SymbolFlagsExportValue, nil /*nameNotFoundMessage*/, true /*isUse*/, false) if fallback != nil { b.ctx.tracker.TrackSymbol(fallback, enclosingDeclaration, ast.SymbolFlagsValue) } diff --git a/tsc/internal/checker/nodebuilderscopes.go b/tsc/internal/checker/nodebuilderscopes.go index 60fd7b3fb086a..b4fdecacc6e68 100644 --- a/tsc/internal/checker/nodebuilderscopes.go +++ b/tsc/internal/checker/nodebuilderscopes.go @@ -1,8 +1,6 @@ package checker import ( - "unique" - "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/debug" @@ -232,7 +230,7 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] continue } typeParamName := b.typeParameterToName(typeParam).Text - add(unique.Make(typeParamName), typeParam.symbol) + add(ast.MakeSymbolName(typeParamName), typeParam.symbol) } }) } diff --git a/tsc/internal/checker/pseudotypenodebuilder.go b/tsc/internal/checker/pseudotypenodebuilder.go index 6f699740430a1..39b752d410575 100644 --- a/tsc/internal/checker/pseudotypenodebuilder.go +++ b/tsc/internal/checker/pseudotypenodebuilder.go @@ -1,8 +1,6 @@ package checker import ( - "unique" - "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/debug" "github.com/microsoft/TypeScript/tsc/internal/nodebuilder" @@ -667,7 +665,7 @@ func (b *NodeBuilderImpl) pseudoReturnTypeMatchesPredicate(rt *pseudochecker.Pse } // For identifier predicates, check parameter name matches if !isThis { - if unique.Make(tp.ParameterName.Text()) != predicate.parameterName { + if ast.MakeSymbolName(tp.ParameterName.Text()) != predicate.parameterName { return false } } diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index 48ec8677a4abb..f191710cfe835 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -4,7 +4,6 @@ import ( "slices" "strconv" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -532,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, unique.Make(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)) @@ -1114,7 +1113,7 @@ func (c *Checker) getMatchingUnionConstituentForType(unionType *Type, t *Type) * // an empty name if no such discriminant property exists. func (c *Checker) getKeyPropertyName(t *Type) ast.SymbolName { u := t.AsUnionType() - if u.keyPropertyName == (ast.SymbolName{}) { + if u.keyPropertyName.IsZero() { u.keyPropertyName, u.constituentMap = c.computeKeyPropertyNameAndMap(t) } if u.keyPropertyName == ast.InternalSymbolNameMissing { @@ -1979,7 +1978,7 @@ func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) ast. func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol *ast.Symbol, index int) ast.SymbolName { if elementInfo.labeledDeclaration != nil { - return unique.Make(elementInfo.labeledDeclaration.Name().Text()) + return ast.MakeSymbolName(elementInfo.labeledDeclaration.Name().Text()) } if restSymbol != nil && restSymbol.ValueDeclaration() != nil && ast.IsParameterDeclaration(restSymbol.ValueDeclaration()) { return c.getTupleElementLabelFromBindingElement(restSymbol.ValueDeclaration(), index, elementInfo.flags) @@ -1988,7 +1987,7 @@ func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol if restSymbol != nil { rootName = restSymbol.Name() } - return unique.Make(rootName.Value() + "_" + strconv.Itoa(index)) + return ast.MakeSymbolName(rootName.Value() + "_" + strconv.Itoa(index)) } func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index int, elementFlags ElementFlags) ast.SymbolName { @@ -2009,9 +2008,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 unique.Make(name) + return ast.MakeSymbolName(name) } - return unique.Make(name + "_" + strconv.Itoa(index)) + return ast.MakeSymbolName(name + "_" + strconv.Itoa(index)) } // given // (...[x]: [number]) => ... @@ -2025,9 +2024,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 unique.Make(name) + return ast.MakeSymbolName(name) } - return unique.Make(name + "_n") + return ast.MakeSymbolName(name + "_n") case ast.KindArrayBindingPattern: if hasDotDotDotToken(node) { elements := node.Name().Elements() @@ -2045,7 +2044,7 @@ func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index i } } } - return unique.Make("arg_" + strconv.Itoa(index)) + return ast.MakeSymbolName("arg_" + strconv.Itoa(index)) } func (c *Checker) getTypePredicateOfSignature(sig *Signature) *TypePredicate { @@ -2129,8 +2128,8 @@ func (c *Checker) createTypePredicateFromTypePredicateNode(node *ast.Node, signa } 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() == unique.Make(name) }) - return c.newTypePredicate(kind, unique.Make(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 { @@ -2787,7 +2786,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(unique.Make(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 { @@ -2806,7 +2805,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(unique.Make(name.Text()), errorTarget) + suggestion = r.c.getSuggestionForNonexistentProperty(ast.MakeSymbolName(name.Text()), errorTarget) } } if suggestion != "" { @@ -4233,7 +4232,7 @@ func (r *Relater) propertiesRelatedTo(source *Type, target *Type, reportErrors b if sourceFlags&ElementFlagsVariable != 0 || targetFlags&ElementFlagsVariable != 0 { canExcludeDiscriminants = false } - if canExcludeDiscriminants && excludedProperties.Has(unique.Make(strconv.Itoa(sourcePosition))) { + if canExcludeDiscriminants && excludedProperties.Has(ast.MakeSymbolName(strconv.Itoa(sourcePosition))) { continue } } diff --git a/tsc/internal/checker/services.go b/tsc/internal/checker/services.go index 4740c8cb9fc5e..7603962b81b57 100644 --- a/tsc/internal/checker/services.go +++ b/tsc/internal/checker/services.go @@ -4,7 +4,6 @@ import ( "maps" "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -595,7 +594,7 @@ func (c *Checker) GetReferencesToSymbolInFile( continue } id := token.AsIdentifier() - if unique.Make(id.Text) != identifierText { + if ast.MakeSymbolName(id.Text) != identifierText { continue } refSymbol := c.GetSymbolAtLocation(token) @@ -1028,7 +1027,7 @@ func (c *Checker) GetPropertySymbolsFromContextualType(node *ast.Node, contextua return nil } if contextualType.flags&TypeFlagsUnion == 0 { - if symbol := c.getPropertyOfType(contextualType, unique.Make(name)); symbol != nil { + if symbol := c.getPropertyOfType(contextualType, ast.MakeSymbolName(name)); symbol != nil { return []*ast.Symbol{symbol} } return nil @@ -1040,17 +1039,17 @@ func (c *Checker) GetPropertySymbolsFromContextualType(node *ast.Node, contextua }) } discriminatedPropertySymbols := core.MapNonNil(filteredTypes, func(t *Type) *ast.Symbol { - return c.getPropertyOfType(t, unique.Make(name)) + return c.getPropertyOfType(t, ast.MakeSymbolName(name)) }) if unionSymbolOk && (len(discriminatedPropertySymbols) == 0 || len(discriminatedPropertySymbols) == len(contextualType.Types())) { - if symbol := c.getPropertyOfType(contextualType, unique.Make(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, unique.Make(name)) + return c.getPropertyOfType(t, ast.MakeSymbolName(name)) }) } // by eliminating duplicates we might even end up with a single symbol @@ -1071,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, unique.Make(location.Text())) + return c.getPropertyOfType(typeOfObjectLiteral, ast.MakeSymbolName(location.Text())) } } return nil diff --git a/tsc/internal/checker/symbolaccessibility.go b/tsc/internal/checker/symbolaccessibility.go index fc4a6beb1afab..3cb3176d5aaeb 100644 --- a/tsc/internal/checker/symbolaccessibility.go +++ b/tsc/internal/checker/symbolaccessibility.go @@ -3,7 +3,6 @@ package checker import ( "cmp" "slices" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -893,7 +892,7 @@ func (c *Checker) getClassExpressionNameTable(location *ast.Node) ast.SymbolTabl if len(nameText) == 0 || classSymbol == nil { return nil } - table := ast.SymbolTable{unique.Make(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_test.go b/tsc/internal/checker/types_test.go index b8b7078c7a371..7fff276d4ca10 100644 --- a/tsc/internal/checker/types_test.go +++ b/tsc/internal/checker/types_test.go @@ -7,7 +7,6 @@ import ( "strconv" "strings" "testing" - "unique" "unsafe" "github.com/microsoft/TypeScript/tsc/internal/ast" @@ -294,7 +293,7 @@ func TestIntersectionReductionAllocations(t *testing.T) { //nolint:paralleltest c, _ := newCompositeTestChecker() members := make(ast.SymbolTable) for i := range 128 { - name := unique.Make(strconv.Itoa(i)) + name := ast.MakeSymbolName(strconv.Itoa(i)) members[name] = c.newSymbol(ast.SymbolFlagsProperty, name) } object := c.newAnonymousType(nil, members, nil, nil, nil) @@ -309,32 +308,32 @@ func TestTemporaryPropertyCounts(t *testing.T) { t.Parallel() c := &Checker{} outer := c.getTemporaryPropertyCounts() - outer.Set(unique.Make("second"), 1) - outer.Set(unique.Make("first"), 1) - outer.Set(unique.Make("second"), 2) - assert.Assert(t, slices.Equal(slices.Collect(outer.Keys()), []ast.SymbolName{unique.Make("second"), unique.Make("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(unique.Make("first"), 4) - assert.Equal(t, outer.GetOrZero(unique.Make("first")), 1) - assert.Equal(t, outer.GetOrZero(unique.Make("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(unique.Make("first"))) + assert.Assert(t, !inner.Has(ast.MakeSymbolName("first"))) reused := c.getTemporaryPropertyCounts() assert.Equal(t, reused, inner) - reused.Set(unique.Make("second"), 3) - reused.Set(unique.Make("first"), 5) - assert.Assert(t, slices.Equal(slices.Collect(reused.Keys()), []ast.SymbolName{unique.Make("second"), unique.Make("first")})) - assert.Equal(t, outer.GetOrZero(unique.Make("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(unique.Make("second"))) + assert.Assert(t, !reused.Has(ast.MakeSymbolName("second"))) for i := range 4097 { - reused.Set(unique.Make(strconv.Itoa(i)), i) + reused.Set(ast.MakeSymbolName(strconv.Itoa(i)), i) } c.releaseTemporaryPropertyCounts(reused) for counts := c.freePropertyCounts; counts != nil; counts = counts.next { @@ -349,23 +348,23 @@ func TestTemporaryPropertyCounts(t *testing.T) { func TestIntersectionReductionReentrancy(t *testing.T) { t.Parallel() c, _ := newCompositeTestChecker() - property := c.newSymbol(ast.SymbolFlagsProperty, unique.Make("value")) - object := c.newAnonymousType(nil, ast.SymbolTable{unique.Make("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, unique.Make("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, unique.Make("value"), ast.CheckFlagsContainsPrivate) - outer.AsUnionOrIntersectionType().propertyCacheWithoutFunctionPropertyAugment[unique.Make("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(unique.Make("value"))) + assert.Assert(t, !counts.Has(ast.MakeSymbolName("value"))) } } @@ -629,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, unique.Make("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 ccf90169c2009..2326d8f6b5bad 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -5,7 +5,6 @@ import ( "slices" "strings" "sync" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -1009,9 +1008,9 @@ func isTypeUsableAsPropertyName(t *Type) bool { func getPropertyNameFromType(t *Type) ast.SymbolName { switch { case t.flags&TypeFlagsStringLiteral != 0: - return unique.Make(t.AsLiteralType().value.(string)) + return ast.MakeSymbolName(t.AsLiteralType().value.(string)) case t.flags&TypeFlagsNumberLiteral != 0: - return unique.Make(t.AsLiteralType().value.(jsnum.Number).String()) + return ast.MakeSymbolName(t.AsLiteralType().value.(jsnum.Number).String()) case t.flags&TypeFlagsUniqueESSymbol != 0: return t.AsUniqueESSymbolType().name } diff --git a/tsc/internal/ls/autoimport/export.go b/tsc/internal/ls/autoimport/export.go index 788a5f5aace98..76739b4dd0cdd 100644 --- a/tsc/internal/ls/autoimport/export.go +++ b/tsc/internal/ls/autoimport/export.go @@ -116,7 +116,7 @@ type Export struct { } func (e *Export) Name() ast.SymbolName { - if e.localName != (ast.SymbolName{}) && e.localName != ast.EmptySymbolName { + if !e.localName.IsZero() && e.localName != ast.EmptySymbolName { return e.localName } if e.ExportName == ast.InternalSymbolNameExportEquals { diff --git a/tsc/internal/ls/autoimport/extract.go b/tsc/internal/ls/autoimport/extract.go index 5731bb013a4c5..7b652ce1759f2 100644 --- a/tsc/internal/ls/autoimport/extract.go +++ b/tsc/internal/ls/autoimport/extract.go @@ -3,7 +3,6 @@ package autoimport import ( "slices" "sync/atomic" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -252,7 +251,7 @@ func (e *symbolExtractor) extractFromSymbol(name ast.SymbolName, symbol *ast.Sym *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()[unique.Make(prop.Name().Text())], moduleID, moduleFileName, syntax, file, checkerLease) + export, _ := e.createExport(expression.Symbol().Members()[ast.MakeSymbolName(prop.Name().Text())], moduleID, moduleFileName, syntax, file, checkerLease) if export != nil { export.through = name *exports = append(*exports, export) @@ -353,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 = unique.Make(lsutil.ModuleSpecifierToValidIdentifier(fileNameForDefaultExportName(targetSymbol, moduleFileName, moduleID), false)) + export.localName = ast.MakeSymbolName(lsutil.ModuleSpecifierToValidIdentifier(fileNameForDefaultExportName(targetSymbol, moduleFileName, moduleID), false)) } } @@ -400,7 +399,7 @@ func (e *symbolExtractor) tryResolveSymbol(symbol *ast.Symbol, syntax ExportSynt } if loc != nil { - local := e.localNameResolver.Resolve(loc, unique.Make(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 } @@ -452,7 +451,7 @@ func getSyntax(symbol *ast.Symbol) ExportSyntax { } func isUnusableName(name ast.SymbolName) bool { - return name == (ast.SymbolName{}) || name == ast.EmptySymbolName || + return name.IsZero() || name == ast.EmptySymbolName || name == ast.SymbolNameUnderscoreDefault || name == ast.InternalSymbolNameExportStar || name == ast.InternalSymbolNameDefault || diff --git a/tsc/internal/ls/autoimport/fix.go b/tsc/internal/ls/autoimport/fix.go index 299f14bea6bf2..3d7e6d17449cc 100644 --- a/tsc/internal/ls/autoimport/fix.go +++ b/tsc/internal/ls/autoimport/fix.go @@ -7,7 +7,6 @@ import ( "slices" "strings" "unicode" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -84,7 +83,7 @@ func (f *Fix) Edits( return edits, diagnostics.Update_import_from_0.Localize(locale, f.ModuleSpecifier), safe case lsproto.AutoImportFixKindAddNew: var declarations []*ast.Statement - name := unique.Make(f.Name) + 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 @@ -196,7 +195,7 @@ func getAddToExistingImportFix(file *ast.SourceFile, fix *Fix) *addToExistingImp panic("expected import declaration or require call expression") } - name := unique.Make(fix.Name) + 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{ @@ -610,7 +609,7 @@ func (v *View) GetFixes(export *Export, forJSX bool, isValidTypeOnlyUseSite bool startsWithUpper := unicode.IsUpper(rune(nameText[0])) if forJSX && !startsWithUpper { if export.IsRenameable() { - name = unique.Make(fmt.Sprintf("%c%s", unicode.ToUpper(rune(nameText[0])), nameText[1:])) + name = ast.MakeSymbolName(fmt.Sprintf("%c%s", unicode.ToUpper(rune(nameText[0])), nameText[1:])) } else { return nil } diff --git a/tsc/internal/ls/autoimport/import_adder.go b/tsc/internal/ls/autoimport/import_adder.go index 6fea18017ca1b..dd5c481274b9b 100644 --- a/tsc/internal/ls/autoimport/import_adder.go +++ b/tsc/internal/ls/autoimport/import_adder.go @@ -6,7 +6,6 @@ import ( "maps" "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -189,7 +188,7 @@ func sortedNamedImports(m map[ast.SymbolName]*newImportBinding) []*newImportBind // 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 := unique.Make(fix.Name) + symbolName := ast.MakeSymbolName(fix.Name) compilerOptions := adder.view.program.Options() switch fix.Kind { diff --git a/tsc/internal/ls/autoimport/index_test.go b/tsc/internal/ls/autoimport/index_test.go index e3b434ab1b323..e13353c7721a7 100644 --- a/tsc/internal/ls/autoimport/index_test.go +++ b/tsc/internal/ls/autoimport/index_test.go @@ -4,7 +4,6 @@ import ( "slices" "strings" "testing" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" @@ -16,7 +15,7 @@ type testEntry struct { package_ string } -func (e *testEntry) Name() ast.SymbolName { return unique.Make(e.name) } +func (e *testEntry) Name() ast.SymbolName { return ast.MakeSymbolName(e.name) } func TestIndexFind(t *testing.T) { t.Parallel() @@ -26,9 +25,9 @@ func TestIndexFind(t *testing.T) { idx.insertAsWords(lower) idx.insertAsWords(upper) - assert.Assert(t, slices.Equal(idx.Find(unique.Make(strings.Clone("fooBar")), true), []*testEntry{lower})) + 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 := unique.Make(strings.ToUpper(lower.name)) + 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) diff --git a/tsc/internal/ls/autoimport/util.go b/tsc/internal/ls/autoimport/util.go index 06f1f0bb19677..fec1a718df406 100644 --- a/tsc/internal/ls/autoimport/util.go +++ b/tsc/internal/ls/autoimport/util.go @@ -6,7 +6,6 @@ import ( "sync/atomic" "unicode" "unicode/utf8" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -120,20 +119,20 @@ func getDefaultLikeExportNameFromDeclaration(symbol *ast.Symbol) ast.SymbolName // "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 unique.Make(innerExpression.Text()) + return ast.MakeSymbolName(innerExpression.Text()) } continue } // "export { ~ as default }" if ast.IsExportSpecifier(d) && d.Symbol().Flags() == ast.SymbolFlagsAlias && d.PropertyName() != nil { if d.PropertyName().Kind == ast.KindIdentifier { - return unique.Make(d.PropertyName().Text()) + return ast.MakeSymbolName(d.PropertyName().Text()) } continue } // GH#52694 if name := ast.GetNameOfDeclaration(d); name != nil && name.Kind == ast.KindIdentifier { - return unique.Make(name.Text()) + return ast.MakeSymbolName(name.Text()) } if symbol.Parent() != nil && !checker.IsExternalModuleSymbol(symbol.Parent()) { return symbol.Parent().Name() diff --git a/tsc/internal/ls/autoimport/view.go b/tsc/internal/ls/autoimport/view.go index 0a038b7abd502..28898a3ada312 100644 --- a/tsc/internal/ls/autoimport/view.go +++ b/tsc/internal/ls/autoimport/view.go @@ -3,7 +3,6 @@ package autoimport import ( "slices" "unicode" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -81,7 +80,7 @@ const ( func (v *View) Search(query string, kind QueryKind) []*Export { var queryName ast.SymbolName if kind != QueryKindWordPrefix { - queryName = unique.Make(query) + queryName = ast.MakeSymbolName(query) } searchFn := func(bucket *RegistryBucket) []*Export { switch kind { diff --git a/tsc/internal/ls/codeactions_importfixes.go b/tsc/internal/ls/codeactions_importfixes.go index 0623c6525afe2..b96a1c3318023 100644 --- a/tsc/internal/ls/codeactions_importfixes.go +++ b/tsc/internal/ls/codeactions_importfixes.go @@ -4,7 +4,6 @@ import ( "context" "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -287,7 +286,7 @@ func getUmdSymbol(token *ast.Node, ch *checker.Checker) *ast.Symbol { location = parent } jsxNamespace := ch.GetJsxNamespace(parent) - parentSymbol := ch.ResolveName(unique.Make(jsxNamespace), location, ast.SymbolFlagsValue, false /* excludeGlobals */) + parentSymbol := ch.ResolveName(ast.MakeSymbolName(jsxNamespace), location, ast.SymbolFlagsValue, false /* excludeGlobals */) if isUMDExportSymbol(parentSymbol) { return parentSymbol } @@ -334,7 +333,7 @@ func getFixesInfoForNonUMDImport(fixContext *CodeFixContext, symbolToken *ast.No exports := view.Search(symbolName, queryKind) for _, export := range exports { - if isJSXTagName && !(export.Name() == unique.Make(symbolName) || export.IsRenameable()) { + if isJSXTagName && !(export.Name() == ast.MakeSymbolName(symbolName) || export.IsRenameable()) { continue } @@ -355,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(unique.Make(symbolName), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */) + symbol := ch.ResolveName(ast.MakeSymbolName(symbolName), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */) if symbol == nil { return nil } @@ -388,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(unique.Make(symbolToken.Text()), symbolToken, ast.SymbolFlagsValue, false /* excludeGlobals */) + compSymbol := ch.ResolveName(ast.MakeSymbolName(symbolToken.Text()), symbolToken, ast.SymbolFlagsValue, false /* excludeGlobals */) if compSymbol == nil { result = append(result, symbolNameInfo{name: symbolToken.Text()}) } else if ch.GetTypeOnlyAliasDeclaration(compSymbol) != nil { @@ -396,7 +395,7 @@ func getSymbolNamesToImport(sourceFile *ast.SourceFile, ch *checker.Checker, sym } } nsIsTypeOnly := false - if nsSymbol := ch.ResolveName(unique.Make(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}) @@ -404,7 +403,7 @@ func getSymbolNamesToImport(sourceFile *ast.SourceFile, ch *checker.Checker, sym } } tokenIsTypeOnly := false - if sym := ch.ResolveName(unique.Make(symbolToken.Text()), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); sym != nil { + if sym := ch.ResolveName(ast.MakeSymbolName(symbolToken.Text()), symbolToken, ast.SymbolFlagsValue, true /* excludeGlobals */); sym != nil { tokenIsTypeOnly = ch.GetTypeOnlyAliasDeclaration(sym) != nil } return []symbolNameInfo{{name: symbolToken.Text(), isTypeOnly: tokenIsTypeOnly}} @@ -414,7 +413,7 @@ func needsJsxNamespaceFix(jsxNamespace string, symbolToken *ast.Node, ch *checke if scanner.IsIntrinsicJsxName(symbolToken.Text()) { return true } - namespaceSymbol := ch.ResolveName(unique.Make(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 b8ade7d29654e..bbd9be8f1a5c9 100644 --- a/tsc/internal/ls/codeactions_missingmemberfixer.go +++ b/tsc/internal/ls/codeactions_missingmemberfixer.go @@ -2,7 +2,6 @@ package ls import ( "strconv" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -112,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, []ast.SymbolName{unique.Make(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{ast.MakeSymbolName(parameter.Name().Text())}, []*ast.TypeNode{f.createTypeNode(t, enclosingDeclaration, flags, nodeBuilder, idToSymbol)}, 1, ast.IsInJSFile(enclosingDeclaration)), nil /*type*/, nil /*fullSignature*/, f.createBody(body, quotePreference, signatureOnly), ), ) @@ -458,14 +457,14 @@ func createDummyParameters(factory *ast.NodeFactory, argCount int, names []ast.S if i < len(names) && names[i] != ast.EmptySymbolName { parameterName = names[i] } else { - parameterName = unique.Make("arg" + strconv.Itoa(i)) + parameterName = ast.MakeSymbolName("arg" + strconv.Itoa(i)) } count := parameterNameCounts[parameterName] parameterNameCounts[parameterName] = count + 1 if count > 0 { - parameterName = unique.Make(parameterName.Value() + strconv.Itoa(count)) + parameterName = ast.MakeSymbolName(parameterName.Value() + strconv.Itoa(count)) } var questionToken *ast.QuestionToken diff --git a/tsc/internal/ls/completions.go b/tsc/internal/ls/completions.go index 41339490dba8b..c1b324e0b6223 100644 --- a/tsc/internal/ls/completions.go +++ b/tsc/internal/ls/completions.go @@ -9,7 +9,6 @@ import ( "sync" "unicode" "unicode/utf8" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -1332,7 +1331,7 @@ func (l *LanguageService) getCompletionData( if isCurrentlyEditingNode(element, file, position) { continue } - existing.Add(unique.Make(element.PropertyNameOrName().Text())) + existing.Add(ast.MakeSymbolName(element.PropertyNameOrName().Text())) } uniques := core.Filter(exports, func(symbol *ast.Symbol) bool { return symbol.Name() != ast.InternalSymbolNameDefault && !existing.Has(symbol.Name()) @@ -1368,7 +1367,7 @@ func (l *LanguageService) getCompletionData( elements = importAttributes.AsImportAttributes().Attributes.Nodes } attributeNames := core.Map(elements, func(el *ast.Node) ast.SymbolName { - return unique.Make(el.AsImportAttribute().Name().Text()) + return ast.MakeSymbolName(el.AsImportAttribute().Name().Text()) }) existing := collections.NewSetFromItems(attributeNames...) uniques := core.Filter( @@ -1550,7 +1549,7 @@ func (l *LanguageService) getCompletionData( // Set sort texts. for _, symbol := range filteredSymbols { symbolId := ast.GetSymbolId(symbol) - if spreadMemberNames.Has(unique.Make(ast.SymbolNameText(symbol))) { + if spreadMemberNames.Has(ast.MakeSymbolName(ast.SymbolNameText(symbol))) { symbolToSortTextMap[symbolId] = SortTextMemberDeclaredBySpreadAssignment } if symbol.Flags()&ast.SymbolFlagsOptional != 0 { @@ -4320,7 +4319,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, unique.Make(name)) + return typeChecker.GetTypeOfPropertyOfContextualType(t, ast.MakeSymbolName(name)) } return nil @@ -4535,7 +4534,7 @@ func filterObjectMembersList( } if existingName != "" { - existingMemberNames.Add(unique.Make(existingName)) + existingMemberNames.Add(ast.MakeSymbolName(existingName)) } } @@ -4737,7 +4736,7 @@ func filterClassMembersList( } return core.Filter(baseSymbols, func(propertySymbol *ast.Symbol) bool { - return !existingMemberNames.Has(unique.Make(ast.SymbolNameText(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())) @@ -4824,7 +4823,7 @@ func filterJsxAttributes( } if attr.Kind == ast.KindJsxAttribute { - existingNames.Add(unique.Make(attr.Name().Text())) + existingNames.Add(ast.MakeSymbolName(attr.Name().Text())) } else if ast.IsJsxSpreadAttribute(attr) { setMemberDeclaredBySpreadAssignment(attr, &membersDeclaredBySpreadAssignment, typeChecker) } diff --git a/tsc/internal/ls/definition.go b/tsc/internal/ls/definition.go index 583cb89a15e34..8c8ee995eccf6 100644 --- a/tsc/internal/ls/definition.go +++ b/tsc/internal/ls/definition.go @@ -3,7 +3,6 @@ package ls import ( "context" "slices" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -341,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, unique.Make(name)); prop != nil { + if prop := c.GetPropertyOfType(unionType, ast.MakeSymbolName(name)); prop != nil { result = append(result, prop.Declarations()...) } } @@ -486,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), unique.Make(name)) + return typeChecker.GetPropertyOfType(typeChecker.GetTypeOfSymbol(base), ast.MakeSymbolName(name)) } - return typeChecker.GetPropertyOfType(typeChecker.GetDeclaredTypeOfSymbol(base), unique.Make(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 563bb1e0cbf43..cbb6fc3a8f94f 100644 --- a/tsc/internal/ls/findallreferences.go +++ b/tsc/internal/ls/findallreferences.go @@ -7,7 +7,6 @@ import ( "slices" "strings" "sync" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -1394,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), unique.Make(node.Text())) != nil + return checker.GetPropertyOfType(checker.GetTypeAtLocation(node.Parent.Parent), ast.MakeSymbolName(node.Text())) != nil } return false } @@ -1966,7 +1965,7 @@ func (state *refState) createSearch(location *ast.Node, symbol *ast.Symbol, comi } } symbolName := ast.SymbolNameText(s) - if moduleName, ok := ast.TryGetAmbientModuleNameFromSymbolName(unique.Make(symbolName)); ok { + 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 b27ab50b483bf..85195029613b7 100644 --- a/tsc/internal/ls/importTracker.go +++ b/tsc/internal/ls/importTracker.go @@ -3,7 +3,6 @@ package ls import ( "context" "slices" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -358,7 +357,7 @@ func getSearchesFromDirectImports( isNameMatch := func(name string) bool { // Use name of "default" even in `export =` case because we may have allowSyntheticDefaultImports - return unique.Make(name) == exportSymbol.Name() || exportKind != ExportKindNamed && unique.Make(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"`. @@ -386,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 || unique.Make(name.Text()) == exportSymbol.Name() { + if !isForRename || ast.MakeSymbolName(name.Text()) == exportSymbol.Name() { // Search locally for `bar`. addSearch(name, checker.GetSymbolAtLocation(name)) } @@ -416,7 +415,7 @@ func getSearchesFromDirectImports( if ast.IsImportTypeNode(decl) { if qualifier := decl.AsImportTypeNode().Qualifier; qualifier != nil { firstIdentifier := ast.GetFirstIdentifier(qualifier) - if unique.Make(firstIdentifier.Text()) == exportSymbol.Name() { + if ast.MakeSymbolName(firstIdentifier.Text()) == exportSymbol.Name() { singleReferences = append(singleReferences, firstIdentifier) } } else if exportKind == ExportKindExportEquals { @@ -449,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 || unique.Make(name.Text()) == symbolNameNoDefault(exportSymbol)) { + if name := importClause.Name(); name != nil && (exportKind == ExportKindDefault || exportKind == ExportKindExportEquals) && (!isForRename || ast.MakeSymbolName(name.Text()) == symbolNameNoDefault(exportSymbol)) { defaultImportAlias := checker.GetSymbolAtLocation(name) addSearch(name, defaultImportAlias) } @@ -707,7 +706,7 @@ func symbolNameNoDefault(symbol *ast.Symbol) ast.SymbolName { for _, decl := range symbol.Declarations() { name := ast.GetNameOfDeclaration(decl) if name != nil && ast.IsIdentifier(name) { - return unique.Make(name.Text()) + return ast.MakeSymbolName(name.Text()) } } return ast.EmptySymbolName diff --git a/tsc/internal/ls/jsdoc.go b/tsc/internal/ls/jsdoc.go index a6c1c1b878120..eb07d576de3c0 100644 --- a/tsc/internal/ls/jsdoc.go +++ b/tsc/internal/ls/jsdoc.go @@ -3,7 +3,6 @@ package ls import ( "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/checker" @@ -191,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, unique.Make(name.Text())); prop != nil { + if prop := c.GetPropertyOfType(objectType, ast.MakeSymbolName(name.Text())); 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 3ec0e3619356b..aca7b2a78fc43 100644 --- a/tsc/internal/ls/lsutil/utilities.go +++ b/tsc/internal/ls/lsutil/utilities.go @@ -3,7 +3,6 @@ package lsutil import ( "strings" "unicode" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -116,7 +115,7 @@ 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 = unique.Make(ambientModuleName) + moduleName = ast.MakeSymbolName(ambientModuleName) } return ModuleSpecifierToValidIdentifier(moduleName.Value(), forceCapitalize) } diff --git a/tsc/internal/ls/sourcedefinition.go b/tsc/internal/ls/sourcedefinition.go index a4af8c2829465..d61936a3872d9 100644 --- a/tsc/internal/ls/sourcedefinition.go +++ b/tsc/internal/ls/sourcedefinition.go @@ -4,7 +4,6 @@ import ( "context" "math" "slices" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -230,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), unique.Make(node.Text())); prop != nil { + if prop := c.GetPropertyOfType(c.GetTypeAtLocation(left), ast.MakeSymbolName(node.Text())); prop != nil { declarations = prop.Declarations() } } diff --git a/tsc/internal/ls/string_completions.go b/tsc/internal/ls/string_completions.go index 04b71f01b68b7..863c90095876b 100644 --- a/tsc/internal/ls/string_completions.go +++ b/tsc/internal/ls/string_completions.go @@ -8,7 +8,6 @@ import ( "maps" "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -398,7 +397,7 @@ func (l *LanguageService) getStringLiteralCompletionEntries( } exports := typeChecker.GetExportsAndPropertiesOfModule(moduleSpecifierSymbol) existing := collections.NewSetFromItems(core.Map(namedImportsOrExports.Elements(), func(n *ast.Node) ast.SymbolName { - return unique.Make(n.PropertyNameOrName().Text()) + return ast.MakeSymbolName(n.PropertyNameOrName().Text()) })...) uniques := core.Filter(exports, func(e *ast.Symbol) bool { return e.Name() != ast.InternalSymbolNameDefault && !existing.Has(e.Name()) @@ -519,7 +518,7 @@ func fromUnionableLiteralType( switch { case result.fromProperties != nil: result := result.fromProperties - alreadyUsedNames := collections.NewSetFromItems(core.Map(alreadyUsedTypes, unique.Make[string])...) + alreadyUsedNames := collections.NewSetFromItems(core.Map(alreadyUsedTypes, ast.MakeSymbolName)...) return &stringLiteralCompletions{ fromProperties: &completionsFromProperties{ symbols: core.Filter( @@ -2030,7 +2029,7 @@ func getStringLiteralCompletionsFromSignature( } t := typeChecker.GetTypeParameterAtPosition(candidate, argumentInfo.argumentIndex) if ast.IsJsxOpeningLikeElement(call) { - propType := typeChecker.GetTypeOfPropertyOfType(t, unique.Make(editingArgument.AsJsxAttribute().Name().Text())) + propType := typeChecker.GetTypeOfPropertyOfType(t, ast.MakeSymbolName(editingArgument.AsJsxAttribute().Name().Text())) if propType != nil { t = propType } @@ -2091,7 +2090,7 @@ func (l *LanguageService) stringLiteralCompletionDetails( case completion.fromProperties != nil: properties := completion.fromProperties for _, symbol := range properties.symbols { - if symbol.Name() == unique.Make(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 257b91cd9ed68..0493769e06c82 100644 --- a/tsc/internal/ls/utilities.go +++ b/tsc/internal/ls/utilities.go @@ -5,7 +5,6 @@ import ( "iter" "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/astnav" @@ -996,7 +995,7 @@ func getPropertySymbolsFromBaseTypes(symbol *ast.Symbol, propertyName ast.Symbol func getPropertySymbolFromBindingElement(checker *checker.Checker, bindingElement *ast.Node) *ast.Symbol { if typeOfPattern := checker.GetTypeAtLocation(bindingElement.Parent); typeOfPattern != nil { - return checker.GetPropertyOfType(typeOfPattern, unique.Make(bindingElement.Name().Text())) + return checker.GetPropertyOfType(typeOfPattern, ast.MakeSymbolName(bindingElement.Name().Text())) } return nil } diff --git a/tsc/internal/printer/namegenerator.go b/tsc/internal/printer/namegenerator.go index 9572e5ebacbd7..6d6fca689a281 100644 --- a/tsc/internal/printer/namegenerator.go +++ b/tsc/internal/printer/namegenerator.go @@ -2,7 +2,6 @@ package printer import ( "fmt" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -367,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[unique.Make(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/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index caf0837392f6f..8635bfaedf559 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -5,7 +5,6 @@ import ( "iter" "slices" "strings" - "unique" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/collections" @@ -1194,7 +1193,7 @@ func (tx *DeclarationTransformer) tryGetNameOfAssignedExpression(unwrapped *ast. nameText = unwrapped.Text() } if nameText != "" && nameText != "default" { - if tx.resolver.IsNameResolvable(tx.enclosingDeclaration, unique.Make(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 { @@ -2812,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, unique.Make(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 } @@ -2848,7 +2847,7 @@ func (tx *DeclarationTransformer) transformExpandoAssignment(node *ast.BinaryExp declarationData.Symbol = host containerData := synthesizedNamespace.LocalsContainerData() containerData.Locals = make(ast.SymbolTable, 0) - containerData.Locals[unique.Make(localName.Text())] = symbol + containerData.Locals[ast.MakeSymbolName(localName.Text())] = symbol oldEnclosing := tx.enclosingDeclaration tx.enclosingDeclaration = synthesizedNamespace From 7fceb7666a68e41d4890e19ed18cfbcaae76faa9 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Oct 2026 08:46:06 -0700 Subject: [PATCH 04/14] Intern symbol names in a pointer-free table unique.Make registers a weak handle for every new string, which made binding substantially slower and added allocations. Canonical names do not need to be collected during a compilation, so a dedicated table can make interning cheap. Identifying names by a 32-bit ID also keeps them free of pointers, so the symbol tables, nodes, and caches that store them cost the garbage collector nothing to scan or write-barrier. --- tsc/internal/ast/symbol.go | 9 +- tsc/internal/ast/symbol_test.go | 30 +++++ tsc/internal/ast/symbolname_intern.go | 151 ++++++++++++++++++++++++++ 3 files changed, 186 insertions(+), 4 deletions(-) create mode 100644 tsc/internal/ast/symbolname_intern.go diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index 1c085d4f09cd0..b505258ad3b23 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -6,7 +6,6 @@ import ( "strings" "sync/atomic" "unicode/utf8" - "unique" "github.com/microsoft/TypeScript/tsc/internal/core" "github.com/microsoft/TypeScript/tsc/internal/debug" @@ -171,14 +170,16 @@ func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags { // 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 unique.Handle[string] +type SymbolName struct { + id uint32 +} func MakeSymbolName(text string) SymbolName { - return SymbolName(unique.Make(text)) + return SymbolName{symbolNames.intern(text)} } func (name SymbolName) Value() string { - return unique.Handle[string](name).Value() + return symbolNames.text(name.id) } func (name SymbolName) IsZero() bool { diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index 04377b181dde5..6a6b97b73b4a3 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -3,7 +3,9 @@ package ast_test import ( "reflect" "runtime" + "strconv" "strings" + "sync" "testing" "unsafe" @@ -42,6 +44,34 @@ func TestSymbolNameInterning(t *testing.T) { 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() { + 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) + 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{ diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go new file mode 100644 index 0000000000000..825d571fab7d1 --- /dev/null +++ b/tsc/internal/ast/symbolname_intern.go @@ -0,0 +1,151 @@ +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 + } + } +} + +// hashSymbolNameText is FNV-1a with a final mix. Names are short, so this +// inlines well and beats a general-purpose hash call. +func hashSymbolNameText(text string) uint64 { + h := uint64(14695981039346656037) + for i := range len(text) { + h ^= uint64(text[i]) + h *= 1099511628211 + } + h ^= h >> 32 + h *= 0x9E3779B97F4A7C15 + h ^= h >> 29 + return h +} From 2b8032574c91354ef3dfd4ea7b18d926526e0ad4 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Oct 2026 08:50:52 -0700 Subject: [PATCH 05/14] Store interned names on identifiers Binding, checking, and language features reinterned identifier text at every symbol-table lookup, so interning cost was paid many times per identifier and showed up as a large binding regression. Interning once when the identifier is created lets every later lookup use the stored name directly. The AST schema gains a SymbolName field type so the generated Go AST and encoder carry the interned name while the JavaScript API still sees a plain string. --- tools/scripts/tsc/ast.json | 2 +- tools/scripts/tsc/generate-encoder.ts | 21 +++- tools/scripts/tsc/generate-go-ast.ts | 40 ++++++- tools/scripts/tsc/schema.ts | 2 + tsc/internal/api/encoder/decoder_test.go | 12 +- tsc/internal/api/encoder/encoder_generated.go | 2 +- tsc/internal/ast/ast.go | 11 +- tsc/internal/ast/ast_generated.go | 8 +- tsc/internal/ast/nodeaccessors_test.go | 2 +- tsc/internal/ast/utilities.go | 6 +- tsc/internal/binder/binder.go | 14 +-- tsc/internal/binder/nameresolver.go | 6 +- tsc/internal/binder/referenceresolver.go | 4 +- tsc/internal/checker/checker.go | 112 +++++++++--------- tsc/internal/checker/emitresolver.go | 6 +- tsc/internal/checker/emitsupport.go | 2 +- tsc/internal/checker/flow.go | 10 +- tsc/internal/checker/jsx.go | 6 +- tsc/internal/checker/nodebuilderimpl.go | 12 +- tsc/internal/checker/nodebuilderscopes.go | 2 +- tsc/internal/checker/nodecopy.go | 2 +- tsc/internal/checker/pseudotypenodebuilder.go | 2 +- tsc/internal/checker/relater.go | 4 +- tsc/internal/checker/services.go | 8 +- tsc/internal/ls/autoimport/extract.go | 2 +- tsc/internal/ls/autoimport/util.go | 6 +- .../codeactions_fixmissingtypeannotation.go | 4 +- tsc/internal/ls/codeactions_importfixes.go | 4 +- .../ls/codeactions_missingmemberfixer.go | 2 +- tsc/internal/ls/completions.go | 6 +- tsc/internal/ls/findallreferences.go | 2 +- tsc/internal/ls/importTracker.go | 8 +- tsc/internal/ls/jsdoc.go | 2 +- tsc/internal/ls/sourcedefinition.go | 2 +- tsc/internal/ls/string_completions.go | 4 +- tsc/internal/ls/utilities.go | 2 +- tsc/internal/parser/reparser.go | 10 +- tsc/internal/printer/printer.go | 4 +- tsc/internal/pseudochecker/lookup.go | 2 +- tsc/internal/scanner/utilities.go | 2 +- .../transformers/declarations/transform.go | 2 +- .../tstransforms/typeserializer.go | 2 +- 42 files changed, 208 insertions(+), 154 deletions(-) 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-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/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/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/utilities.go b/tsc/internal/ast/utilities.go index 45e599f3664a7..3f7dc64ba1ee9 100644 --- a/tsc/internal/ast/utilities.go +++ b/tsc/internal/ast/utilities.go @@ -2667,7 +2667,7 @@ func GetNamespaceDeclarationNode(node *Node) *Node { } func ModuleExportNameIsDefault(node *Node) bool { - return MakeSymbolName(node.Text()) == InternalSymbolNameDefault + return node.TextSymbolName() == InternalSymbolNameDefault } func IsDefaultImport(node *Node /*ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration*/) bool { @@ -3287,11 +3287,11 @@ func GetPropertyNameForPropertyNameNode(name *Node) SymbolName { switch name.Kind { case KindIdentifier, KindPrivateIdentifier, KindStringLiteral, KindNoSubstitutionTemplateLiteral, KindNumericLiteral, KindBigIntLiteral, KindJsxNamespacedName: - return MakeSymbolName(name.Text()) + return name.TextSymbolName() case KindComputedPropertyName: nameExpression := name.Expression() if IsStringOrNumericLiteralLike(nameExpression) { - return MakeSymbolName(nameExpression.Text()) + return nameExpression.TextSymbolName() } if IsSignedNumericLiteral(nameExpression) { text := nameExpression.AsPrefixUnaryExpression().Operand.Text() diff --git a/tsc/internal/binder/binder.go b/tsc/internal/binder/binder.go index 47946e236ba69..1b4109c1fac22 100644 --- a/tsc/internal/binder/binder.go +++ b/tsc/internal/binder/binder.go @@ -326,13 +326,13 @@ func (b *Binder) getDeclarationName(node *ast.Node) ast.SymbolName { return GetSymbolNameForPrivateIdentifier(containingClass.Symbol(), name.Text()) } if ast.IsPropertyNameLiteral(name) || ast.IsJsxNamespacedName(name) { - return ast.MakeSymbolName(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 ast.MakeSymbolName(nameExpression.Text()) + return nameExpression.TextSymbolName() } if ast.IsSignedNumericLiteral(nameExpression) { unaryExpression := nameExpression.AsPrefixUnaryExpression() @@ -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 = ast.MakeSymbolName(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 = ast.MakeSymbolName(name.Text()) + nameText = name.TextSymbolName() } b.bindAnonymousDeclaration(node, ast.SymbolFlagsClass, nameText) } @@ -1273,19 +1273,19 @@ 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(ast.MakeSymbolName(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[ast.MakeSymbolName(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()[ast.MakeSymbolName(name.Text())] + return symbol.Exports()[name.TextSymbolName()] } } return nil diff --git a/tsc/internal/binder/nameresolver.go b/tsc/internal/binder/nameresolver.go index 99e97bf1f28b2..c747ce2aa9987 100644 --- a/tsc/internal/binder/nameresolver.go +++ b/tsc/internal/binder/nameresolver.go @@ -196,7 +196,7 @@ loop: } if ast.IsClassExpression(location) && meaning&ast.SymbolFlagsClass != 0 { className := location.Name() - if className != nil && name == ast.MakeSymbolName(className.Text()) { + if className != nil && name == className.TextSymbolName() { result = location.Symbol() break loop } @@ -245,7 +245,7 @@ loop: } if meaning&ast.SymbolFlagsFunction != 0 { functionName := location.AsFunctionExpression().Name() - if functionName != nil && name == ast.MakeSymbolName(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 == ast.MakeSymbolName(parameterName.Text()) { + if parameterName != nil && name == parameterName.TextSymbolName() { result = location.AsInferTypeNode().TypeParameter.Symbol() break loop } diff --git a/tsc/internal/binder/referenceresolver.go b/tsc/internal/binder/referenceresolver.go index f3ccd529ae728..646c10fefa455 100644 --- a/tsc/internal/binder/referenceresolver.go +++ b/tsc/internal/binder/referenceresolver.go @@ -92,7 +92,7 @@ func (r *referenceResolver) getReferencedValueSymbol(reference *ast.IdentifierNo } if r.hooks.ResolveName != nil { - return r.hooks.ResolveName(location, ast.MakeSymbolName(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, ast.MakeSymbolName(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 { diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 3bbdb36909846..744ad5dff39cd 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -1500,8 +1500,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)[ast.MakeSymbolName(moduleName.Text())] = merged - ast.GetSymbolTable(&c.patternAmbientModuleAugmentationTargets)[ast.MakeSymbolName(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 @@ -1602,7 +1602,7 @@ func (c *Checker) checkAndReportErrorForInvalidInitializer(errorLocation *ast.No } func (c *Checker) checkAndReportErrorForMissingPrefix(errorLocation *ast.Node, name ast.SymbolName) bool { - if !ast.IsIdentifier(errorLocation) || ast.MakeSymbolName(errorLocation.Text()) != name || isTypeReferenceIdentifier(errorLocation) || IsInTypeQuery(errorLocation) { + if !ast.IsIdentifier(errorLocation) || errorLocation.TextSymbolName() != name || isTypeReferenceIdentifier(errorLocation) || IsInTypeQuery(errorLocation) { return false } container := c.getThisContainer(errorLocation, false /*includeArrowFunctions*/, false /*includeClassComputedPropertyName*/) @@ -1650,7 +1650,7 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name ast.Symb return } declarationName := name - if errorLocation != nil && ast.IsIdentifier(errorLocation) && ast.MakeSymbolName(errorLocation.Text()) == name { + 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 @@ -2643,7 +2643,7 @@ func (c *Checker) resolveJSDocMemberName(name *ast.Node) *ast.Symbol { if t == nil { t = c.getDeclaredTypeOfSymbol(symbol) } - return c.getPropertyOfType(t, ast.MakeSymbolName(name.AsQualifiedName().Right.Text())) + return c.getPropertyOfType(t, name.AsQualifiedName().Right.TextSymbolName()) } } } @@ -3193,7 +3193,7 @@ func (c *Checker) checkIfTypePredicateVariableIsDeclaredInBindingPattern(pattern if name == nil { continue } - if ast.IsIdentifier(name) && ast.MakeSymbolName(name.Text()) == 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 } @@ -4528,7 +4528,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 ast.MakeSymbolName(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 @@ -5605,7 +5605,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, ast.MakeSymbolName(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 } @@ -5748,7 +5748,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, ast.MakeSymbolName(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 { @@ -6198,7 +6198,7 @@ func (c *Checker) checkVarDeclaredNamesNotShadowed(node *ast.Node) { if !ast.IsIdentifier(name) { panic("Identifier expected") } - localDeclarationSymbol := c.resolveName(node, ast.MakeSymbolName(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) @@ -6956,7 +6956,7 @@ 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()[ast.MakeSymbolName(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().Value())) } @@ -6965,7 +6965,7 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { } else { identifierText := symbol.Name() if ast.IsIdentifier(errorNode) { - identifierText = ast.MakeSymbolName(errorNode.Text()) + identifierText = errorNode.TextSymbolName() } specifierText := "..." if importDeclaration := ast.FindAncestor(node, func(n *ast.Node) bool { @@ -7091,7 +7091,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[ast.MakeSymbolName(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, @@ -7789,7 +7789,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.MakeSymbolName(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()) @@ -8050,7 +8050,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(ast.MakeSymbolName(node.Text()), node) + links.resolvedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(node.TextSymbolName(), node) } return links.resolvedSymbol } @@ -10052,7 +10052,7 @@ func (c *Checker) isPromiseResolveArityError(node *ast.Node) bool { if !ast.IsCallExpression(node) || !ast.IsIdentifier(node.Expression()) { return false } - symbol := c.resolveName(node.Expression(), ast.MakeSymbolName(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 } @@ -11515,7 +11515,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l c.checkExternalEmitHelpers(node, ExternalEmitHelpersClassPrivateFieldGet) } } - lexicallyScopedSymbol := c.lookupSymbolForPrivateIdentifierDeclaration(ast.MakeSymbolName(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()) } @@ -11559,14 +11559,14 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l } return apparentType } - prop = c.getPropertyOfTypeEx(apparentType, ast.MakeSymbolName(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, ast.MakeSymbolName(right.Text())) + indexInfo = c.getApplicableIndexInfoForName(apparentType, right.TextSymbolName()) } if indexInfo == nil { isUncheckedJS := c.isUncheckedJSSuggestion(node, leftType.symbol, true /*excludeClasses*/) @@ -11574,7 +11574,7 @@ func (c *Checker) checkPropertyAccessExpressionOrQualifiedName(node *ast.Node, l return c.anyType } if leftType.symbol == c.globalThisSymbol { - globalSymbol := c.globalThisSymbol.Exports()[ast.MakeSymbolName(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 { @@ -11784,19 +11784,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, ast.MakeSymbolName(propNode.Text())) == nil && c.getApplicableIndexInfoForName(subtype, ast.MakeSymbolName(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(ast.MakeSymbolName(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, ast.MakeSymbolName(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 { @@ -11853,7 +11853,7 @@ func (c *Checker) getSuggestedSymbolForNonexistentProperty(name *ast.Node, conta return c.isValidPropertyAccessForCompletions(parent, containingType, prop) }) } - return c.getSpellingSuggestionForName(ast.MakeSymbolName(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. @@ -13016,7 +13016,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()), ast.MakeSymbolName(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 } @@ -13616,7 +13616,7 @@ func (c *Checker) checkDeprecatedProperty(name *ast.Node, contextualType *Type) if contextualType == nil { return } - prop := c.getPropertyOfType(contextualType, ast.MakeSymbolName(name.Text())) + prop := c.getPropertyOfType(contextualType, name.TextSymbolName()) if prop == nil || len(prop.Declarations()) == 0 { return } @@ -14166,7 +14166,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, ast.MakeSymbolName(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) @@ -14183,7 +14183,7 @@ func (c *Checker) getReferencedValueOrAliasSymbol(reference *ast.Node) *ast.Symb if resolvedSymbol != nil && resolvedSymbol != c.unknownSymbol { return resolvedSymbol } - return c.resolveName(reference, ast.MakeSymbolName(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 { @@ -14810,7 +14810,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, ast.MakeSymbolName(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 @@ -15214,7 +15214,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[ast.MakeSymbolName(name.Text())] + localSymbol = locals[name.TextSymbolName()] } exports := moduleSymbol.Exports() if localSymbol != nil { @@ -16095,7 +16095,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(), ast.MakeSymbolName(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 } @@ -16205,19 +16205,19 @@ func (c *Checker) resolveEntityName(name *ast.Node, meaning ast.SymbolFlags, ign resolveLocation = name } if meaning == ast.SymbolFlagsNamespace { - symbol = c.getMergedSymbol(c.resolveName(resolveLocation, ast.MakeSymbolName(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, ast.MakeSymbolName(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, ast.MakeSymbolName(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, ast.MakeSymbolName(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() @@ -16306,14 +16306,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, ast.MakeSymbolName(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, ast.MakeSymbolName(n.Parent.AsQualifiedName().Right.Text())) + symbol = c.getPropertyOfType(t, n.Parent.AsQualifiedName().Right.TextSymbolName()) if symbol == nil { return nil } @@ -16323,7 +16323,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(ast.MakeSymbolName(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 { @@ -18731,7 +18731,7 @@ func (c *Checker) reportImplicitAny(declaration *ast.Node, t *Type, wideningKind originalKeywordKind := scanner.IdentifierToKeywordKind(name) if (ast.IsCallSignatureDeclaration(declaration.Parent) || ast.IsMethodSignatureDeclaration(declaration.Parent) || ast.IsFunctionTypeNode(declaration.Parent)) && slices.Contains(declaration.Parent.Parameters(), declaration) && - (ast.IsTypeNodeKind(originalKeywordKind) || c.resolveName(declaration, ast.MakeSymbolName(name.Text), ast.SymbolFlagsType, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) != nil) { + (ast.IsTypeNodeKind(originalKeywordKind) || c.resolveName(declaration, name.Text, ast.SymbolFlagsType, nil /*nameNotFoundMessage*/, true /*isUse*/, false /*excludeGlobals*/) != nil) { newName := fmt.Sprintf("arg%v", slices.Index(declaration.Parent.Parameters(), declaration)) typeName := scanner.DeclarationNameToString(param.Name()) + core.IfElse(param.DotDotDotToken != nil, "[]", "") c.errorOrSuggestion(c.noImplicitAny, declaration, diagnostics.Parameter_has_a_name_but_no_type_Did_you_mean_0_Colon_1, newName, typeName) @@ -21141,7 +21141,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, ast.MakeSymbolName(param.Name().Text()), int32(i), trueType) + return c.newTypePredicate(TypePredicateKindIdentifier, param.Name().TextSymbolName(), int32(i), trueType) } } return nil @@ -24730,7 +24730,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(ast.MakeSymbolName(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. @@ -25307,9 +25307,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), ast.MakeSymbolName(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), ast.MakeSymbolName(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= // !!! @@ -25317,7 +25317,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()), ast.MakeSymbolName(current.Text()), meaning) + symbolFromModule = c.getSymbol(c.getExportsOfSymbol(immediateModuleSymbol.Parent()), current.TextSymbolName(), meaning) } } } @@ -29203,7 +29203,7 @@ func (c *Checker) markPropertyAliasReferenced(location *ast.Node /*PropertyAcces } var lexicallyScopedSymbol *ast.Symbol if ast.IsPrivateIdentifier(right) { - lexicallyScopedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(ast.MakeSymbolName(right.Text()), right) + lexicallyScopedSymbol = c.lookupSymbolForPrivateIdentifierDeclaration(right.TextSymbolName(), right) } assignmentKind := getAssignmentTargetKind(location) var apparentType *Type @@ -29217,7 +29217,7 @@ func (c *Checker) markPropertyAliasReferenced(location *ast.Node /*PropertyAcces prop = c.getPrivateIdentifierPropertyOfType(apparentType, lexicallyScopedSymbol) } } else { - prop = c.getPropertyOfType(apparentType, ast.MakeSymbolName(right.Text())) + prop = c.getPropertyOfType(apparentType, right.TextSymbolName()) } } if !(prop != nil && (isConstEnumOrConstEnumOnlyModule(prop) || prop.Flags()&ast.SymbolFlagsEnumMember != 0 && location.Parent.Kind == ast.KindEnumMember)) { @@ -29306,7 +29306,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, ast.MakeSymbolName(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 { @@ -29614,7 +29614,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, ast.MakeSymbolName(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 && @@ -30632,7 +30632,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), ast.MakeSymbolName(left.Name().Text())) + return c.getTypeOfPropertyOfContextualType(c.getTypeFromTypeNode(typeNode), left.Name().TextSymbolName()) } nameType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) if isTypeUsableAsPropertyName(nameType) { @@ -30657,7 +30657,7 @@ func (c *Checker) getContextualTypeForAssignmentExpression(binary *ast.BinaryExp symbol = c.getPropertyOfType(thisType, binder.GetSymbolNameForPrivateIdentifier(thisType.symbol, name.Text())) } } else { - symbol = c.getPropertyOfType(thisType, ast.MakeSymbolName(name.Text())) + symbol = c.getPropertyOfType(thisType, name.TextSymbolName()) } } else { propType := c.checkExpressionCached(left.AsElementAccessExpression().ArgumentExpression) @@ -30808,7 +30808,7 @@ func (c *Checker) getContextualTypeForSubstitutionExpression(template *ast.Node, } func (c *Checker) getContextualImportAttributeType(node *ast.Node) *Type { - return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), ast.MakeSymbolName(node.Name().Text())) + return c.getTypeOfPropertyOfContextualType(c.getGlobalImportAttributesType(), node.Name().TextSymbolName()) } // Returns the effective arguments for an expression that works like a function invocation. @@ -32399,7 +32399,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, ast.MakeSymbolName(node.Text())); propertyDeclaration != nil { + if propertyDeclaration := c.getPropertyOfType(typeOfPattern, node.TextSymbolName()); propertyDeclaration != nil { return propertyDeclaration } } else if ast.IsMetaProperty(parent) && parent.Name() == node { @@ -32484,7 +32484,7 @@ func (c *Checker) getSymbolAtLocation(node *ast.Node, ignoreErrors bool) *ast.Sy } if objectType != nil { - return c.getPropertyOfType(objectType, ast.MakeSymbolName(node.Text())) + return c.getPropertyOfType(objectType, node.TextSymbolName()) } return nil case ast.KindDefaultKeyword, ast.KindFunctionKeyword, ast.KindEqualsGreaterThanToken, ast.KindClassKeyword: @@ -32636,8 +32636,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), ast.MakeSymbolName(name.Text()), meaning)); result == nil { - result = c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), ast.MakeSymbolName(name.Text())) + if result = c.getMergedSymbol(c.getSymbol(c.getExportsOfSymbol(symbol), name.TextSymbolName(), meaning)); result == nil { + result = c.getPropertyOfType(c.getDeclaredTypeOfSymbol(symbol), name.TextSymbolName()) } } } @@ -32912,7 +32912,7 @@ func (c *Checker) containsArgumentsReference(node *ast.Node) bool { } switch node.Kind { case ast.KindIdentifier: - return ast.MakeSymbolName(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 ae6f4dff4ab78..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, ast.MakeSymbolName(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, ast.MakeSymbolName(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 } } @@ -791,7 +791,7 @@ func (r *EmitResolver) CreateLateBoundIndexSignatures(container *ast.Node, enclo } firstIdentifier := ast.GetFirstIdentifier(c.Name().Expression()) - name := r.checker.resolveName(firstIdentifier, ast.MakeSymbolName(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 84372fcc4dc61..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, ast.MakeSymbolName(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/flow.go b/tsc/internal/checker/flow.go index dc1b598e3c91e..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 == ast.MakeSymbolName(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)) } } @@ -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 ast.MakeSymbolName(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: @@ -1726,7 +1726,7 @@ func (c *Checker) writeFlowCacheKey(b *keyBuilder, node *ast.Node, declaredType func (c *Checker) getAccessedPropertyName(access *ast.Node) (ast.SymbolName, bool) { if ast.IsPropertyAccessExpression(access) { - return ast.MakeSymbolName(access.Name().Text()), true + return access.Name().TextSymbolName(), true } if ast.IsElementAccessExpression(access) { return c.tryGetElementAccessExpressionName(access.AsElementAccessExpression()) @@ -1743,7 +1743,7 @@ func (c *Checker) getAccessedPropertyName(access *ast.Node) (ast.SymbolName, boo func (c *Checker) tryGetElementAccessExpressionName(node *ast.ElementAccessExpression) (ast.SymbolName, bool) { switch { case ast.IsStringOrNumericLiteralLike(node.ArgumentExpression): - return ast.MakeSymbolName(node.ArgumentExpression.Text()), true + return node.ArgumentExpression.TextSymbolName(), true case ast.IsEntityNameExpression(node.ArgumentExpression): return c.tryGetNameFromEntityNameExpression(node.ArgumentExpression) } @@ -2140,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, ast.MakeSymbolName(name.Text())) + prop = c.getPropertyOfType(t, name.TextSymbolName()) } if prop != nil { return c.getExplicitTypeOfSymbol(prop, diagnostic) diff --git a/tsc/internal/checker/jsx.go b/tsc/internal/checker/jsx.go index 5635a7dac5ae3..ce6b5b7a04ad1 100644 --- a/tsc/internal/checker/jsx.go +++ b/tsc/internal/checker/jsx.go @@ -221,7 +221,7 @@ func (c *Checker) getContextualTypeForJsxAttribute(attribute *ast.Node, contextF if attributesType == nil || IsTypeAny(attributesType) { return nil } - return c.getTypeOfPropertyOfContextualType(attributesType, ast.MakeSymbolName(attribute.Name().Text())) + return c.getTypeOfPropertyOfContextualType(attributesType, attribute.Name().TextSymbolName()) } return c.getContextualType(attribute.Parent, contextFlags) } @@ -754,7 +754,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme if allAttributesTable != nil { allAttributesTable[attributeSymbol.Name()] = attributeSymbol } - if ast.MakeSymbolName(attributeDecl.Name().Text()) == jsxChildrenPropertyName { + if attributeDecl.Name().TextSymbolName() == jsxChildrenPropertyName { explicitlySpecifyChildrenAttribute = true } if contextualType != nil && checkMode&CheckModeInferential != 0 && checkMode&CheckModeSkipContextSensitive == 0 && c.isContextSensitive(attributeDecl) { @@ -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), ast.MakeSymbolName(node.TagName().Text())) + indexInfo := c.getApplicableIndexInfoForName(c.getJsxType(JsxNames.IntrinsicElements, node), node.TagName().TextSymbolName()) if indexInfo != nil { links.resolvedJsxElementAttributesType = indexInfo.valueType return links.resolvedJsxElementAttributesType diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index d66920310b4e7..a670d55aa1c6a 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -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(ast.MakeSymbolName(typeNode.AsTypeReferenceNode().TypeName.Text()), seenName{t, len(result) - 1}) + seenNames.Add(typeNode.AsTypeReferenceNode().TypeName.TextSymbolName(), seenName{t, len(result) - 1}) } } } @@ -1504,7 +1504,7 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi } } if b.ctx.flags&nodebuilder.FlagsGenerateNamesForShadowedTypeParams != 0 { - rawName := ast.MakeSymbolName(result.Text()) + rawName := result.TextSymbolName() i, _ := b.ctx.typeParameterNamesByTextNextNameCount.Get(rawName) name := rawName @@ -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, ast.MakeSymbolName(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, ast.MakeSymbolName(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) } @@ -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 { diff --git a/tsc/internal/checker/nodebuilderscopes.go b/tsc/internal/checker/nodebuilderscopes.go index b4fdecacc6e68..9e918c97713e5 100644 --- a/tsc/internal/checker/nodebuilderscopes.go +++ b/tsc/internal/checker/nodebuilderscopes.go @@ -230,7 +230,7 @@ func (b *NodeBuilderImpl) enterNewScope(declaration *ast.Node, expandedParams [] continue } typeParamName := b.typeParameterToName(typeParam).Text - add(ast.MakeSymbolName(typeParamName), typeParam.symbol) + add(typeParamName, typeParam.symbol) } }) } 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 39b752d410575..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 ast.MakeSymbolName(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 f191710cfe835..bca5db0a50fc7 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -1978,7 +1978,7 @@ func (c *Checker) getParameterNameAtPosition(signature *Signature, pos int) ast. func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol *ast.Symbol, index int) ast.SymbolName { if elementInfo.labeledDeclaration != nil { - return ast.MakeSymbolName(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) @@ -2805,7 +2805,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(ast.MakeSymbolName(name.Text()), errorTarget) + suggestion = r.c.getSuggestionForNonexistentProperty(name.TextSymbolName(), errorTarget) } } if suggestion != "" { diff --git a/tsc/internal/checker/services.go b/tsc/internal/checker/services.go index 7603962b81b57..92ba415164c14 100644 --- a/tsc/internal/checker/services.go +++ b/tsc/internal/checker/services.go @@ -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 } @@ -594,7 +594,7 @@ func (c *Checker) GetReferencesToSymbolInFile( continue } id := token.AsIdentifier() - if ast.MakeSymbolName(id.Text) != identifierText { + if id.Text != identifierText { continue } refSymbol := c.GetSymbolAtLocation(token) @@ -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, ast.MakeSymbolName(location.Text())) + return c.getPropertyOfType(typeOfObjectLiteral, location.TextSymbolName()) } } return nil diff --git a/tsc/internal/ls/autoimport/extract.go b/tsc/internal/ls/autoimport/extract.go index 7b652ce1759f2..e7adb14807080 100644 --- a/tsc/internal/ls/autoimport/extract.go +++ b/tsc/internal/ls/autoimport/extract.go @@ -251,7 +251,7 @@ func (e *symbolExtractor) extractFromSymbol(name ast.SymbolName, symbol *ast.Sym *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()[ast.MakeSymbolName(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) diff --git a/tsc/internal/ls/autoimport/util.go b/tsc/internal/ls/autoimport/util.go index fec1a718df406..5e6519afbdf0c 100644 --- a/tsc/internal/ls/autoimport/util.go +++ b/tsc/internal/ls/autoimport/util.go @@ -119,20 +119,20 @@ func getDefaultLikeExportNameFromDeclaration(symbol *ast.Symbol) ast.SymbolName // "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 ast.MakeSymbolName(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 ast.MakeSymbolName(d.PropertyName().Text()) + return d.PropertyName().TextSymbolName() } continue } // GH#52694 if name := ast.GetNameOfDeclaration(d); name != nil && name.Kind == ast.KindIdentifier { - return ast.MakeSymbolName(name.Text()) + return name.TextSymbolName() } if symbol.Parent() != nil && !checker.IsExternalModuleSymbol(symbol.Parent()) { return symbol.Parent().Name() diff --git a/tsc/internal/ls/codeactions_fixmissingtypeannotation.go b/tsc/internal/ls/codeactions_fixmissingtypeannotation.go index e69f35af51f19..e7f185454adf6 100644 --- a/tsc/internal/ls/codeactions_fixmissingtypeannotation.go +++ b/tsc/internal/ls/codeactions_fixmissingtypeannotation.go @@ -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) } diff --git a/tsc/internal/ls/codeactions_importfixes.go b/tsc/internal/ls/codeactions_importfixes.go index b96a1c3318023..085b7dbd8f68b 100644 --- a/tsc/internal/ls/codeactions_importfixes.go +++ b/tsc/internal/ls/codeactions_importfixes.go @@ -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(ast.MakeSymbolName(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 { @@ -403,7 +403,7 @@ func getSymbolNamesToImport(sourceFile *ast.SourceFile, ch *checker.Checker, sym } } tokenIsTypeOnly := false - if sym := ch.ResolveName(ast.MakeSymbolName(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}} diff --git a/tsc/internal/ls/codeactions_missingmemberfixer.go b/tsc/internal/ls/codeactions_missingmemberfixer.go index bbd9be8f1a5c9..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, []ast.SymbolName{ast.MakeSymbolName(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), ), ) diff --git a/tsc/internal/ls/completions.go b/tsc/internal/ls/completions.go index c1b324e0b6223..e315955c240a3 100644 --- a/tsc/internal/ls/completions.go +++ b/tsc/internal/ls/completions.go @@ -1331,7 +1331,7 @@ func (l *LanguageService) getCompletionData( if isCurrentlyEditingNode(element, file, position) { continue } - existing.Add(ast.MakeSymbolName(element.PropertyNameOrName().Text())) + existing.Add(element.PropertyNameOrName().TextSymbolName()) } uniques := core.Filter(exports, func(symbol *ast.Symbol) bool { return symbol.Name() != ast.InternalSymbolNameDefault && !existing.Has(symbol.Name()) @@ -1367,7 +1367,7 @@ func (l *LanguageService) getCompletionData( elements = importAttributes.AsImportAttributes().Attributes.Nodes } attributeNames := core.Map(elements, func(el *ast.Node) ast.SymbolName { - return ast.MakeSymbolName(el.AsImportAttribute().Name().Text()) + return el.AsImportAttribute().Name().TextSymbolName() }) existing := collections.NewSetFromItems(attributeNames...) uniques := core.Filter( @@ -4823,7 +4823,7 @@ func filterJsxAttributes( } if attr.Kind == ast.KindJsxAttribute { - existingNames.Add(ast.MakeSymbolName(attr.Name().Text())) + existingNames.Add(attr.Name().TextSymbolName()) } else if ast.IsJsxSpreadAttribute(attr) { setMemberDeclaredBySpreadAssignment(attr, &membersDeclaredBySpreadAssignment, typeChecker) } diff --git a/tsc/internal/ls/findallreferences.go b/tsc/internal/ls/findallreferences.go index cbb6fc3a8f94f..006ed40e76aa5 100644 --- a/tsc/internal/ls/findallreferences.go +++ b/tsc/internal/ls/findallreferences.go @@ -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), ast.MakeSymbolName(node.Text())) != nil + return checker.GetPropertyOfType(checker.GetTypeAtLocation(node.Parent.Parent), node.TextSymbolName()) != nil } return false } diff --git a/tsc/internal/ls/importTracker.go b/tsc/internal/ls/importTracker.go index 85195029613b7..5e6561617554c 100644 --- a/tsc/internal/ls/importTracker.go +++ b/tsc/internal/ls/importTracker.go @@ -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 || ast.MakeSymbolName(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 ast.MakeSymbolName(firstIdentifier.Text()) == exportSymbol.Name() { + 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 || ast.MakeSymbolName(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) } @@ -706,7 +706,7 @@ func symbolNameNoDefault(symbol *ast.Symbol) ast.SymbolName { for _, decl := range symbol.Declarations() { name := ast.GetNameOfDeclaration(decl) if name != nil && ast.IsIdentifier(name) { - return ast.MakeSymbolName(name.Text()) + return name.TextSymbolName() } } return ast.EmptySymbolName diff --git a/tsc/internal/ls/jsdoc.go b/tsc/internal/ls/jsdoc.go index eb07d576de3c0..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, ast.MakeSymbolName(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/sourcedefinition.go b/tsc/internal/ls/sourcedefinition.go index d61936a3872d9..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), ast.MakeSymbolName(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 863c90095876b..ee5da8c36c945 100644 --- a/tsc/internal/ls/string_completions.go +++ b/tsc/internal/ls/string_completions.go @@ -397,7 +397,7 @@ func (l *LanguageService) getStringLiteralCompletionEntries( } exports := typeChecker.GetExportsAndPropertiesOfModule(moduleSpecifierSymbol) existing := collections.NewSetFromItems(core.Map(namedImportsOrExports.Elements(), func(n *ast.Node) ast.SymbolName { - return ast.MakeSymbolName(n.PropertyNameOrName().Text()) + return n.PropertyNameOrName().TextSymbolName() })...) uniques := core.Filter(exports, func(e *ast.Symbol) bool { return e.Name() != ast.InternalSymbolNameDefault && !existing.Has(e.Name()) @@ -2029,7 +2029,7 @@ func getStringLiteralCompletionsFromSignature( } t := typeChecker.GetTypeParameterAtPosition(candidate, argumentInfo.argumentIndex) if ast.IsJsxOpeningLikeElement(call) { - propType := typeChecker.GetTypeOfPropertyOfType(t, ast.MakeSymbolName(editingArgument.AsJsxAttribute().Name().Text())) + propType := typeChecker.GetTypeOfPropertyOfType(t, editingArgument.AsJsxAttribute().Name().TextSymbolName()) if propType != nil { t = propType } diff --git a/tsc/internal/ls/utilities.go b/tsc/internal/ls/utilities.go index 0493769e06c82..ea3ffa679c753 100644 --- a/tsc/internal/ls/utilities.go +++ b/tsc/internal/ls/utilities.go @@ -995,7 +995,7 @@ func getPropertySymbolsFromBaseTypes(symbol *ast.Symbol, propertyName ast.Symbol func getPropertySymbolFromBindingElement(checker *checker.Checker, bindingElement *ast.Node) *ast.Symbol { if typeOfPattern := checker.GetTypeAtLocation(bindingElement.Parent); typeOfPattern != nil { - return checker.GetPropertyOfType(typeOfPattern, ast.MakeSymbolName(bindingElement.Name().Text())) + return checker.GetPropertyOfType(typeOfPattern, bindingElement.Name().TextSymbolName()) } return 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/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/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/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index 8635bfaedf559..2b4a46829eb0e 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -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[ast.MakeSymbolName(localName.Text())] = symbol + containerData.Locals[localName.TextSymbolName()] = symbol oldEnclosing := tx.enclosingDeclaration tx.enclosingDeclaration = synthesizedNamespace 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 } From b1eae9997116f2ee303bf486308700191501b692 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Oct 2026 08:51:54 -0700 Subject: [PATCH 06/14] Cache recent identifier names in the parser Most identifiers in a file repeat a small set of names, and going to the shared intern table for each one makes parsing noticeably slower, especially when many files are parsed in parallel. A small per-parser cache resolves repeated names without touching shared state. --- tsc/internal/ast/symbol_test.go | 7 ++++++- tsc/internal/ast/symbolname_intern.go | 25 +++++++++++++++++++++++++ tsc/internal/parser/parser.go | 7 ++++--- 3 files changed, 35 insertions(+), 4 deletions(-) diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index 6a6b97b73b4a3..8c3757378db33 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -52,12 +52,17 @@ func TestConcurrentSymbolNameInterning(t *testing.T) { 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) - names[j] = ast.MakeSymbolName(text) + if i%2 == 0 { + names[j] = cache.Make(text) + } else { + names[j] = ast.MakeSymbolName(text) + } } results[w] = names }) diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go index 825d571fab7d1..e4f6e00db7776 100644 --- a/tsc/internal/ast/symbolname_intern.go +++ b/tsc/internal/ast/symbolname_intern.go @@ -136,6 +136,31 @@ func storeSymbolNameSlot(slots []atomic.Uint64, hash uint64, v uint64) { } } +// 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 { + hash := hashSymbolNameText(text) + 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} +} + // hashSymbolNameText is FNV-1a with a final mix. Names are short, so this // inlines well and beats a general-purpose hash call. func hashSymbolNameText(text string) uint64 { diff --git a/tsc/internal/parser/parser.go b/tsc/internal/parser/parser.go index c670d64ad21c2..e106502b2cc20 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) } @@ -3040,7 +3041,7 @@ func (p *Parser) parseRightSideOfDot(allowIdentifierNames bool, allowPrivateIden func (p *Parser) newIdentifier(text string) *ast.Node { p.identifierCount++ - id := p.factory.NewIdentifier(text) + id := p.factory.NewIdentifierFromSymbolName(p.identifierNames.Make(text)) if text == "await" { p.statementHasAwaitIdentifier = true } From 395d87ba0effe41d6ca9c535617ea47eb690af72 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Thu, 15 Oct 2026 12:15:07 -0700 Subject: [PATCH 07/14] Reuse the scanner's identifier hash when interning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Interning every identifier at parse time hashes its text, but the scanner has just walked the same bytes. Hashing while scanning saves a second pass over each identifier in the parser's hottest path. │ sec/op │ sec/op vs base │ Parse/empty.ts-20 610.1n ± 2% 610.2n ± 1% ~ (p=0.767 n=12) Parse/checker.ts-20 46.61m ± 3% 45.68m ± 3% -1.99% (p=0.005 n=12) Parse/dom.generated.d.ts-20 16.71m ± 2% 16.53m ± 3% ~ (p=0.178 n=12) Parse/Herebyfile.mjs-20 786.8µ ± 2% 779.4µ ± 1% ~ (p=0.319 n=12) Parse/jsxComplexSignatureHasApplicabilityError.tsx-20 218.6µ ± 2% 213.3µ ± 2% -2.41% (p=0.012 n=12) geomean 606.0µ 598.2µ -1.29% --- tsc/internal/ast/symbolname_intern.go | 33 +++++++++++++----- tsc/internal/parser/jsdoc.go | 4 +-- tsc/internal/parser/parser.go | 20 +++++++++-- tsc/internal/scanner/scanner.go | 48 +++++++++++++++++++++------ 4 files changed, 81 insertions(+), 24 deletions(-) diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go index e4f6e00db7776..0bf951d5a8285 100644 --- a/tsc/internal/ast/symbolname_intern.go +++ b/tsc/internal/ast/symbolname_intern.go @@ -151,7 +151,12 @@ type symbolNameCacheSlot struct { const symbolNameCacheSize = 4096 func (c *SymbolNameCache) Make(text string) SymbolName { - hash := hashSymbolNameText(text) + 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} @@ -161,16 +166,26 @@ func (c *SymbolNameCache) Make(text string) SymbolName { return SymbolName{id} } -// hashSymbolNameText is FNV-1a with a final mix. Names are short, so this -// inlines well and beats a general-purpose hash call. -func hashSymbolNameText(text string) uint64 { - h := uint64(14695981039346656037) - for i := range len(text) { - h ^= uint64(text[i]) - h *= 1099511628211 - } +// 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/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 e106502b2cc20..0e63ea8b24197 100644 --- a/tsc/internal/parser/parser.go +++ b/tsc/internal/parser/parser.go @@ -3040,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.NewIdentifierFromSymbolName(p.identifierNames.Make(text)) + id := p.factory.NewIdentifierFromSymbolName(name) if text == "await" { p.statementHasAwaitIdentifier = true } @@ -5937,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/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 From f0c6b742c05c3ef15b25b2db3cc8e9fa3f30e35c Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Tue, 27 Oct 2026 23:44:21 -0700 Subject: [PATCH 08/14] Store symbol names in 64 bits Interned IDs stay 32 bits, but every struct and map slot that holds a SymbolName aligns its neighbors to 8 bytes, so the 32-bit name was padded to 8 bytes anyway: Identifier.Text, symbolData.name, symbol table map slots, and the checker types that hold names all had a 4-byte hole after it. Widening the field costs nothing, and the spare bits leave room to encode names that never need to enter the table. tsc --extendedDiagnostics memory, median of 3 runs: 32-bit 64-bit self-build-src 224,394K 224,449K +0.02% xstate 268,337K 268,372K +0.01% mui-docs 1,761,690K 1,761,642K -0.00% vscode 2,829,089K 2,826,766K -0.08% --- tsc/internal/ast/symbol.go | 10 +++++++--- tsc/internal/ast/symbolname_intern.go | 4 ++-- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index b505258ad3b23..1a4209f56da88 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -170,16 +170,20 @@ func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags { // 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. +// +// Interned IDs are 32 bits, but SymbolName stores them in 64. Every struct +// and map slot that holds a name aligns its neighbors to 8 bytes, so a 32-bit +// name is padded to 8 bytes anyway; the upper bits cost no memory. type SymbolName struct { - id uint32 + id uint64 } func MakeSymbolName(text string) SymbolName { - return SymbolName{symbolNames.intern(text)} + return SymbolName{uint64(symbolNames.intern(text))} } func (name SymbolName) Value() string { - return symbolNames.text(name.id) + return symbolNames.text(uint32(name.id)) } func (name SymbolName) IsZero() bool { diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go index 0bf951d5a8285..14bc15287c4c1 100644 --- a/tsc/internal/ast/symbolname_intern.go +++ b/tsc/internal/ast/symbolname_intern.go @@ -159,11 +159,11 @@ func (c *SymbolNameCache) Make(text string) SymbolName { 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} + return SymbolName{uint64(slot.id)} } id := symbolNames.internHashed(text, hash) *slot = symbolNameCacheSlot{hash: uint32(hash >> 32), id: id} - return SymbolName{id} + return SymbolName{uint64(id)} } // Symbol name hashes are FNV-1a with a final mix. Names are short, so this From 18bc77d9a57ada8284fd8920180b8ce3736a157c Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 28 Oct 2026 09:33:57 -0700 Subject: [PATCH 09/14] Encode synthesized symbol names in spare bits The checker and binder synthesize names with unbounded numeric parts: private names, unique ES symbols, module patterns, and the "(auto@N)"/"(generated@N)" names. Interning each of these grows the table without bound in a long-lived process, since interned names are never freed. The spare bits of the 64-bit SymbolName can hold them directly instead: a 3-bit kind, a 35-bit number, and the 26-bit ID of the interned base text. These names are never interned, and two names are equal exactly when their texts are equal, because MakeSymbolName parses derived-shaped text back into its derived form. Interned text that starts with the internal "\xFE" prefix is tagged with its own kind, and records the byte after the prefix. This makes IsInternal, IsPrivateName, IsLateBoundName and IsReservedMemberName bit tests rather than lookups of the text. The fixed names are now iota constants generated from a single list (npx hereby generate:symbolnames), so they are compile-time constants and are seeded into the table in order. The zero value is the empty name, so an unset SymbolName needs no special handling, and String is the only way to get the text. --- Herebyfile.mjs | 7 + .../typescript/enums/internalSymbolName.d.ts | 2 +- .../typescript/enums/internalSymbolName.js | 2 +- tools/scripts/tsc/generate-encoder.ts | 2 +- tools/scripts/tsc/generate-enums.ts | 15 +- tsc/internal/api/encoder/decoder_test.go | 12 +- tsc/internal/api/encoder/encoder_generated.go | 2 +- tsc/internal/api/session.go | 4 +- tsc/internal/ast/ast.go | 2 +- tsc/internal/ast/symbol.go | 268 +----------- tsc/internal/ast/symbol_test.go | 96 +++- tsc/internal/ast/symbolname_derived.go | 344 +++++++++++++++ tsc/internal/ast/symbolname_intern.go | 56 ++- tsc/internal/ast/symbolnames_generate.go | 300 +++++++++++++ tsc/internal/ast/symbolnames_generated.go | 411 ++++++++++++++++++ tsc/internal/ast/utilities.go | 8 +- tsc/internal/binder/binder.go | 6 +- tsc/internal/binder/nameresolver.go | 2 +- tsc/internal/checker/checker.go | 152 ++++--- tsc/internal/checker/flow.go | 19 +- tsc/internal/checker/jsx.go | 22 +- tsc/internal/checker/nodebuilder_hover.go | 24 +- tsc/internal/checker/nodebuilderimpl.go | 61 ++- tsc/internal/checker/relater.go | 18 +- tsc/internal/checker/services.go | 8 +- tsc/internal/checker/types_test.go | 2 +- tsc/internal/checker/utilities.go | 25 +- tsc/internal/ls/autoimport/export.go | 2 +- tsc/internal/ls/autoimport/extract.go | 2 +- tsc/internal/ls/autoimport/fix.go | 34 +- tsc/internal/ls/autoimport/import_adder.go | 6 +- tsc/internal/ls/autoimport/index.go | 8 +- tsc/internal/ls/autoimport/view.go | 4 +- .../codeactions_fixmissingtypeannotation.go | 6 +- tsc/internal/ls/codeactions_importfixes.go | 2 +- .../ls/codeactions_missingmemberfixer.go | 10 +- tsc/internal/ls/findallreferences.go | 2 +- tsc/internal/ls/inlay_hints.go | 2 +- tsc/internal/ls/lsutil/utilities.go | 2 +- tsc/internal/ls/signaturehelp.go | 2 +- tsc/internal/ls/string_completions.go | 2 +- tsc/internal/printer/factory.go | 14 +- tsc/internal/printer/printer.go | 4 +- tsc/internal/scanner/utilities.go | 2 +- tsc/internal/tracing/tracing.go | 4 +- .../transformers/declarations/transform.go | 2 +- 46 files changed, 1441 insertions(+), 539 deletions(-) create mode 100644 tsc/internal/ast/symbolname_derived.go create mode 100644 tsc/internal/ast/symbolnames_generate.go create mode 100644 tsc/internal/ast/symbolnames_generated.go diff --git a/Herebyfile.mjs b/Herebyfile.mjs index bf3010588e80a..33f07b6b91e8a 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -473,6 +473,13 @@ export const generateBundled = goGenerateTask("generate:bundled", [{ commands: [["go", "run", "generate.go"]], }]); +export const generateSymbolNames = goGenerateTask("generate:symbolnames", [{ + file: "tsc/internal/ast/symbol.go", + inputs: ["symbolnames_generate.go"], + outputs: ["symbolnames_generated.go"], + commands: [["go", "run", "symbolnames_generate.go"]], +}]); + export const generateChecker = goGenerateTask("generate:checker", [ stringerGenerator("tsc/internal/checker/types.go", "SignatureKind", "stringer_generated.go"), ]); diff --git a/packages/typescript/enums/internalSymbolName.d.ts b/packages/typescript/enums/internalSymbolName.d.ts index 74a6d6beee51a..65ce23420d560 100644 --- a/packages/typescript/enums/internalSymbolName.d.ts +++ b/packages/typescript/enums/internalSymbolName.d.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/symbol.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/symbolnames_generated.go. DO NOT EDIT. export declare enum InternalSymbolName { Call = "__call", diff --git a/packages/typescript/enums/internalSymbolName.js b/packages/typescript/enums/internalSymbolName.js index 26291c993b77b..2ebe82d9d47f9 100644 --- a/packages/typescript/enums/internalSymbolName.js +++ b/packages/typescript/enums/internalSymbolName.js @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/symbol.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/symbolnames_generated.go. DO NOT EDIT. export var InternalSymbolName; (function (InternalSymbolName) { InternalSymbolName["Call"] = "__call"; diff --git a/tools/scripts/tsc/generate-encoder.ts b/tools/scripts/tsc/generate-encoder.ts index 38bc76258385e..34ffa3fba54a6 100644 --- a/tools/scripts/tsc/generate-encoder.ts +++ b/tools/scripts/tsc/generate-encoder.ts @@ -548,7 +548,7 @@ 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; + const textValue = isSymbolNamePrimitive(info.textMember.declaredType) ? `${textAccess}.String()` : textAccess; w.write(`case ${kinds.join(", ")}:`); w.push(); diff --git a/tools/scripts/tsc/generate-enums.ts b/tools/scripts/tsc/generate-enums.ts index 7232166e5198d..bed4b249aa95d 100644 --- a/tools/scripts/tsc/generate-enums.ts +++ b/tools/scripts/tsc/generate-enums.ts @@ -76,7 +76,7 @@ export const enumDefs = [ { name: "EmitOnly", goPrefix: "Emit", goFile: "tsc/internal/compiler/emitter.go", outDir: "packages/typescript/enums", excludeMembers: ["OnlyBuilderSignature"] }, // String enum: Go stores internal names with a "\xFE" sentinel prefix, but the escaped // form sent over the wire uses "__" (see EscapeSymbolName), so map the sentinel accordingly. - { name: "InternalSymbolName", goPrefix: "InternalSymbolName", goFile: "tsc/internal/ast/symbol.go", outDir: "packages/typescript/enums", stringEnum: true, valueReplacements: { InternalSymbolNamePrefix: "__" } }, + { name: "InternalSymbolName", goPrefix: "InternalSymbolName", goFile: "tsc/internal/ast/symbolnames_generated.go", outDir: "packages/typescript/enums", stringEnum: true, valueReplacements: { InternalSymbolNamePrefix: "__" } }, ] satisfies EnumDef[]; function syntaxKindMembers(): EnumMember[] { @@ -103,7 +103,9 @@ function parseGoDeclarationBlock(block: string, def: EnumDef): EnumMember[] { } // Match: PrefixName Type = value or PrefixName = value - const fullMatch = line.match(new RegExp(`^(${prefix}\\w+)\\s+(?:\\S+\\s*)?=\\s*(.+)$`)); + // or, in a keyed composite literal: PrefixName: value, or PrefixName & mask: value, + const fullMatch = line.match(new RegExp(`^(${prefix}\\w+)\\s+(?:\\S+\\s*)?=\\s*(.+)$`)) + ?? (def.stringEnum ? line.match(new RegExp(`^(${prefix}\\w+)(?:\\s*&\\s*\\w+)?:\\s*(.+?),$`)) : null); // Match bare iota continuation: just PrefixName const bareMatch = !fullMatch && iotaExpression !== undefined ? line.match(new RegExp(`^(${prefix}\\w+)$`)) @@ -307,11 +309,14 @@ interface EnumMember { function parseGoEnum(def: EnumDef): EnumMember[] { const source = fs.readFileSync(path.join(ROOT, def.goFile), "utf-8"); - const declarationBlockRegex = /(const|var)\s*\(([\s\S]*?)\n\)/g; + // Numeric enums come from const blocks. String enums come from var blocks or + // keyed composite literals, such as the texts of constant symbol names. + const declarationBlockRegex = /(const|var)\s*\(([\s\S]*?)\n\)|var\s+\w+\s*=\s*[^{\n]*\{([\s\S]*?)\n\}/g; 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)); + const isConst = match[1] === "const"; + if (isConst === !!def.stringEnum) continue; + const members = parseGoDeclarationBlock(match[2] ?? match[3], def).filter(member => !def.excludeMembers?.includes(member.name)); if (members.length > 0) return topoSortMembers(members); } diff --git a/tsc/internal/api/encoder/decoder_test.go b/tsc/internal/api/encoder/decoder_test.go index dc560a1d8ddf2..b890a5cfac822 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.Value(), "x") + assert.Equal(t, decl.Name().AsIdentifier().Text.String(), "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.Value(), "add") + assert.Equal(t, funcDecl.Name().AsIdentifier().Text.String(), "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.Value(), "a") + assert.Equal(t, param0.Name().AsIdentifier().Text.String(), "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.Value(), "bar") + assert.Equal(t, spec.Name().AsIdentifier().Text.String(), "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.Value(), "Foo") + assert.Equal(t, classDecl.Name().AsIdentifier().Text.String(), "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.Value(), "greet") + assert.Equal(t, funcDecl.Name().AsIdentifier().Text.String(), "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 5970b696eac5c..e0921403f9a38 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.Value(), node.Kind, node.Pos(), node.End()) + return strs.add(node.AsIdentifier().Text.String(), 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 ba837e30c6107..316b5376e945a 100644 --- a/tsc/internal/api/session.go +++ b/tsc/internal/api/session.go @@ -3487,7 +3487,7 @@ func (s *Session) resolveSymbolTablePropertyOfSymbol(ctx context.Context, params return order } } - if order := cmp.Compare(left.Name().Value(), right.Name().Value()); order != 0 { + if order := cmp.Compare(left.Name().String(), right.Name().String()); order != 0 { return order } return cmp.Compare(ast.GetSymbolId(left), ast.GetSymbolId(right)) @@ -4319,7 +4319,7 @@ func (s *Session) handleGetTypePredicateOfSignature(ctx context.Context, params resp := &TypePredicateResponse{ Kind: int32(pred.Kind()), ParameterIndex: pred.ParameterIndex(), - ParameterName: pred.ParameterName().Value(), + ParameterName: pred.ParameterName().String(), } if pred.Type() != nil { resp.Type = setup.sd.newTypeResponse(setup.projectID, pred.Type(), setup.checker) diff --git a/tsc/internal/ast/ast.go b/tsc/internal/ast/ast.go index d270a817103b6..327634fd0e642 100644 --- a/tsc/internal/ast/ast.go +++ b/tsc/internal/ast/ast.go @@ -256,7 +256,7 @@ func (n *Node) TextSymbolName() SymbolName { func (n *Node) Text() string { switch n.Kind { case KindIdentifier: - return n.AsIdentifier().Text.Value() + return n.AsIdentifier().Text.String() case KindPrivateIdentifier: return n.AsPrivateIdentifier().Text case KindStringLiteral: diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index 36d38fabbaffd..1c777464b1d81 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -1,7 +1,6 @@ package ast import ( - "bytes" "errors" "iter" "slices" @@ -171,39 +170,30 @@ func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags { } // 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. +// Its zero value is EmptySymbolName. // -// Interned IDs are 32 bits, but SymbolName stores them in 64. Every struct -// and map slot that holds a name aligns its neighbors to 8 bytes, so a 32-bit -// name is padded to 8 bytes anyway; the upper bits cost no memory. -type SymbolName struct { - id uint64 -} +// The low bits hold an intern table ID; the upper bits encode derived names +// and tag internal names. See symbolname_derived.go. +// +// Fixed names, such as SymbolNamePrototype, are constants generated from the +// list in symbolnames_generate.go. +// +//go:generate npx hereby generate:symbolnames +type SymbolName uint64 func MakeSymbolName(text string) SymbolName { - return SymbolName{uint64(symbolNames.intern(text))} -} - -func (name SymbolName) Value() string { - return symbolNames.text(uint32(name.id)) -} - -func (name SymbolName) IsZero() bool { - return name == SymbolName{} + return symbolNames.make(text, hashSymbolNameText(text)) } func (name SymbolName) String() string { - if name.IsZero() { - return "" + if name.derivedKind() != derivedNamePlain { + return name.derivedValue() } - return name.Value() + return symbolNames.text(uint32(name)) } // 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") @@ -219,23 +209,7 @@ func (name *SymbolName) UnmarshalText(text []byte) error { 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") } @@ -246,191 +220,6 @@ func (name *SymbolName) UnmarshalJSON(data []byte) error { return name.UnmarshalText([]byte(text)) } -// EmptySymbolName is a valid empty name, distinct from an unset zero handle. -var EmptySymbolName = MakeSymbolName("") - -// 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") -) - // SymbolTable // // A SymbolTable maps names to symbols and iterates in insertion order, like Strada's Map, so that iterating a table @@ -454,7 +243,7 @@ type SymbolMap struct { // hashSymbolTableKey spreads interned name IDs, which are small and dense, across the index. func hashSymbolTableKey(name SymbolName) uint64 { - h := name.id * 0x9e3779b97f4a7c15 + h := uint64(name) * 0x9e3779b97f4a7c15 return h ^ h>>32 } @@ -644,35 +433,12 @@ func (m *SymbolMap) Clone() SymbolTable { const InternalSymbolNamePrefix = "\xFE" // Invalid UTF8 sequence, will never occur as IdentifierName -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") -) - // 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().Value() + return symbol.Name().String() } // EscapeAllInternalSymbolNames replaces internal symbol name markers ("\xFE") with "__". @@ -681,7 +447,7 @@ func EscapeAllInternalSymbolNames(name string) string { } func EscapeInternalSymbolName(symbolName SymbolName) string { - name := symbolName.Value() + name := symbolName.String() if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok { return "__" + rest } @@ -693,7 +459,7 @@ func EscapeInternalSymbolName(symbolName SymbolName) string { // and user names that already begin with "__" gain an extra leading underscore // so they can be distinguished from internal names. func EscapeSymbolName(symbolName SymbolName) string { - name := symbolName.Value() + name := symbolName.String() if rest, ok := strings.CutPrefix(name, InternalSymbolNamePrefix); ok { return "__" + rest } diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index 879530da0bd1c..3c2ce3ef8fd28 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -25,7 +25,7 @@ func TestSymbolNameInterning(t *testing.T) { symbol.SetName(name) storedName := symbol.Name() assert.Assert(t, storedName == otherName) - assert.Equal(t, storedName.Value(), text) + assert.Equal(t, storedName.String(), text) table := ast.SymbolTableOf(name, symbol) assert.Equal(t, table.Get(otherName), symbol) @@ -73,7 +73,7 @@ func TestConcurrentSymbolNameInterning(t *testing.T) { for w := range workers { assert.Assert(t, results[w][i] == results[0][i]) } - assert.Equal(t, results[0][i].Value(), text) + assert.Equal(t, results[0][i].String(), text) } } @@ -91,9 +91,73 @@ func TestPreinternedSymbolNames(t *testing.T) { t.Run(text, func(t *testing.T) { t.Parallel() assert.Assert(t, name == ast.MakeSymbolName(strings.Clone(text))) - assert.Equal(t, name.Value(), text) + assert.Equal(t, name.String(), text) + }) + } +} + +func TestDerivedSymbolNames(t *testing.T) { + t.Parallel() + const maxNum = 1<<35 - 1 + for text, name := range map[string]ast.SymbolName{ + "\xFE#12@#value": ast.MakePrivateSymbolName(12, "#value"), + "\xFE#0@": ast.MakePrivateSymbolName(0, ""), + "\xFE@iterator@7": ast.MakeUniqueESSymbolName(ast.SymbolNameIteratorProperty, 7), + "\xFE@a@b@7": ast.MakeUniqueESSymbolName(ast.MakeSymbolName("a@b"), 7), + "\xFE\"*.css\"pattern@9": ast.MakeModulePatternSymbolName("*.css", 9), + "(auto@3)": ast.MakeGeneratedSymbolName("", false, 3, ""), + "_(generated@4)_1": ast.MakeGeneratedSymbolName("_", true, 4, "_1"), + "(auto@(auto@5)": ast.MakeGeneratedSymbolName("(auto@", false, 5, ""), + "(auto@1)(auto@2)": ast.MakeGeneratedSymbolName("(auto@1)", false, 2, ""), + "\xFE#" + "34359738367@#x": ast.MakePrivateSymbolName(maxNum, "#x"), + "\xFE#" + "34359738368@#x": ast.MakePrivateSymbolName(maxNum+1, "#x"), + "\xFE@\xFE#1@#x@2": ast.MakeUniqueESSymbolName(ast.MakePrivateSymbolName(1, "#x"), 2), + "\xFEx(auto@1)": ast.MakeGeneratedSymbolName("\xFEx", false, 1, ""), + } { + t.Run(text, func(t *testing.T) { + t.Parallel() + assert.Equal(t, name.String(), text) + assert.Assert(t, name == ast.MakeSymbolName(strings.Clone(text))) + checkSymbolNamePredicates(t, name) }) } + // Text that is not canonical keeps its spelling as a distinct plain name. + for _, text := range []string{"\xFE#012@#x", "\xFE@iterator", "\xFE@x@", "(auto@)", "(auto@1", "\xFE\"x\"pattern@", "\xFE#x(auto@1)", "\xFE", "\xFEcall"} { + name := ast.MakeSymbolName(text) + assert.Equal(t, name.String(), text) + assert.Assert(t, name == ast.MakeSymbolName(strings.Clone(text))) + checkSymbolNamePredicates(t, name) + } + for name, text := range map[ast.SymbolName]string{ + ast.InternalSymbolNameCall: "\xFEcall", + ast.InternalSymbolNameExportStar: "\xFEexport", + ast.InternalSymbolNameExportEquals: "export=", + ast.SymbolNamePrototype: "prototype", + } { + assert.Equal(t, name.String(), text) + assert.Assert(t, name == ast.MakeSymbolName(strings.Clone(text))) + checkSymbolNamePredicates(t, name) + } + description, ok := ast.MakePrivateSymbolName(1, "#x").PrivateNameDescription() + assert.Assert(t, ok) + assert.Equal(t, description, "#x") + description, ok = ast.MakePrivateSymbolName(maxNum+1, "#y").PrivateNameDescription() + assert.Assert(t, ok) + assert.Equal(t, description, "#y") + moduleName, ok := ast.TryGetAmbientModuleNameFromSymbolName(ast.MakeModulePatternSymbolName("*.css", 9)) + assert.Assert(t, ok) + assert.Equal(t, moduleName, "*.css") +} + +// checkSymbolNamePredicates checks the predicates against the name's text. +func checkSymbolNamePredicates(t *testing.T, name ast.SymbolName) { + t.Helper() + text := name.String() + rest, internal := strings.CutPrefix(text, ast.InternalSymbolNamePrefix) + assert.Equal(t, name.IsInternal(), internal, text) + assert.Equal(t, name.IsPrivateName(), internal && strings.HasPrefix(rest, "#"), text) + assert.Equal(t, name.IsLateBoundName(), internal && strings.HasPrefix(rest, "@"), text) + assert.Equal(t, name.IsReservedMemberName(), internal && rest != "" && rest[0] != '#' && rest[0] != '@', text) } func TestSymbolNameMarshaling(t *testing.T) { @@ -110,7 +174,6 @@ func TestSymbolNameMarshaling(t *testing.T) { 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) @@ -138,18 +201,17 @@ func TestSymbolNameMarshaling(t *testing.T) { } } -func TestUnsetSymbolNameMarshaling(t *testing.T) { +func TestEmptySymbolName(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()) + assert.Assert(t, name == ast.EmptySymbolName) + assert.Assert(t, ast.MakeSymbolName("") == ast.EmptySymbolName) + var cache ast.SymbolNameCache + assert.Assert(t, cache.Make("") == ast.EmptySymbolName) + assert.Equal(t, name.String(), "") + name = ast.SymbolNamePrototype + assert.NilError(t, json.Unmarshal([]byte("null"), &name)) + assert.Assert(t, name == ast.EmptySymbolName) } func TestInvalidSymbolNameMarshaling(t *testing.T) { @@ -179,7 +241,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().Value(), "") + assert.Equal(t, symbol.Name().String(), "") assert.Assert(t, symbol.Declarations() == nil) assert.Assert(t, symbol.ValueDeclaration() == nil) assert.Assert(t, symbol.Members() == nil) @@ -209,7 +271,7 @@ 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().Value(), "C") + assert.Equal(t, symbol.Name().String(), "C") assert.Equal(t, symbol.Declarations()[0], declaration) assert.Equal(t, symbol.ValueDeclaration(), declaration) assert.Equal(t, symbol.Members().Get(ast.MakeSymbolName("member")), member) @@ -238,7 +300,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().Value(), "") + assert.Equal(t, symbol.Name().String(), "") assert.Assert(t, symbol.Declarations() == nil) assert.Assert(t, symbol.ValueDeclaration() == nil) assert.Assert(t, symbol.Members() == nil) diff --git a/tsc/internal/ast/symbolname_derived.go b/tsc/internal/ast/symbolname_derived.go new file mode 100644 index 0000000000000..f75550153df04 --- /dev/null +++ b/tsc/internal/ast/symbolname_derived.go @@ -0,0 +1,344 @@ +package ast + +import ( + "encoding/binary" + "strconv" + "strings" +) + +// Some names are synthesized by combining a base name with a symbol, node, or +// generated-name ID, such as private names, unique symbol property names, and +// placeholder text for generated identifiers. Every such ID is distinct, so +// interning them would grow the table without bound in a long-lived process. +// Instead, a derived name packs its kind, ID, and the interned base name into +// the SymbolName itself and renders its text on demand: +// +// bits 61-63: kind (0 for plain interned names) +// bits 26-60: number +// bits 0-25: interned ID of the base text (always an interned name) +// +// Names must be equal exactly when their texts are equal, so MakeSymbolName +// parses text that has a derived form into that form and never interns it. +// Text that only fails to fit (an oversized number, or a base that is itself +// derived) is interned instead. +// +// Interned text that starts with InternalSymbolNamePrefix, such as +// InternalSymbolNameCall, is tagged with its own kind, and its number holds +// the byte after the prefix plus one (zero if there is none). So whether a +// name is internal, and which sort, never requires looking at its text. +type derivedNameKind uint8 + +const ( + derivedNamePlain derivedNameKind = iota + derivedNamePrivate // "\xFE#" number "@" base + derivedNameUniqueESSymbol // "\xFE@" base "@" number + derivedNameModulePattern // "\xFE\"" base "\"pattern@" number + derivedNameAuto // prefix "(auto@" number ")" suffix + derivedNameGenerated // prefix "(generated@" number ")" suffix + derivedNameInternal // "\xFE" base, interned; number is base[1]+1 +) + +const ( + derivedNameKindShift = 61 + derivedNameNumShift = 26 + derivedNameNumMax = 1<<(derivedNameKindShift-derivedNameNumShift) - 1 + derivedNameBaseMask = 1<> derivedNameKindShift) +} + +func (name SymbolName) derivedNum() uint64 { + return uint64(name) >> derivedNameNumShift & derivedNameNumMax +} + +func (name SymbolName) derivedBase() string { + return symbolNames.text(uint32(name & derivedNameBaseMask)) +} + +func encodeDerivedName(kind derivedNameKind, num uint64, base string) (SymbolName, bool) { + if num > derivedNameNumMax { + return 0, false + } + baseName := MakeSymbolName(base) + if !baseName.isInterned() { + return 0, false + } + return SymbolName(uint64(kind)<= 0 +} + +// IsPrivateName reports whether the name is that of a private identifier +// member (InternalSymbolNamePrefix + "#"). +func (name SymbolName) IsPrivateName() bool { + return name.internalMarker() == '#'+1 +} + +// IsLateBoundName reports whether the name is that of a property keyed by a +// unique symbol (InternalSymbolNamePrefix + "@"). +func (name SymbolName) IsLateBoundName() bool { + return name.internalMarker() == '@'+1 +} + +// IsReservedMemberName reports whether the name is an internal member name +// such as "\xFEcall", rather than a private or late-bound name. +func (name SymbolName) IsReservedMemberName() bool { + marker := name.internalMarker() + return marker > 0 && marker != '@'+1 && marker != '#'+1 +} + +// PrivateNameDescription returns the private identifier text (such as "#x") +// of a private name. +func (name SymbolName) PrivateNameDescription() (string, bool) { + if name.derivedKind() == derivedNamePrivate { + return name.derivedBase(), true + } + if !name.IsPrivateName() { + return "", false + } + _, description, ok := strings.Cut(name.String(), "@") + return description, ok +} + +// parseDerivedName returns the derived form of text, if it has one. +func parseDerivedName(text string) (SymbolName, bool) { + if kind, num, base, ok := splitDerivedName(text); ok { + return encodeDerivedName(kind, num, base) + } + return 0, false +} + +// splitDerivedName matches text against the derived name shapes. Only the +// internal kinds start with InternalSymbolNamePrefix, so their kinds alone +// determine the leading bytes of the text. +func splitDerivedName(text string) (kind derivedNameKind, num uint64, base string, ok bool) { + if strings.HasPrefix(text, InternalSymbolNamePrefix) { + if len(text) < 2 { + return derivedNamePlain, 0, "", false + } + rest := text[2:] + switch text[1] { + case '#': + if digits, base, found := strings.Cut(rest, "@"); found { + if num, ok := parseCanonicalUint(digits); ok { + return derivedNamePrivate, num, base, true + } + } + case '@': + if base, digits, found := strings.CutLast(rest, "@"); found { + if num, ok := parseCanonicalUint(digits); ok { + return derivedNameUniqueESSymbol, num, base, true + } + } + case '"': + if base, digits, found := strings.CutLast(rest, modulePatternMarker); found { + if num, ok := parseCanonicalUint(digits); ok { + return derivedNameModulePattern, num, base, true + } + } + } + return derivedNamePlain, 0, "", false + } + if start, end, forNode, num, found := findGeneratedPlaceholder(text); found { + kind := derivedNameAuto + if forNode { + kind = derivedNameGenerated + } + return kind, num, generatedAffixes(text[:start], text[end:]), true + } + return derivedNamePlain, 0, "", false +} + +// findGeneratedPlaceholder finds the first "(auto@N)" or "(generated@N)" in text. +func findGeneratedPlaceholder(text string) (start int, end int, forNode bool, num uint64, found bool) { + for offset := 0; ; { + i := strings.IndexByte(text[offset:], '(') + if i < 0 { + return 0, 0, false, 0, false + } + start = offset + i + rest := text[start+1:] + var digits string + if after, ok := strings.CutPrefix(rest, "auto@"); ok { + digits, forNode = after, false + } else if after, ok := strings.CutPrefix(rest, "generated@"); ok { + digits, forNode = after, true + } + if closing := strings.IndexByte(digits, ')'); closing >= 0 { + if num, ok := parseCanonicalUint(digits[:closing]); ok { + end = len(text) - len(digits) + closing + 1 + return start, end, forNode, num, true + } + } + offset = start + 1 + } +} + +// parseCanonicalUint parses digits as strconv.FormatUint would have printed them. +func parseCanonicalUint(digits string) (uint64, bool) { + if len(digits) == 0 || len(digits) > 1 && digits[0] == '0' { + return 0, false + } + var n uint64 + for i := range len(digits) { + c := digits[i] + if c < '0' || c > '9' { + return 0, false + } + if n > derivedNameNumMax { + return 0, false + } + n = n*10 + uint64(c-'0') + } + return n, true +} diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go index 14bc15287c4c1..1704606f938fb 100644 --- a/tsc/internal/ast/symbolname_intern.go +++ b/tsc/internal/ast/symbolname_intern.go @@ -5,10 +5,12 @@ import ( "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. +// Symbol names are interned into a process-wide table and identified by an +// ID; ID 0 is the empty name, and the fixed names generated in +// symbolnames_generated.go take the IDs after it. Interned names are never +// freed. Names synthesized from symbol and node IDs are not interned; see +// symbolname_derived.go. IDs contain no pointers, so nodes, symbol tables, and +// caches that hold them cost the garbage collector nothing to scan. // // 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 @@ -47,6 +49,19 @@ func newSymbolNameTable() *symbolNameTable { slots := make([]atomic.Uint64, symbolNameInitialSlots) t.shards[i].table.Store(&slots) } + for want := SymbolName(1); want < SymbolName(len(fixedSymbolNameTexts)); want++ { + text := fixedSymbolNameTexts[want] + if text == "" { + panic("fixed symbol name has no text") + } + if _, _, _, ok := splitDerivedName(text); ok { + panic("fixed symbol name has a derived form: " + text) + } + hash := hashSymbolNameText(text) + if id := t.insert(&t.shards[hash&(symbolNameShardCount-1)], hash, text); SymbolName(id) != want { + panic("duplicate fixed symbol name: " + text) + } + } return t } @@ -70,16 +85,21 @@ func (t *symbolNameTable) lookup(slots []atomic.Uint64, hash uint64, text string } } -func (t *symbolNameTable) intern(text string) uint32 { - return t.internHashed(text, hashSymbolNameText(text)) -} - -func (t *symbolNameTable) internHashed(text string, hash uint64) uint32 { +// make returns the name for text. Text with a derived form is never interned, +// so a lookup hit is always the canonical name. The empty name is ID 0, which +// the hash table uses for empty slots, so it is never inserted either. +func (t *symbolNameTable) make(text string, hash uint64) SymbolName { + if text == "" { + return EmptySymbolName + } shard := &t.shards[hash&(symbolNameShardCount-1)] if id := t.lookup(*shard.table.Load(), hash, text); id != 0 { - return id + return internedSymbolName(id, text) } - return t.insert(shard, hash, text) + if name, ok := parseDerivedName(text); ok { + return name + } + return internedSymbolName(t.insert(shard, hash, text), text) } func (t *symbolNameTable) insert(shard *symbolNameShard, hash uint64, text string) uint32 { @@ -159,15 +179,17 @@ func (c *SymbolNameCache) Make(text string) SymbolName { 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{uint64(slot.id)} + return SymbolName(slot.id) + } + name := symbolNames.make(text, hash) + // Only untagged names, whose value is their ID, are cached. + if name.derivedKind() == derivedNamePlain { + *slot = symbolNameCacheSlot{hash: uint32(hash >> 32), id: uint32(name)} } - id := symbolNames.internHashed(text, hash) - *slot = symbolNameCacheSlot{hash: uint32(hash >> 32), id: id} - return SymbolName{uint64(id)} + return name } -// 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 +// Symbol name hashes are FNV-1a with a final mix. The incremental form lets // the scanner hash identifiers while it scans them. const SymbolNameHashSeed uint64 = 14695981039346656037 diff --git a/tsc/internal/ast/symbolnames_generate.go b/tsc/internal/ast/symbolnames_generate.go new file mode 100644 index 0000000000000..7ef74d6848656 --- /dev/null +++ b/tsc/internal/ast/symbolnames_generate.go @@ -0,0 +1,300 @@ +//go:build ignore + +// This program generates symbolnames_generated.go, which declares the fixed +// symbol names as constants and seeds the intern table with their texts. +// Add new fixed names to the list below and run `npx hereby generate:symbolnames`. + +package main + +import ( + "bytes" + "fmt" + "go/format" + "log" + "os" + "strconv" + "strings" + "unicode/utf8" +) + +const internal = "\xFE" // InternalSymbolNamePrefix + +var names = []struct{ name, text, comment string }{ + {"SymbolNameZero", "0", ""}, + {"SymbolNameUnresolved", "<>", ""}, + {"SymbolNameAbstractModuleSource", "AbstractModuleSource", ""}, + {"SymbolNameArray", "Array", ""}, + {"SymbolNameArrayBuffer", "ArrayBuffer", ""}, + {"SymbolNameArrayConstructor", "ArrayConstructor", ""}, + {"SymbolNameArrayLike", "ArrayLike", ""}, + {"SymbolNameAsyncDisposable", "AsyncDisposable", ""}, + {"SymbolNameAsyncDisposableStack", "AsyncDisposableStack", ""}, + {"SymbolNameAsyncGenerator", "AsyncGenerator", ""}, + {"SymbolNameAsyncGeneratorFunction", "AsyncGeneratorFunction", ""}, + {"SymbolNameAsyncIterable", "AsyncIterable", ""}, + {"SymbolNameAsyncIterableIterator", "AsyncIterableIterator", ""}, + {"SymbolNameAsyncIterator", "AsyncIterator", ""}, + {"SymbolNameAsyncIteratorObject", "AsyncIteratorObject", ""}, + {"SymbolNameAtomics", "Atomics", ""}, + {"SymbolNameAwaited", "Awaited", ""}, + {"SymbolNameBigInt", "BigInt", ""}, + {"SymbolNameBigInt64Array", "BigInt64Array", ""}, + {"SymbolNameBigUint64Array", "BigUint64Array", ""}, + {"SymbolNameBoolean", "Boolean", ""}, + {"SymbolNameBuiltinIteratorReturn", "BuiltinIteratorReturn", ""}, + {"SymbolNameCallableFunction", "CallableFunction", ""}, + {"SymbolNameCapitalize", "Capitalize", ""}, + {"SymbolNameClassAccessorDecoratorContext", "ClassAccessorDecoratorContext", ""}, + {"SymbolNameClassAccessorDecoratorResult", "ClassAccessorDecoratorResult", ""}, + {"SymbolNameClassAccessorDecoratorTarget", "ClassAccessorDecoratorTarget", ""}, + {"SymbolNameClassDecoratorContext", "ClassDecoratorContext", ""}, + {"SymbolNameClassFieldDecoratorContext", "ClassFieldDecoratorContext", ""}, + {"SymbolNameClassGetterDecoratorContext", "ClassGetterDecoratorContext", ""}, + {"SymbolNameClassMethodDecoratorContext", "ClassMethodDecoratorContext", ""}, + {"SymbolNameClassSetterDecoratorContext", "ClassSetterDecoratorContext", ""}, + {"SymbolNameDataView", "DataView", ""}, + {"SymbolNameDate", "Date", ""}, + {"SymbolNameDateTimeFormat", "DateTimeFormat", ""}, + {"SymbolNameDisposable", "Disposable", ""}, + {"SymbolNameDisposableStack", "DisposableStack", ""}, + {"SymbolNameElement", "Element", ""}, + {"SymbolNameElementAttributesProperty", "ElementAttributesProperty", ""}, + {"SymbolNameElementChildrenAttribute", "ElementChildrenAttribute", ""}, + {"SymbolNameElementClass", "ElementClass", ""}, + {"SymbolNameElementType", "ElementType", ""}, + {"SymbolNameError", "Error", ""}, + {"SymbolNameErrorConstructor", "ErrorConstructor", ""}, + {"SymbolNameEventTarget", "EventTarget", ""}, + {"SymbolNameExtract", "Extract", ""}, + {"SymbolNameFloat16Array", "Float16Array", ""}, + {"SymbolNameFloat32Array", "Float32Array", ""}, + {"SymbolNameFloat64Array", "Float64Array", ""}, + {"SymbolNameFunction", "Function", ""}, + {"SymbolNameGenerator", "Generator", ""}, + {"SymbolNameIArguments", "IArguments", ""}, + {"SymbolNameImportAttributes", "ImportAttributes", ""}, + {"SymbolNameImportCallOptions", "ImportCallOptions", ""}, + {"SymbolNameImportMeta", "ImportMeta", ""}, + {"SymbolNameImportMetaExpression", "ImportMetaExpression", ""}, + {"SymbolNameInt16Array", "Int16Array", ""}, + {"SymbolNameInt32Array", "Int32Array", ""}, + {"SymbolNameInt8Array", "Int8Array", ""}, + {"SymbolNameIntl", "Intl", ""}, + {"SymbolNameIntrinsicAttributes", "IntrinsicAttributes", ""}, + {"SymbolNameIntrinsicClassAttributes", "IntrinsicClassAttributes", ""}, + {"SymbolNameIntrinsicElements", "IntrinsicElements", ""}, + {"SymbolNameIterable", "Iterable", ""}, + {"SymbolNameIterableIterator", "IterableIterator", ""}, + {"SymbolNameIterator", "Iterator", ""}, + {"SymbolNameIteratorConstructor", "IteratorConstructor", ""}, + {"SymbolNameIteratorObject", "IteratorObject", ""}, + {"SymbolNameIteratorReturnResult", "IteratorReturnResult", ""}, + {"SymbolNameIteratorYieldResult", "IteratorYieldResult", ""}, + {"SymbolNameJSON", "JSON", ""}, + {"SymbolNameJSX", "JSX", ""}, + {"SymbolNameK", "K", ""}, + {"SymbolNameLibraryManagedAttributes", "LibraryManagedAttributes", ""}, + {"SymbolNameLowercase", "Lowercase", ""}, + {"SymbolNameMap", "Map", ""}, + {"SymbolNameMapConstructor", "MapConstructor", ""}, + {"SymbolNameMath", "Math", ""}, + {"SymbolNameNaN", "NaN", ""}, + {"SymbolNameNewableFunction", "NewableFunction", ""}, + {"SymbolNameNoInfer", "NoInfer", ""}, + {"SymbolNameNode", "Node", ""}, + {"SymbolNameNodeList", "NodeList", ""}, + {"SymbolNameNonNullable", "NonNullable", ""}, + {"SymbolNameNumber", "Number", ""}, + {"SymbolNameNumberConstructor", "NumberConstructor", ""}, + {"SymbolNameNumberFormat", "NumberFormat", ""}, + {"SymbolNameObject", "Object", ""}, + {"SymbolNameObjectConstructor", "ObjectConstructor", ""}, + {"SymbolNameOmit", "Omit", ""}, + {"SymbolNamePartial", "Partial", ""}, + {"SymbolNamePick", "Pick", ""}, + {"SymbolNamePromise", "Promise", ""}, + {"SymbolNamePromiseConstructor", "PromiseConstructor", ""}, + {"SymbolNamePromiseLike", "PromiseLike", ""}, + {"SymbolNameRawJSON", "RawJSON", ""}, + {"SymbolNameReadonly", "Readonly", ""}, + {"SymbolNameReadonlyArray", "ReadonlyArray", ""}, + {"SymbolNameReadonlyMap", "ReadonlyMap", ""}, + {"SymbolNameReadonlySet", "ReadonlySet", ""}, + {"SymbolNameRecord", "Record", ""}, + {"SymbolNameReflect", "Reflect", ""}, + {"SymbolNameRegExp", "RegExp", ""}, + {"SymbolNameRegExpConstructor", "RegExpConstructor", ""}, + {"SymbolNameRegExpExecArray", "RegExpExecArray", ""}, + {"SymbolNameRegExpMatchArray", "RegExpMatchArray", ""}, + {"SymbolNameRelativeTimeFormat", "RelativeTimeFormat", ""}, + {"SymbolNameRequired", "Required", ""}, + {"SymbolNameSet", "Set", ""}, + {"SymbolNameSharedArrayBuffer", "SharedArrayBuffer", ""}, + {"SymbolNameString", "String", ""}, + {"SymbolNameStringConstructor", "StringConstructor", ""}, + {"SymbolNameSymbol", "Symbol", ""}, + {"SymbolNameSymbolConstructor", "SymbolConstructor", ""}, + {"SymbolNameT", "T", ""}, + {"SymbolNameTemplateStringsArray", "TemplateStringsArray", ""}, + {"SymbolNameThisType", "ThisType", ""}, + {"SymbolNameTypedPropertyDescriptor", "TypedPropertyDescriptor", ""}, + {"SymbolNameUint16Array", "Uint16Array", ""}, + {"SymbolNameUint32Array", "Uint32Array", ""}, + {"SymbolNameUint8Array", "Uint8Array", ""}, + {"SymbolNameUint8ArrayConstructor", "Uint8ArrayConstructor", ""}, + {"SymbolNameUint8ClampedArray", "Uint8ClampedArray", ""}, + {"SymbolNameUncapitalize", "Uncapitalize", ""}, + {"SymbolNameUppercase", "Uppercase", ""}, + {"SymbolNameWeakMap", "WeakMap", ""}, + {"SymbolNameWeakSet", "WeakSet", ""}, + {"SymbolNameESModule", "__esModule", ""}, + {"SymbolNameUnderscoreDefault", "_default", ""}, + {"SymbolNameAny", "any", ""}, + {"SymbolNameArg", "arg", ""}, + {"SymbolNameArgs", "args", ""}, + {"SymbolNameArguments", "arguments", ""}, + {"SymbolNameAsyncIteratorProperty", "asyncIterator", ""}, + {"SymbolNameBind", "bind", ""}, + {"SymbolNameBooleanKeyword", "boolean", ""}, + {"SymbolNameCaller", "caller", ""}, + {"SymbolNameChildren", "children", ""}, + {"SymbolNameClass", "class", ""}, + {"SymbolNameClassName", "className", ""}, + {"SymbolNameConst", "const", ""}, + {"SymbolNameContext", "context", ""}, + {"SymbolNameDescriptor", "descriptor", ""}, + {"SymbolNameDone", "done", ""}, + {"SymbolNameExports", "exports", ""}, + {"SymbolNameFor", "for", ""}, + {"SymbolNameGetProperty", "get", ""}, + {"SymbolNameGlobal", "global", ""}, + {"SymbolNameGlobalThis", "globalThis", ""}, + {"SymbolNameHasInstance", "hasInstance", ""}, + {"SymbolNameHtmlFor", "htmlFor", ""}, + {"SymbolNameIteratorProperty", "iterator", ""}, + {"SymbolNameLength", "length", ""}, + {"SymbolNameMeta", "meta", ""}, + {"SymbolNameModule", "module", ""}, + {"SymbolNameName", "name", ""}, + {"SymbolNameNever", "never", ""}, + {"SymbolNameNext", "next", ""}, + {"SymbolNameNumberKeyword", "number", ""}, + {"SymbolNameParameterIndex", "parameterIndex", ""}, + {"SymbolNamePrivate", "private", ""}, + {"SymbolNamePropertyKey", "propertyKey", ""}, + {"SymbolNameProps", "props", ""}, + {"SymbolNamePrototype", "prototype", ""}, + {"SymbolNameRequire", "require", ""}, + {"SymbolNameReturn", "return", ""}, + {"SymbolNameSelf", "self", ""}, + {"SymbolNameSetProperty", "set", ""}, + {"SymbolNameStatic", "static", ""}, + {"SymbolNameStringKeyword", "string", ""}, + {"SymbolNameTarget", "target", ""}, + {"SymbolNameThen", "then", ""}, + {"SymbolNameThrow", "throw", ""}, + {"SymbolNameUndefined", "undefined", ""}, + {"SymbolNameUnknown", "unknown", ""}, + {"SymbolNameValue", "value", ""}, + {"SymbolNameWith", "with", ""}, + {"SymbolNameWritable", "writable", ""}, + {"InternalSymbolNameCall", internal + "call", "Call signatures"}, + {"InternalSymbolNameConstructor", internal + "constructor", "Constructor implementations"}, + {"InternalSymbolNameNew", internal + "new", "Constructor signatures"}, + {"InternalSymbolNameIndex", internal + "index", "Index signatures"}, + {"InternalSymbolNameExportStar", internal + "export", "Module export * declarations"}, + {"InternalSymbolNameGlobal", internal + "global", "Global self-reference"}, + {"InternalSymbolNameMissing", internal + "missing", "Indicates missing symbol"}, + {"InternalSymbolNameType", internal + "type", "Anonymous type literal symbol"}, + {"InternalSymbolNameObject", internal + "object", "Anonymous object literal declaration"}, + {"InternalSymbolNameJSXAttributes", internal + "jsxAttributes", "Anonymous JSX attributes object literal declaration"}, + {"InternalSymbolNameClass", internal + "class", "Unnamed class expression"}, + {"InternalSymbolNameFunction", internal + "function", "Unnamed function expression"}, + {"InternalSymbolNameComputed", internal + "computed", "Computed property name declaration with dynamic name"}, + {"InternalSymbolNameAssignmentDeclaration", internal + "assignment", "Assignment declarations"}, + {"InternalSymbolNameInstantiationExpression", internal + "instantiationExpression", "Instantiation expressions"}, + {"InternalSymbolNameImportAttributes", internal + "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", ""}, +} + +func main() { + log.SetFlags(log.LstdFlags | log.Lshortfile) + + seenNames := map[string]bool{} + seenTexts := map[string]string{"": "EmptySymbolName"} + for _, n := range names { + if seenNames[n.name] { + log.Fatalf("duplicate fixed symbol name %s", n.name) + } + if other, ok := seenTexts[n.text]; ok { + log.Fatalf("%s and %s have the same text %q", n.name, other, n.text) + } + seenNames[n.name] = true + seenTexts[n.text] = n.name + } + + var code bytes.Buffer + code.WriteString("// Code generated by symbolnames_generate.go; DO NOT EDIT.\n\n") + code.WriteString("package ast\n\n") + code.WriteString("// Fixed symbol names take the first IDs in the intern table, so they are\n") + code.WriteString("// compile-time constants. Internal names carry the same tag that\n") + code.WriteString("// internedSymbolName gives them.\n") + code.WriteString("const (\n") + code.WriteString("\tEmptySymbolName SymbolName = iota // The zero value.\n") + repeatingIota := true + for _, n := range names { + code.WriteString("\t" + n.name) + if rest, ok := strings.CutPrefix(n.text, internal); ok { + marker := "0" + if rest != "" { + marker = "(" + strconv.QuoteRuneToASCII(rune(rest[0])) + " + 1)" + if rest[0] >= utf8.RuneSelf { + marker = fmt.Sprintf("0x%x", int(rest[0])+1) + } + } + code.WriteString(" SymbolName = iota | internalSymbolNameBits | " + marker + "<>", + SymbolNameAbstractModuleSource: "AbstractModuleSource", + SymbolNameArray: "Array", + SymbolNameArrayBuffer: "ArrayBuffer", + SymbolNameArrayConstructor: "ArrayConstructor", + SymbolNameArrayLike: "ArrayLike", + SymbolNameAsyncDisposable: "AsyncDisposable", + SymbolNameAsyncDisposableStack: "AsyncDisposableStack", + SymbolNameAsyncGenerator: "AsyncGenerator", + SymbolNameAsyncGeneratorFunction: "AsyncGeneratorFunction", + SymbolNameAsyncIterable: "AsyncIterable", + SymbolNameAsyncIterableIterator: "AsyncIterableIterator", + SymbolNameAsyncIterator: "AsyncIterator", + SymbolNameAsyncIteratorObject: "AsyncIteratorObject", + SymbolNameAtomics: "Atomics", + SymbolNameAwaited: "Awaited", + SymbolNameBigInt: "BigInt", + SymbolNameBigInt64Array: "BigInt64Array", + SymbolNameBigUint64Array: "BigUint64Array", + SymbolNameBoolean: "Boolean", + SymbolNameBuiltinIteratorReturn: "BuiltinIteratorReturn", + SymbolNameCallableFunction: "CallableFunction", + SymbolNameCapitalize: "Capitalize", + SymbolNameClassAccessorDecoratorContext: "ClassAccessorDecoratorContext", + SymbolNameClassAccessorDecoratorResult: "ClassAccessorDecoratorResult", + SymbolNameClassAccessorDecoratorTarget: "ClassAccessorDecoratorTarget", + SymbolNameClassDecoratorContext: "ClassDecoratorContext", + SymbolNameClassFieldDecoratorContext: "ClassFieldDecoratorContext", + SymbolNameClassGetterDecoratorContext: "ClassGetterDecoratorContext", + SymbolNameClassMethodDecoratorContext: "ClassMethodDecoratorContext", + SymbolNameClassSetterDecoratorContext: "ClassSetterDecoratorContext", + SymbolNameDataView: "DataView", + SymbolNameDate: "Date", + SymbolNameDateTimeFormat: "DateTimeFormat", + SymbolNameDisposable: "Disposable", + SymbolNameDisposableStack: "DisposableStack", + SymbolNameElement: "Element", + SymbolNameElementAttributesProperty: "ElementAttributesProperty", + SymbolNameElementChildrenAttribute: "ElementChildrenAttribute", + SymbolNameElementClass: "ElementClass", + SymbolNameElementType: "ElementType", + SymbolNameError: "Error", + SymbolNameErrorConstructor: "ErrorConstructor", + SymbolNameEventTarget: "EventTarget", + SymbolNameExtract: "Extract", + SymbolNameFloat16Array: "Float16Array", + SymbolNameFloat32Array: "Float32Array", + SymbolNameFloat64Array: "Float64Array", + SymbolNameFunction: "Function", + SymbolNameGenerator: "Generator", + SymbolNameIArguments: "IArguments", + SymbolNameImportAttributes: "ImportAttributes", + SymbolNameImportCallOptions: "ImportCallOptions", + SymbolNameImportMeta: "ImportMeta", + SymbolNameImportMetaExpression: "ImportMetaExpression", + SymbolNameInt16Array: "Int16Array", + SymbolNameInt32Array: "Int32Array", + SymbolNameInt8Array: "Int8Array", + SymbolNameIntl: "Intl", + SymbolNameIntrinsicAttributes: "IntrinsicAttributes", + SymbolNameIntrinsicClassAttributes: "IntrinsicClassAttributes", + SymbolNameIntrinsicElements: "IntrinsicElements", + SymbolNameIterable: "Iterable", + SymbolNameIterableIterator: "IterableIterator", + SymbolNameIterator: "Iterator", + SymbolNameIteratorConstructor: "IteratorConstructor", + SymbolNameIteratorObject: "IteratorObject", + SymbolNameIteratorReturnResult: "IteratorReturnResult", + SymbolNameIteratorYieldResult: "IteratorYieldResult", + SymbolNameJSON: "JSON", + SymbolNameJSX: "JSX", + SymbolNameK: "K", + SymbolNameLibraryManagedAttributes: "LibraryManagedAttributes", + SymbolNameLowercase: "Lowercase", + SymbolNameMap: "Map", + SymbolNameMapConstructor: "MapConstructor", + SymbolNameMath: "Math", + SymbolNameNaN: "NaN", + SymbolNameNewableFunction: "NewableFunction", + SymbolNameNoInfer: "NoInfer", + SymbolNameNode: "Node", + SymbolNameNodeList: "NodeList", + SymbolNameNonNullable: "NonNullable", + SymbolNameNumber: "Number", + SymbolNameNumberConstructor: "NumberConstructor", + SymbolNameNumberFormat: "NumberFormat", + SymbolNameObject: "Object", + SymbolNameObjectConstructor: "ObjectConstructor", + SymbolNameOmit: "Omit", + SymbolNamePartial: "Partial", + SymbolNamePick: "Pick", + SymbolNamePromise: "Promise", + SymbolNamePromiseConstructor: "PromiseConstructor", + SymbolNamePromiseLike: "PromiseLike", + SymbolNameRawJSON: "RawJSON", + SymbolNameReadonly: "Readonly", + SymbolNameReadonlyArray: "ReadonlyArray", + SymbolNameReadonlyMap: "ReadonlyMap", + SymbolNameReadonlySet: "ReadonlySet", + SymbolNameRecord: "Record", + SymbolNameReflect: "Reflect", + SymbolNameRegExp: "RegExp", + SymbolNameRegExpConstructor: "RegExpConstructor", + SymbolNameRegExpExecArray: "RegExpExecArray", + SymbolNameRegExpMatchArray: "RegExpMatchArray", + SymbolNameRelativeTimeFormat: "RelativeTimeFormat", + SymbolNameRequired: "Required", + SymbolNameSet: "Set", + SymbolNameSharedArrayBuffer: "SharedArrayBuffer", + SymbolNameString: "String", + SymbolNameStringConstructor: "StringConstructor", + SymbolNameSymbol: "Symbol", + SymbolNameSymbolConstructor: "SymbolConstructor", + SymbolNameT: "T", + SymbolNameTemplateStringsArray: "TemplateStringsArray", + SymbolNameThisType: "ThisType", + SymbolNameTypedPropertyDescriptor: "TypedPropertyDescriptor", + SymbolNameUint16Array: "Uint16Array", + SymbolNameUint32Array: "Uint32Array", + SymbolNameUint8Array: "Uint8Array", + SymbolNameUint8ArrayConstructor: "Uint8ArrayConstructor", + SymbolNameUint8ClampedArray: "Uint8ClampedArray", + SymbolNameUncapitalize: "Uncapitalize", + SymbolNameUppercase: "Uppercase", + SymbolNameWeakMap: "WeakMap", + SymbolNameWeakSet: "WeakSet", + SymbolNameESModule: "__esModule", + SymbolNameUnderscoreDefault: "_default", + SymbolNameAny: "any", + SymbolNameArg: "arg", + SymbolNameArgs: "args", + SymbolNameArguments: "arguments", + SymbolNameAsyncIteratorProperty: "asyncIterator", + SymbolNameBind: "bind", + SymbolNameBooleanKeyword: "boolean", + SymbolNameCaller: "caller", + SymbolNameChildren: "children", + SymbolNameClass: "class", + SymbolNameClassName: "className", + SymbolNameConst: "const", + SymbolNameContext: "context", + SymbolNameDescriptor: "descriptor", + SymbolNameDone: "done", + SymbolNameExports: "exports", + SymbolNameFor: "for", + SymbolNameGetProperty: "get", + SymbolNameGlobal: "global", + SymbolNameGlobalThis: "globalThis", + SymbolNameHasInstance: "hasInstance", + SymbolNameHtmlFor: "htmlFor", + SymbolNameIteratorProperty: "iterator", + SymbolNameLength: "length", + SymbolNameMeta: "meta", + SymbolNameModule: "module", + SymbolNameName: "name", + SymbolNameNever: "never", + SymbolNameNext: "next", + SymbolNameNumberKeyword: "number", + SymbolNameParameterIndex: "parameterIndex", + SymbolNamePrivate: "private", + SymbolNamePropertyKey: "propertyKey", + SymbolNameProps: "props", + SymbolNamePrototype: "prototype", + SymbolNameRequire: "require", + SymbolNameReturn: "return", + SymbolNameSelf: "self", + SymbolNameSetProperty: "set", + SymbolNameStatic: "static", + SymbolNameStringKeyword: "string", + SymbolNameTarget: "target", + SymbolNameThen: "then", + SymbolNameThrow: "throw", + SymbolNameUndefined: "undefined", + SymbolNameUnknown: "unknown", + SymbolNameValue: "value", + SymbolNameWith: "with", + SymbolNameWritable: "writable", + InternalSymbolNameCall & derivedNameBaseMask: InternalSymbolNamePrefix + "call", + InternalSymbolNameConstructor & derivedNameBaseMask: InternalSymbolNamePrefix + "constructor", + InternalSymbolNameNew & derivedNameBaseMask: InternalSymbolNamePrefix + "new", + InternalSymbolNameIndex & derivedNameBaseMask: InternalSymbolNamePrefix + "index", + InternalSymbolNameExportStar & derivedNameBaseMask: InternalSymbolNamePrefix + "export", + InternalSymbolNameGlobal & derivedNameBaseMask: InternalSymbolNamePrefix + "global", + InternalSymbolNameMissing & derivedNameBaseMask: InternalSymbolNamePrefix + "missing", + InternalSymbolNameType & derivedNameBaseMask: InternalSymbolNamePrefix + "type", + InternalSymbolNameObject & derivedNameBaseMask: InternalSymbolNamePrefix + "object", + InternalSymbolNameJSXAttributes & derivedNameBaseMask: InternalSymbolNamePrefix + "jsxAttributes", + InternalSymbolNameClass & derivedNameBaseMask: InternalSymbolNamePrefix + "class", + InternalSymbolNameFunction & derivedNameBaseMask: InternalSymbolNamePrefix + "function", + InternalSymbolNameComputed & derivedNameBaseMask: InternalSymbolNamePrefix + "computed", + InternalSymbolNameAssignmentDeclaration & derivedNameBaseMask: InternalSymbolNamePrefix + "assignment", + InternalSymbolNameInstantiationExpression & derivedNameBaseMask: InternalSymbolNamePrefix + "instantiationExpression", + InternalSymbolNameImportAttributes & derivedNameBaseMask: InternalSymbolNamePrefix + "importAttributes", + InternalSymbolNameExportEquals: "export=", + InternalSymbolNameDefault: "default", + InternalSymbolNameThis: "this", + InternalSymbolNameModuleExports: "module.exports", +} diff --git a/tsc/internal/ast/utilities.go b/tsc/internal/ast/utilities.go index fe6d62d244e9b..a0da214b3d5cb 100644 --- a/tsc/internal/ast/utilities.go +++ b/tsc/internal/ast/utilities.go @@ -1716,7 +1716,13 @@ func IsAmbientModuleSymbolName(s SymbolName) bool { // Ambient module symbols are either of the form `"modulename"` or `InternalSymbolNamePrefix + "\"modulename\"pattern@nodeId"`; // see `getDeclarationName`. func TryGetAmbientModuleNameFromSymbolName(name SymbolName) (string, bool) { - s := name.Value() + if kind := name.derivedKind(); kind == derivedNameModulePattern { + base := name.derivedBase() + return base, base != "" + } else if !name.isInterned() { + return "", false + } + s := name.String() if strings.HasPrefix(s, "\"") && strings.HasSuffix(s, "\"") { return s[1 : len(s)-1], true } diff --git a/tsc/internal/binder/binder.go b/tsc/internal/binder/binder.go index fb27efdb448aa..62969493c484b 100644 --- a/tsc/internal/binder/binder.go +++ b/tsc/internal/binder/binder.go @@ -311,7 +311,7 @@ func (b *Binder) getDeclarationName(node *ast.Node) ast.SymbolName { } if pattern := core.TryParsePattern(moduleName); pattern.IsValid() && pattern.StarIndex >= 0 { if attributes := node.AsModuleDeclaration().Attributes; attributes != nil { - return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "\"" + moduleName + "\"pattern@" + strconv.FormatUint(uint64(ast.GetNodeId(attributes)), 10)) + return ast.MakeModulePatternSymbolName(moduleName, ast.GetNodeId(attributes)) } } return ast.MakeSymbolName("\"" + moduleName + "\"") @@ -366,13 +366,13 @@ func (b *Binder) getDisplayName(node *ast.Node) string { } name := b.getDeclarationName(node) if name != ast.InternalSymbolNameMissing { - return name.Value() + return name.String() } return "(Missing)" } func GetSymbolNameForPrivateIdentifier(containingClassSymbol *ast.Symbol, description string) ast.SymbolName { - return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "#" + strconv.Itoa(int(ast.GetSymbolId(containingClassSymbol))) + "@" + description) + return ast.MakePrivateSymbolName(ast.GetSymbolId(containingClassSymbol), description) } func (b *Binder) declareModuleMember(node *ast.Node, symbolFlags ast.SymbolFlags, symbolExcludes ast.SymbolFlags) *ast.Symbol { diff --git a/tsc/internal/binder/nameresolver.go b/tsc/internal/binder/nameresolver.go index 5b4d3d019de1f..19366a939b5a8 100644 --- a/tsc/internal/binder/nameresolver.go +++ b/tsc/internal/binder/nameresolver.go @@ -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.Value(), isolatedModulesLikeFlagName, enumSymbol.Name().Value()+"."+name.Value()) + name.String(), isolatedModulesLikeFlagName, enumSymbol.Name().String()+"."+name.String()) } break loop } diff --git a/tsc/internal/checker/checker.go b/tsc/internal/checker/checker.go index 9aff6d9d356ae..ded8a10818f3b 100644 --- a/tsc/internal/checker/checker.go +++ b/tsc/internal/checker/checker.go @@ -1527,7 +1527,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.Value())) + c.addDiagnostic(createDiagnosticForNode(declaration, diagnostics.Declaration_name_conflicts_with_built_in_global_identifier_0, name.String())) } } } else { @@ -1595,7 +1595,7 @@ 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.Value()) + c.error(errorLocation, message, scanner.DeclarationNameToString(prop.Name()), name.String()) return true } return false @@ -1615,7 +1615,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.Value(), c.symbolToString(classSymbol)) + c.error(errorLocation, diagnostics.Cannot_find_name_0_Did_you_mean_the_static_member_1_0, name.String(), c.symbolToString(classSymbol)) return true } // No static member is present. @@ -1624,7 +1624,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.Value()) + c.error(errorLocation, diagnostics.Cannot_find_name_0_Did_you_mean_the_instance_member_this_0, name.String()) return true } } @@ -1656,7 +1656,7 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name ast.Symb // Report missing lib first suggestedLib := c.getSuggestedLibForNonExistentName(name) if suggestedLib != "" { - c.error(errorLocation, nameNotFoundMessage, declarationName.Value(), suggestedLib) + c.error(errorLocation, nameNotFoundMessage, declarationName.String(), suggestedLib) return } // Then spelling suggestions @@ -1666,7 +1666,7 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name ast.Symb 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.Value(), suggestionName) + diagnostic := NewDiagnosticForNode(errorLocation, message, declarationName.String(), suggestionName) if suggestion.ValueDeclaration() != nil { diagnostic.AddRelatedInfo(NewDiagnosticForNode(suggestion.ValueDeclaration(), diagnostics.X_0_is_declared_here, suggestionName)) } @@ -1674,7 +1674,7 @@ func (c *Checker) onFailedToResolveSymbol(errorLocation *ast.Node, name ast.Symb return } // And then fall back to unspecified "not found" - c.error(errorLocation, nameNotFoundMessage, declarationName.Value()) + c.error(errorLocation, nameNotFoundMessage, declarationName.String()) } func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast.Node, name ast.SymbolName, meaning ast.SymbolFlags) bool { @@ -1687,11 +1687,11 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast. propName := parent.AsQualifiedName().Right.Text() 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.Value(), 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.String(), propName) return true } } - c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, name.Value()) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_namespace_here, name.String()) return true } } @@ -1700,7 +1700,7 @@ func (c *Checker) checkAndReportErrorForUsingTypeAsNamespace(errorLocation *ast. 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.Value()) + c.error(errorLocation, diagnostics.Cannot_export_0_Only_local_declarations_can_be_exported_from_a_module, name.String()) return true } return false @@ -1717,14 +1717,14 @@ func (c *Checker) checkAndReportErrorForUsingNamespaceAsTypeOrValue(errorLocatio // `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.Value()) + c.error(errorLocation, diagnostics.Cannot_use_namespace_0_as_a_value, name.String()) } 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.Value()) + c.error(errorLocation, diagnostics.Cannot_use_namespace_0_as_a_type, name.String()) return true } } @@ -1739,14 +1739,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.Value()) + c.error(errorLocation, diagnostics.An_interface_cannot_extend_a_primitive_type_like_0_It_can_only_extend_other_named_object_types, name.String()) } 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.Value()) + c.error(errorLocation, diagnostics.A_class_cannot_extend_a_primitive_type_like_0_Classes_can_only_extend_constructable_values, name.String()) } 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.Value()) + c.error(errorLocation, diagnostics.A_class_cannot_implement_a_primitive_type_like_0_It_can_only_implement_other_named_object_types, name.String()) } } else { - c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name.Value()) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name.String()) } return true } @@ -1760,11 +1760,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.Value()) + 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.String()) } 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.Value(), core.IfElse(name == ast.SymbolNameK, "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.String(), 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.Value()) + c.error(errorLocation, diagnostics.X_0_only_refers_to_a_type_but_is_being_used_as_a_value_here, name.String()) } return true } @@ -1795,7 +1795,7 @@ func (c *Checker) checkAndReportErrorForUsingValueAsType(errorLocation *ast.Node 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.Value()) + c.error(errorLocation, diagnostics.X_0_refers_to_a_value_but_is_being_used_as_a_type_here_Did_you_mean_typeof_0, name.String()) return true } } @@ -1886,7 +1886,7 @@ func (c *Checker) getSpellingSuggestionForName(name ast.SymbolName, symbols iter } return "" } - return core.GetSpellingSuggestion(name.Value(), symbols, getCandidateName, c.compareSymbols) + return core.GetSpellingSuggestion(name.String(), 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) { @@ -1915,7 +1915,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.Value()) + 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.String()) } } // 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 @@ -1935,7 +1935,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.Value()), typeOnlyDeclaration, name.Value()) + c.addTypeOnlyDeclarationRelatedInfo(c.error(errorLocation, message, name.String()), typeOnlyDeclaration, name.String()) } } // Look at 'compilerOptions.isolatedModules' and not 'getIsolatedModules(...)' (which considers 'verbatimModuleSyntax') @@ -1951,7 +1951,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.Value()) + 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.String()) } } } @@ -3086,7 +3086,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().Value()) + c.addDeprecatedSuggestion(c.getDeprecatedSuggestionNode(node), symbol.Declarations(), symbol.Name().String()) } } } @@ -3169,7 +3169,7 @@ func (c *Checker) checkTypePredicate(node *ast.Node) { } } if !hasReportedError { - c.error(parameterName, diagnostics.Cannot_find_parameter_0, typePredicate.parameterName.Value()) + c.error(parameterName, diagnostics.Cannot_find_parameter_0, typePredicate.parameterName.String()) } } } @@ -3194,7 +3194,7 @@ func (c *Checker) checkIfTypePredicateVariableIsDeclaredInBindingPattern(pattern continue } if ast.IsIdentifier(name) && name.TextSymbolName() == predicateVariableName { - c.error(predicateVariableNode, diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName.Value()) + c.error(predicateVariableNode, diagnostics.A_type_predicate_cannot_reference_element_0_in_a_binding_pattern, predicateVariableName.String()) return true } if ast.IsArrayBindingPattern(name) || ast.IsObjectBindingPattern(name) { @@ -3262,7 +3262,7 @@ func (c *Checker) checkObjectTypeForDuplicateDeclarations(node *ast.Node, checkP isStatic := ast.HasStaticModifier(member) // In non-ambient contexts, check that static members are not named 'prototype'. 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))) + c.error(member.Name(), diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1, symbol.Name().String(), 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. @@ -3731,7 +3731,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().Value()).SetRelatedInfo(relatedDiagnostics) + c.error(core.OrElse(ast.GetNameOfDeclaration(declaration), declaration), diagnostic, symbol.Name().String()).SetRelatedInfo(relatedDiagnostics) } } } @@ -4319,7 +4319,7 @@ func (c *Checker) checkCatchClause(node *ast.Node) { if blockLocals != nil { for caughtName := range node.Locals().All() { if blockLocal := blockLocals.Get(caughtName); blockLocal != nil && blockLocal.ValueDeclaration() != nil && blockLocal.Flags()&ast.SymbolFlagsBlockScopedVariable != 0 { - c.grammarErrorOnNode(blockLocal.ValueDeclaration(), diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName.Value()) + c.grammarErrorOnNode(blockLocal.ValueDeclaration(), diagnostics.Cannot_redeclare_identifier_0_in_catch_clause, caughtName.String()) } } } @@ -4478,7 +4478,7 @@ func (c *Checker) checkClassForStaticPropertyNameConflicts(node *ast.Node) { c.error( memberNameNode, diagnostics.Static_property_0_conflicts_with_built_in_property_Function_0_of_constructor_function_1, - memberName.Value(), + memberName.String(), c.symbolToString(c.getSymbolOfDeclaration(node)), ) } @@ -5914,7 +5914,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.Value()) + c.error(declaration, diagnostics.Cannot_redeclare_exported_variable_0, id.String()) } } } @@ -6768,7 +6768,7 @@ func (c *Checker) getIterationTypesOfMethod(t *Type, resolver *IterationTypesRes if len(methodSignatures) == 0 { if errorNode != nil { diagnostic := core.IfElse(methodName == ast.SymbolNameNext, resolver.mustHaveANextMethodDiagnostic, resolver.mustBeAMethodDiagnostic) - c.reportDiagnostic(NewDiagnosticForNode(errorNode, diagnostic, methodName.Value()), diagnosticOutput) + c.reportDiagnostic(NewDiagnosticForNode(errorNode, diagnostic, methodName.String()), diagnosticOutput) } return IterationTypes{} } @@ -6835,7 +6835,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.Value()), diagnosticOutput) + c.reportDiagnostic(NewDiagnosticForNode(errorNode, resolver.mustHaveAValueDiagnostic, methodName.String()), diagnosticOutput) } yieldType = c.anyType returnTypes = append(returnTypes, c.anyType) @@ -6961,7 +6961,7 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { if sourceSymbol := ast.GetSourceFileOfNode(node).AsNode().Symbol(); sourceSymbol != nil { if alreadyExportedSymbol := sourceSymbol.Exports().Get(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().Value())) + diag.AddRelatedInfo(NewDiagnosticForNode(exportingDeclaration, diagnostics.X_0_is_automatically_exported_here, alreadyExportedSymbol.Name().String())) } } } @@ -6980,9 +6980,9 @@ func (c *Checker) checkAliasSymbol(node *ast.Node) { } importText := "import(\"" + specifierText + "\")" if ast.IsImportSpecifier(node) { - importText = importText + "." + identifierText.Value() + importText = importText + "." + identifierText.String() } - 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) + c.error(errorNode, diagnostics.X_0_is_a_type_and_cannot_be_imported_in_JavaScript_files_Use_1_in_a_JSDoc_type_annotation, identifierText.String(), importText) } return } @@ -7063,7 +7063,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().Value()) + c.addDeprecatedSuggestion(node, targetSymbol.Declarations(), targetSymbol.Name().String()) } } } @@ -7921,7 +7921,7 @@ func hasTypeParameterByName(typeParameters []*Type, name ast.SymbolName) bool { } func getUniqueTypeParameterName(typeParameters []*Type, baseName ast.SymbolName) ast.SymbolName { - baseText := baseName.Value() + baseText := baseName.String() for len(baseText) > 1 && baseText[len(baseText)-1] >= '0' && baseText[len(baseText)-1] <= '9' { baseText = baseText[:len(baseText)-1] } @@ -8445,7 +8445,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.Value()) + c.error(accessNode, diagnostics.Private_or_protected_member_0_cannot_be_accessed_on_a_type_parameter, propertyName.String()) return c.errorType } } @@ -11717,7 +11717,7 @@ func (c *Checker) isMethodAccessForCall(node *ast.Node) bool { 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.Value()) + name := binder.GetSymbolNameForPrivateIdentifier(symbol, propName.String()) prop := symbol.Members().Get(name) if prop != nil { return prop @@ -11903,7 +11903,7 @@ func hasCommonDomTypeName(t *Type) bool { return false } name := t.symbol.Name() - return name == ast.SymbolNameEventTarget || name == ast.SymbolNameNode || name == ast.SymbolNameElement || strings.HasPrefix(name.Value(), "HTML") && strings.HasSuffix(name.Value(), "Element") + return name == ast.SymbolNameEventTarget || name == ast.SymbolNameNode || name == ast.SymbolNameElement || strings.HasPrefix(name.String(), "HTML") && strings.HasSuffix(name.String(), "Element") } func (c *Checker) checkAndReportErrorForExtendingInterface(errorLocation *ast.Node) bool { @@ -13632,7 +13632,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.Get(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().Value()) + diagnostic := c.error(left.ValueDeclaration(), diagnostics.X_0_is_specified_more_than_once_so_this_usage_will_be_overwritten, left.Name().String()) diagnostic.AddRelatedInfo(NewDiagnosticForNode(spread, diagnostics.This_spread_always_overwrites_this_property)) } } @@ -16469,9 +16469,9 @@ func (c *Checker) lateBindMember(parent *ast.Symbol, earlySymbols ast.SymbolTabl name = ast.MakeSymbolName(scanner.DeclarationNameToString(declName)) } for _, d := range declarations { - c.error(core.OrElse(ast.GetNameOfDeclaration(d), d), diagnostics.Duplicate_identifier_0, name.Value()) + c.error(core.OrElse(ast.GetNameOfDeclaration(d), d), diagnostics.Duplicate_identifier_0, name.String()) } - c.error(core.OrElse(declName, decl), diagnostics.Duplicate_identifier_0, name.Value()) + c.error(core.OrElse(declName, decl), diagnostics.Duplicate_identifier_0, name.String()) if lateSymbol.Flags()&ast.SymbolFlagsAccessor != 0 && lateSymbol.Flags()&ast.SymbolFlagsAccessor != symbolFlags&ast.SymbolFlagsAccessor { lateSymbol.SetFlags(lateSymbol.Flags() | ast.SymbolFlagsAccessor) } @@ -16605,7 +16605,7 @@ 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.Value())) + 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.String())) } } c.extendExportSymbols(symbols, nestedSymbols, nil, nil) @@ -16748,7 +16748,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().Value()) + c.addDeprecatedSuggestion(location, target.Declarations(), target.Name().String()) break } else { if symbol == targetSymbol { @@ -18306,7 +18306,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.Value(), ast.TokenFlagsNone) + literal := c.factory.NewStringLiteral(propName.String(), ast.TokenFlagsNone) literal.Loc = node.Loc lhsExpr := parentAccess if !ast.IsLeftHandSideExpression(parentAccess) { @@ -19492,10 +19492,10 @@ func (c *Checker) getApplicableIndexInfo(t *Type, keyType *Type) *IndexInfo { } func (c *Checker) getApplicableIndexInfoForName(t *Type, name ast.SymbolName) *IndexInfo { - if isLateBoundName(name) { + if name.IsLateBoundName() { return c.getApplicableIndexInfo(t, c.esSymbolType) } - return c.getApplicableIndexInfo(t, c.getStringLiteralType(name.Value())) + return c.getApplicableIndexInfo(t, c.getStringLiteralType(name.String())) } func (c *Checker) findApplicableIndexInfo(indexInfos []*IndexInfo, keyType *Type) *IndexInfo { @@ -20323,7 +20323,7 @@ func (c *Checker) isSymbolWithSymbolName(symbol *ast.Symbol) bool { } func (c *Checker) isSymbolWithNumericName(symbol *ast.Symbol) bool { - if isNumericLiteralName(symbol.Name().Value()) { + if isNumericLiteralName(symbol.Name().String()) { return true } if len(symbol.Declarations()) != 0 { @@ -22111,7 +22111,7 @@ func (c *Checker) createUnionOrIntersectionProperty(containingType *Type, name a } } else if isUnion { var indexInfo *IndexInfo - if !isLateBoundName(name) { + if !name.IsLateBoundName() { indexInfo = c.getApplicableIndexInfoForName(t, name) } if indexInfo != nil { @@ -22729,7 +22729,7 @@ func (c *Checker) isDeclarationContainedBy(symbol *ast.Symbol, container *ast.Sy } func (c *Checker) isNamedMember(symbol *ast.Symbol, id ast.SymbolName) bool { - return !isReservedMemberName(id) && c.symbolIsValue(symbol) + return !id.IsReservedMemberName() && c.symbolIsValue(symbol) } func (c *Checker) symbolIsValue(symbol *ast.Symbol) bool { @@ -22806,7 +22806,7 @@ func (c *Checker) getCircularTypeNames() []string { if t.alias != nil { symbol = t.alias.symbol } - if symbol != nil && len(symbol.Name().Value()) != 0 && symbol.Name().Value()[0] != '\xFE' { + if symbol != nil && symbol.Name() != ast.EmptySymbolName && !symbol.Name().IsInternal() { if name := c.SymbolToString(symbol); !slices.Contains(circularTypeNames, name) { circularTypeNames = append(circularTypeNames, name) } @@ -23658,13 +23658,7 @@ func (c *Checker) getESSymbolLikeTypeForNode(node *ast.Node) *Type { if symbol != nil { uniqueType := c.uniqueESSymbolTypes[symbol] if uniqueType == nil { - var b strings.Builder - b.WriteString(ast.InternalSymbolNamePrefix) - b.WriteByte('@') - b.WriteString(symbol.Name().Value()) - b.WriteByte('@') - b.WriteString(strconv.FormatUint(uint64(ast.GetSymbolId(symbol)), 10)) - uniqueType = c.newUniqueESSymbolType(symbol, ast.MakeSymbolName(b.String())) + uniqueType = c.newUniqueESSymbolType(symbol, ast.MakeUniqueESSymbolName(symbol.Name(), ast.GetSymbolId(symbol))) c.uniqueESSymbolTypes[symbol] = uniqueType } return uniqueType @@ -23847,9 +23841,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().Value() + return getSymbolPath(symbol.Parent()) + "." + symbol.Name().String() } - return symbol.Name().Value() + return symbol.Name().String() } func (c *Checker) getTypeReferenceType(node *ast.Node, symbol *ast.Symbol) *Type { @@ -27530,7 +27524,7 @@ func (c *Checker) getLiteralTypeFromPropertyName(name *ast.Node) *Type { } propertyName := ast.GetPropertyNameForPropertyNameNode(name) if propertyName != ast.InternalSymbolNameMissing { - return c.getStringLiteralType(propertyName.Value()) + return c.getStringLiteralType(propertyName.String()) } if ast.IsExpression(name) { return c.getRegularTypeOfLiteralType(c.checkExpression(name)) @@ -27780,7 +27774,7 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy } else { deprecatedNode = accessNode } - c.addDeprecatedSuggestion(deprecatedNode, prop.Declarations(), propName.Value()) + c.addDeprecatedSuggestion(deprecatedNode, prop.Declarations(), propName.String()) } if accessExpression != nil { c.markPropertyAsReferenced(prop, accessExpression, c.isSelfTypeAccess(accessExpression.Expression(), objectType.symbol)) @@ -27810,8 +27804,8 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy return propType } } - if everyType(objectType, isTupleType) && isNumericLiteralName(propName.Value()) { - index := jsnum.FromString(propName.Value()) + if everyType(objectType, isTupleType) && isNumericLiteralName(propName.String()) { + index := jsnum.FromString(propName.String()) if accessNode != nil && everyType(objectType, func(t *Type) bool { return t.TargetTupleType().combinedFlags&ElementFlagsVariable == 0 }) && accessFlags&AccessFlagsAllowMissing == 0 { @@ -27821,9 +27815,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.Value()) + c.error(indexNode, diagnostics.Tuple_type_0_of_length_1_has_no_element_at_index_2, c.TypeToString(objectType), c.getTypeReferenceArity(objectType), propName.String()) } else { - c.error(indexNode, diagnostics.Property_0_does_not_exist_on_type_1, propName.Value(), c.TypeToString(objectType)) + c.error(indexNode, diagnostics.Property_0_does_not_exist_on_type_1, propName.String(), c.TypeToString(objectType)) } } if index >= 0 { @@ -27895,11 +27889,11 @@ func (c *Checker) getPropertyTypeForIndexType(originalObjectType *Type, objectTy } } if objectType.symbol == c.globalThisSymbol && hasPropName && c.globalThisSymbol.Exports().Get(propName) != nil && c.globalThisSymbol.Exports().Get(propName).Flags()&ast.SymbolFlagsBlockScoped != 0 { - c.error(accessExpression, diagnostics.Property_0_does_not_exist_on_type_1, propName.Value(), c.TypeToString(objectType)) + c.error(accessExpression, diagnostics.Property_0_does_not_exist_on_type_1, propName.String(), 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.Value() /* 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.String() /* 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 { @@ -27908,7 +27902,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.Value() /* 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.String() /* as string */, c.TypeToString(objectType), suggestion) } else { suggestion = c.getSuggestionForNonexistentIndexSignature(objectType, accessExpression, indexType) if suggestion != "" { @@ -27975,7 +27969,7 @@ func (c *Checker) typeHasStaticProperty(propName ast.SymbolName, containingType 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().Value() + return symbol.Name().String() } return "" } @@ -28134,8 +28128,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.Value()) { - index := jsnum.FromString(propName.Value()) + if isNumericLiteralName(propName.String()) { + index := jsnum.FromString(propName.String()) return index >= 0 && index < jsnum.Number(limit) } } @@ -28526,7 +28520,7 @@ func (c *Checker) getUniqAssociatedNamesFromTupleType(t *TypeReference, restSymb counters[name] = 0 } counters[name]++ - candidateName := ast.MakeSymbolName(name.Value() + "_" + strconv.Itoa(counters[name])) + candidateName := ast.MakeSymbolName(name.String() + "_" + strconv.Itoa(counters[name])) if counters[candidateName] == 0 { names[i] = candidateName break @@ -31398,7 +31392,7 @@ func (c *Checker) getTypeOfPropertyOfContextualTypeEx(t *Type, name ast.SymbolNa func (c *Checker) getIndexedMappedTypeSubstitutedTypeOfContextualType(t *Type, name ast.SymbolName, nameType *Type) *Type { propertyNameType := nameType if propertyNameType == nil { - propertyNameType = c.getStringLiteralType(name.Value()) + propertyNameType = c.getStringLiteralType(name.String()) } constraint := c.getConstraintTypeFromMappedType(t) // special case for conditional types pretending to be negated types @@ -31435,14 +31429,14 @@ func (c *Checker) getTypeOfConcretePropertyOfContextualType(t *Type, name ast.Sy } func (c *Checker) getTypeFromIndexInfosOfContextualType(t *Type, name ast.SymbolName, nameType *Type) *Type { - if isTupleType(t) && isNumericLiteralName(name.Value()) && jsnum.FromString(name.Value()) >= 0 { + if isTupleType(t) && isNumericLiteralName(name.String()) && jsnum.FromString(name.String()) >= 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.Value()) + nameType = c.getStringLiteralType(name.String()) } indexInfo := c.findApplicableIndexInfo(c.getIndexInfosOfStructuredType(t), nameType) if indexInfo == nil { diff --git a/tsc/internal/checker/flow.go b/tsc/internal/checker/flow.go index 2654024805ac4..5e18fb11de185 100644 --- a/tsc/internal/checker/flow.go +++ b/tsc/internal/checker/flow.go @@ -4,7 +4,6 @@ import ( "math" "slices" "strconv" - "strings" "github.com/microsoft/TypeScript/tsc/internal/ast" "github.com/microsoft/TypeScript/tsc/internal/binder" @@ -1700,7 +1699,7 @@ func (c *Checker) writeFlowCacheKey(b *keyBuilder, node *ast.Node, declaredType return false } b.writeByte('.') - b.writeString(propName.Value()) + b.writeString(propName.String()) return true } if ast.IsElementAccessExpression(node) && ast.IsIdentifier(node.AsElementAccessExpression().ArgumentExpression) { @@ -2113,7 +2112,7 @@ func (c *Checker) getPropertyNameForKnownSymbolName(symbolName ast.SymbolName) a return getPropertyNameFromType(uniqueType) } } - return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "@" + symbolName.Value()) + return ast.MakeSymbolName(ast.InternalSymbolNamePrefix + "@" + symbolName.String()) } // We require the dotted function name in an assertion expression to be comprised of identifiers @@ -2466,11 +2465,10 @@ 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().Value(), ast.InternalSymbolNamePrefix+"#") { - name := symbol.Name().Value() - accessName = c.factory.NewPrivateIdentifier(name[strings.Index(name, "@")+1:]) + if description, ok := symbol.Name().PrivateNameDescription(); ok { + accessName = c.factory.NewPrivateIdentifier(description) } else { - accessName = c.factory.NewIdentifier(symbol.Name().Value()) + accessName = c.factory.NewIdentifier(symbol.Name().String()) } reference := c.factory.NewPropertyAccessExpression(c.factory.NewKeywordExpression(ast.KindThisKeyword), nil, accessName, ast.NodeFlagsNone) reference.Expression().Parent = reference @@ -2489,11 +2487,10 @@ 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().Value(), ast.InternalSymbolNamePrefix+"#") { - name := symbol.Name().Value() - accessName = c.factory.NewPrivateIdentifier(name[strings.Index(name, "@")+1:]) + if description, ok := symbol.Name().PrivateNameDescription(); ok { + accessName = c.factory.NewPrivateIdentifier(description) } else { - accessName = c.factory.NewIdentifier(symbol.Name().Value()) + accessName = c.factory.NewIdentifier(symbol.Name().String()) } for _, staticBlock := range staticBlocks { reference := c.factory.NewPropertyAccessExpression(c.factory.NewKeywordExpression(ast.KindThisKeyword), nil, accessName, ast.NodeFlagsNone) diff --git a/tsc/internal/checker/jsx.go b/tsc/internal/checker/jsx.go index b9710ef0f86e5..e37b4fc1e6ce3 100644 --- a/tsc/internal/checker/jsx.go +++ b/tsc/internal/checker/jsx.go @@ -309,7 +309,7 @@ func (c *Checker) elaborateJsxComponents(node *ast.Node, source *Type, target *T if childrenPropName == ast.InternalSymbolNameMissing { childrenPropName = ast.SymbolNameChildren } - childrenNameType := c.getStringLiteralType(childrenPropName.Value()) + childrenNameType := c.getStringLiteralType(childrenPropName.String()) 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.Value(), c.TypeToString(childrenTargetType)} + invalidTextDiagnosticArgs = []any{tagNameText, childrenPropName.String(), 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.Value(), 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.String(), 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.Value(), 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.String(), c.TypeToString(childrenTargetType)) c.reportDiagnostic(diag, diagnosticOutput) reportedError = true } @@ -823,7 +823,7 @@ func (c *Checker) createJsxAttributesTypeFromAttributesProperty(openingLikeEleme // 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.Value()) + c.error(attributeParent, diagnostics.X_0_are_specified_twice_The_attribute_named_0_will_be_overwritten, jsxChildrenPropertyName.String()) } 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.Value()), nil /*postfixToken*/, nil /*type*/, nil /*initializer*/)) + childrenPropSymbol.SetValueDeclaration(c.factory.NewPropertySignatureDeclaration(nil, c.factory.NewIdentifier(jsxChildrenPropertyName.String()), nil /*postfixToken*/, nil /*type*/, nil /*initializer*/)) childrenPropSymbol.ValueDeclaration().Parent = attributeParent childrenPropSymbol.ValueDeclaration().AsPropertySignatureDeclaration().Symbol = childrenPropSymbol childPropMap := ast.NewSymbolTable() @@ -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.Value()) + c.error(caller, diagnostics.Property_0_does_not_exist_on_type_1, getStringLiteralValue(elementType), "JSX."+JsxNames.IntrinsicElements.String()) return nil } fakeSignature := c.createSignatureForJSXIntrinsic(caller, intrinsicType) @@ -952,7 +952,7 @@ func (c *Checker) getJsxPropsTypeFromClassType(sig *Signature, context *ast.Node 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.Value()) + c.error(context, diagnostics.JSX_element_class_does_not_support_attributes_because_it_does_not_have_a_0_property, forcedLookupLocation.String()) } } if attributesType == nil { @@ -1104,7 +1104,7 @@ func (c *Checker) getNameFromJsxElementAttributesContainer(nameOfAttribPropConta } 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.Value()) + c.error(jsxElementAttribPropInterfaceSym.Declarations()[0], diagnostics.The_global_type_JSX_0_may_not_have_more_than_one_property, nameOfAttribPropContainer.String()) } } } @@ -1243,12 +1243,12 @@ func (c *Checker) getIntrinsicTagSymbol(node *ast.Node) *ast.Symbol { return links.resolvedSymbol } // Wasn't found - c.error(node, diagnostics.Property_0_does_not_exist_on_type_1, tagName.Text(), "JSX."+JsxNames.IntrinsicElements.Value()) + c.error(node, diagnostics.Property_0_does_not_exist_on_type_1, tagName.Text(), "JSX."+JsxNames.IntrinsicElements.String()) 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.Value()) + c.error(node, diagnostics.JSX_element_implicitly_has_type_any_because_no_interface_JSX_0_exists, JsxNames.IntrinsicElements.String()) } links.resolvedSymbol = c.unknownSymbol return links.resolvedSymbol diff --git a/tsc/internal/checker/nodebuilder_hover.go b/tsc/internal/checker/nodebuilder_hover.go index 7d9137fe6bb2d..bcaab16ac6341 100644 --- a/tsc/internal/checker/nodebuilder_hover.go +++ b/tsc/internal/checker/nodebuilder_hover.go @@ -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().Value()), b.enumMemberInitializer(last))) + members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(last.Name().String()), 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().Value()) + b.ctx.approximateLength += 4 + len(p.Name().String()) if initializer != nil { b.ctx.approximateLength += 5 // " = " + value estimate } - members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(p.Name().Value()), initializer)) + members = append(members, b.f.NewEnumMember(b.f.NewIdentifier(p.Name().String()), initializer)) } constModifier := ast.ModifierFlagsNone @@ -418,7 +418,7 @@ func (b *NodeBuilderImpl) expandModuleDecl(symbol *ast.Symbol) *ast.Node { if !b.isNamespaceMember(sym) { continue } - if !scanner.IsIdentifierText(sym.Name().Value(), core.LanguageVariantStandard) { + if !scanner.IsIdentifierText(sym.Name().String(), 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().Value()) + 5 + b.ctx.approximateLength += len(target.Name().String()) + 5 localStmt := b.f.NewVariableStatement(nil, b.f.NewVariableDeclarationList(b.f.NewNodeList([]*ast.Node{ - b.f.NewVariableDeclaration(b.f.NewIdentifier(target.Name().Value()), nil, b.serializeTypeForDeclaration(nil, localType, target, true), nil), + b.f.NewVariableDeclaration(b.f.NewIdentifier(target.Name().String()), 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().Value()) + b.ctx.approximateLength += 16 + len(m.Name().String()) var propertyName *ast.Node if m.Name() != targetName { - propertyName = b.f.NewIdentifier(targetName.Value()) + propertyName = b.f.NewIdentifier(targetName.String()) } stmt := b.f.NewExportDeclaration( nil, false, b.f.NewNamedExports(b.f.NewNodeList([]*ast.Node{ - b.f.NewExportSpecifier(false, propertyName, b.f.NewIdentifier(m.Name().Value())), + b.f.NewExportSpecifier(false, propertyName, b.f.NewIdentifier(m.Name().String())), })), 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().Value()), + name: b.f.NewIdentifier(m.Name().String()), }) 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 && merged.Exports().Len() != 0 if !hasModuleExports { - 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)))}) + bodyStmts = append(bodyStmts, hoverStatement{node: b.f.NewModuleDeclaration(nil, ast.KindNamespaceKeyword, b.f.NewIdentifier(m.Name().String()), 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().Value()); node != nil { + if node := b.serializeNamespaceMember(resolved, m.Name().String()); node != nil { bodyStmts = append(bodyStmts, hoverStatement{node: node}) } } diff --git a/tsc/internal/checker/nodebuilderimpl.go b/tsc/internal/checker/nodebuilderimpl.go index 1a08ed42e198b..afa36f56192e3 100644 --- a/tsc/internal/checker/nodebuilderimpl.go +++ b/tsc/internal/checker/nodebuilderimpl.go @@ -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().Value(), symbol) + identifier := b.newIdentifier(symbol.Name().String(), 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().Value()) + b.ctx.tracker.ReportLikelyUnsafeImportRequiredError(oldSpecifierResult.specifier.AsString(), symbol.Name().String()) } } @@ -774,12 +774,12 @@ func (b *NodeBuilderImpl) createAccessFromSymbolChain(chain []*ast.Symbol, index if exports != nil { // avoid exhaustive iteration in the common case res, ok := exports.Lookup(symbol.Name()) - if symbol.Name() != ast.InternalSymbolNameExportEquals && !isLateBoundName(symbol.Name()) && ok && res != nil && b.ch.getSymbolIfSameReference(res, symbol) != nil { - symbolName = symbol.Name().Value() + if symbol.Name() != ast.InternalSymbolNameExportEquals && !symbol.Name().IsLateBoundName() && ok && res != nil && b.ch.getSymbolIfSameReference(res, symbol) != nil { + symbolName = symbol.Name().String() } else { results := make(map[*ast.Symbol]ast.SymbolName, 1) for name, ex := range exports.All() { - if b.ch.getSymbolIfSameReference(ex, symbol) != nil && !isLateBoundName(name) && name != ast.InternalSymbolNameExportEquals { + if b.ch.getSymbolIfSameReference(ex, symbol) != nil && !name.IsLateBoundName() && name != ast.InternalSymbolNameExportEquals { results[ex] = name // break // must collect all results and sort them - exports are randomly iterated } @@ -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]].Value() + symbolName = results[resultSymbols[0]].String() } } } @@ -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().Value(), b.Name().Value()) }) + slices.SortFunc(properties, func(a, b *ast.Symbol) int { return strings.Compare(a.Name().String(), b.Name().String()) }) 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.Value(), core.LanguageVariantStandard) { - nameNode = b.f.NewIdentifier(name.Value()) + if scanner.IsIdentifierText(name.String(), core.LanguageVariantStandard) { + nameNode = b.f.NewIdentifier(name.String()) } else { - nameNode = b.newStringLiteral(name.Value()) + nameNode = b.newStringLiteral(name.String()) b.ctx.approximateLength += 2 } attributes = append(attributes, b.f.NewImportAttribute(nameNode, b.newStringLiteral(value))) - b.ctx.approximateLength += len(name.Value()) + len(value) + 4 // `name: "value"` + b.ctx.approximateLength += len(name.String()) + len(value) + 4 // `name: "value"` } if len(attributes) == 0 { return nil @@ -1513,13 +1513,13 @@ func (b *NodeBuilderImpl) typeParameterToName(typeParameter *Type) *ast.Identifi break } i++ - name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", rawName.Value(), i)) + name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", rawName.String(), i)) } if name != rawName { // !!! TODO: smuggle type arguments out // const typeArguments = getIdentifierTypeArguments(result); - result = b.newIdentifier(name.Value(), typeParameter.symbol) + result = b.newIdentifier(name.String(), typeParameter.symbol) // setIdentifierTypeArguments(result, typeArguments); } @@ -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.Value()) + parameterName = b.f.NewIdentifier(predicate.parameterName.String()) 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().Value()) + 3 + b.ctx.approximateLength += len(parameterSymbol.Name().String()) + 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().Value(), parameterSymbol) + return b.newIdentifier(parameterSymbol.Name().String(), 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.Value(), nil /*symbol*/) + parameterName = b.newIdentifier(typePredicate.parameterName.String(), nil /*symbol*/) b.e.SetEmitFlags(parameterName, printer.EFNoAsciiEscaping) } else { parameterName = b.f.NewThisTypeNode() @@ -2023,7 +2023,7 @@ func (c *Checker) getExpandedParameters(sig *Signature, skipUnionExpanding bool) } var name ast.SymbolName for true { - name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", names[i].Value(), counter)) + name = ast.MakeSymbolName(fmt.Sprintf("%s_%d", names[i].String(), counter)) _, ok := uniqueNames[name] if ok { counter++ @@ -2527,13 +2527,12 @@ func (b *NodeBuilderImpl) getPropertyNameNodeForSymbol(symbol *ast.Symbol, enclo return fromNameType } - name := symbol.Name().Value() - const privateNamePrefix = ast.InternalSymbolNamePrefix + "#" - if strings.HasPrefix(name, privateNamePrefix) { + var name string + if description, ok := symbol.Name().PrivateNameDescription(); ok { // symbol IDs are unstable - replace #nnn# with #private# - name = name[len(privateNamePrefix):] - name = strings.TrimLeftFunc(name, stringutil.IsDigit) - name = "__#private" + name + name = "__#private@" + description + } else { + name = symbol.Name().String() } return b.createPropertyNameNodeForIdentifierOrLiteral(name, singleQuote, stringNamed, isMethod, symbol) @@ -2601,7 +2600,7 @@ func (b *NodeBuilderImpl) addPropertyToElementList(propertySymbol *ast.Symbol, t } saveEnclosingDeclaration := b.ctx.enclosingDeclaration b.ctx.enclosingDeclaration = nil - if isLateBoundName(propertySymbol.Name()) { + if propertySymbol.Name().IsLateBoundName() { if len(propertySymbol.Declarations()) > 0 { decl := propertySymbol.Declarations()[0] if b.ch.hasLateBindableName(decl) { @@ -2774,7 +2773,7 @@ func (b *NodeBuilderImpl) createTypeNodesFromResolvedType(resolvedType *Structur continue } if getDeclarationModifierFlagsFromSymbol(propertySymbol)&(ast.ModifierFlagsPrivate|ast.ModifierFlagsProtected) != 0 { - b.ctx.tracker.ReportPrivateInBaseOfClassExpression(propertySymbol.Name().Value()) + b.ctx.tracker.ReportPrivateInBaseOfClassExpression(propertySymbol.Name().String()) } if IsPrivateIdentifierSymbol(propertySymbol) { b.ctx.tracker.ReportPrivateInBaseOfClassExpression(ast.SymbolNameText(propertySymbol)) @@ -2871,7 +2870,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().Value(), core.LanguageVariantStandard) && core.Some(symbol.Declarations(), func(declaration *ast.Node) bool { + isStaticMethodSymbol := symbol.Flags()&ast.SymbolFlagsMethod != 0 && scanner.IsIdentifierText(symbol.Name().String(), core.LanguageVariantStandard) && core.Some(symbol.Declarations(), func(declaration *ast.Node) bool { return ast.IsStatic(declaration) && !b.ch.isLateBindableIndexSignature(ast.GetNameOfDeclaration(declaration)) }) isNonLocalFunctionSymbol := false @@ -3133,7 +3132,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).Value(), nil /*symbol*/), + b.newIdentifier(b.ch.getTupleElementLabel(t.Target().AsTupleType().elementInfos[i], nil, i).String(), 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]), ) @@ -3531,7 +3530,7 @@ func (b *NodeBuilderImpl) typeToTypeNode(t *Type) *ast.TypeNode { if !b.shouldExpandType(t, true /*isAlias*/) { sym := t.alias.Symbol() typeArgumentNodes := b.mapToTypeNodes(t.alias.TypeArguments(), false /*isBareList*/) - if isReservedMemberName(sym.Name()) && sym.Flags()&ast.SymbolFlagsClass == 0 { + if sym.Name().IsReservedMemberName() && sym.Flags()&ast.SymbolFlagsClass == 0 { return b.f.NewTypeReferenceNode(b.f.NewIdentifier(""), typeArgumentNodes) } if typeArgumentNodes != nil && len(typeArgumentNodes.Nodes) == 1 && sym == b.ch.globalArrayType.symbol { @@ -3590,8 +3589,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.Value()) - return b.f.NewTypeReferenceNode(b.newIdentifier(name.Text.Value(), t.symbol), nil /*typeArguments*/) + b.ctx.approximateLength += len(name.Text.String()) + return b.f.NewTypeReferenceNode(b.newIdentifier(name.Text.String(), t.symbol), nil /*typeArguments*/) } // Ignore constraint/default when creating a usage (as opposed to declaration) of a type parameter. if t.symbol != nil { diff --git a/tsc/internal/checker/relater.go b/tsc/internal/checker/relater.go index c939a6d5cbdb2..80575d0d4185a 100644 --- a/tsc/internal/checker/relater.go +++ b/tsc/internal/checker/relater.go @@ -605,7 +605,7 @@ func (c *Checker) elaborateElement(source *Type, target *Type, relation *Relatio } else { targetNode = target.symbol.Declarations()[0] } - propertyNameText := propertyName.Value() + propertyNameText := propertyName.String() if propertyName == ast.EmptySymbolName || nameType.flags&TypeFlagsUniqueESSymbol != 0 { propertyNameText = c.TypeToString(nameType) } @@ -723,8 +723,8 @@ func (c *Checker) isKnownProperty(targetType *Type, name ast.SymbolName, isCompa // we should remove this exception. if c.getPropertyOfObjectType(targetType, name) != nil || c.getApplicableIndexInfoForName(targetType, name) != nil || - isLateBoundName(name) && c.getIndexInfoOfType(targetType, c.stringType) != nil || - isComparingJsxAttributes && isHyphenatedJsxName(name.Value()) { + name.IsLateBoundName() && c.getIndexInfoOfType(targetType, c.stringType) != nil || + isComparingJsxAttributes && isHyphenatedJsxName(name.String()) { // For JSXAttributes, if the attribute has a hyphenated name, consider that the attribute to be known. return true } @@ -1114,7 +1114,7 @@ func (c *Checker) getMatchingUnionConstituentForType(unionType *Type, t *Type) * // an empty name if no such discriminant property exists. func (c *Checker) getKeyPropertyName(t *Type) ast.SymbolName { u := t.AsUnionType() - if u.keyPropertyName.IsZero() { + if u.keyPropertyName == ast.EmptySymbolName { u.keyPropertyName, u.constituentMap = c.computeKeyPropertyNameAndMap(t) } if u.keyPropertyName == ast.InternalSymbolNameMissing { @@ -1617,7 +1617,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).Value(), c.getParameterNameAtPosition(target, i).Value()) + errorReporter(diagnostics.Types_of_parameters_0_and_1_are_incompatible, c.getParameterNameAtPosition(source, i).String(), c.getParameterNameAtPosition(target, i).String()) } return TernaryFalse } @@ -1687,7 +1687,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.Value(), target.parameterName.Value()) + errorReporter(diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, source.parameterName.String(), target.parameterName.String()) errorReporter(diagnostics.Type_predicate_0_is_not_assignable_to_1, c.typePredicateToString(source), c.typePredicateToString(target)) } return TernaryFalse @@ -1988,7 +1988,7 @@ func (c *Checker) getTupleElementLabel(elementInfo TupleElementInfo, restSymbol if restSymbol != nil { rootName = restSymbol.Name() } - return ast.MakeSymbolName(rootName.Value() + "_" + strconv.Itoa(index)) + return ast.MakeSymbolName(rootName.String() + "_" + strconv.Itoa(index)) } func (c *Checker) getTupleElementLabelFromBindingElement(node *ast.Node, index int, elementFlags ElementFlags) ast.SymbolName { @@ -2860,7 +2860,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().Value()) + return source.objectFlags&ObjectFlagsJsxAttributes != 0 && isHyphenatedJsxName(sourceProp.Name().String()) } func (c *Checker) isTypeSubsetOf(source *Type, target *Type) bool { @@ -4307,7 +4307,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.Value()) || name == ast.SymbolNameLength) && (!optionalsOnly || targetProp.Flags()&ast.SymbolFlagsOptional != 0) { + if targetProp.Flags()&ast.SymbolFlagsPrototype == 0 && (!numericNamesOnly || isNumericLiteralName(name.String()) || 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) diff --git a/tsc/internal/checker/services.go b/tsc/internal/checker/services.go index dc398646c24e1..e0d9bb71d57c0 100644 --- a/tsc/internal/checker/services.go +++ b/tsc/internal/checker/services.go @@ -133,7 +133,7 @@ func (c *Checker) GetExportsOfModule(symbol *ast.Symbol) []*ast.Symbol { func (c *Checker) ForEachExportAndPropertyOfModule(moduleSymbol *ast.Symbol, cb func(*ast.Symbol, ast.SymbolName)) { for key, exportedSymbol := range c.getExportsOfModule(moduleSymbol).All() { - if !isReservedMemberName(key) { + if !key.IsReservedMemberName() { cb(exportedSymbol, key) } } @@ -528,7 +528,7 @@ func (c *Checker) IsDeclarationUsed( if jsxElementsPresent && jsxModeNeedsExplicitImport { jsxNamespace := c.getJsxNamespace(sourceFile.AsNode()) jsxFragmentFactory := c.GetJsxFragmentFactory(sourceFile.AsNode()) - identifierText := identifier.Text.Value() + identifierText := identifier.Text.String() if identifierText == jsxNamespace { return true } @@ -553,7 +553,7 @@ func (c *Checker) IsSymbolReferencedInFile( symbol *ast.Symbol, ) bool { identifierText := definition.Text - for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText.Value(), sourceFile.AsNode()) { + for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText.String(), sourceFile.AsNode()) { if !ast.IsIdentifier(token) { continue } @@ -588,7 +588,7 @@ func (c *Checker) GetReferencesToSymbolInFile( ) []*ast.Node { identifierText := symbol.Name() var result []*ast.Node - for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText.Value(), sourceFile.AsNode()) { + for _, token := range getPossibleSymbolReferenceNodes(sourceFile, identifierText.String(), sourceFile.AsNode()) { if !ast.IsIdentifier(token) { continue } diff --git a/tsc/internal/checker/types_test.go b/tsc/internal/checker/types_test.go index f26563287e894..48f03cef2b3f4 100644 --- a/tsc/internal/checker/types_test.go +++ b/tsc/internal/checker/types_test.go @@ -310,7 +310,7 @@ func TestTemporaryPropertyCounts(t *testing.T) { names := func(p *temporaryPropertyCounts) []string { var result []string for _, e := range p.entries { - result = append(result, e.name.Value()) + result = append(result, e.name.String()) } return result } diff --git a/tsc/internal/checker/utilities.go b/tsc/internal/checker/utilities.go index 57268b828f467..0983e96dec39c 100644 --- a/tsc/internal/checker/utilities.go +++ b/tsc/internal/checker/utilities.go @@ -381,7 +381,7 @@ func (c *Checker) compareSymbolsWorker(s1, s2 *ast.Symbol) int { } else if len(s2.Declarations()) != 0 { return 1 } - if r := strings.Compare(s1.Name().Value(), s2.Name().Value()); r != 0 { + if r := strings.Compare(s1.Name().String(), s2.Name().String()); r != 0 { return r } // Fall back to symbol IDs. This is a last resort that should happen only when symbols have @@ -644,7 +644,7 @@ func compareTypeNames(t1, t2 *Type) int { if s2 == nil { return -1 } - if c := strings.Compare(s1.Name().Value(), s2.Name().Value()); c != 0 { + if c := strings.Compare(s1.Name().String(), s2.Name().String()); c != 0 { return c } // Keep distinct same-named declarations together before comparing alias arguments or structure. @@ -1135,19 +1135,14 @@ func isVariableDeclarationInVariableStatement(node *ast.Node) bool { } func IsKnownSymbol(symbol *ast.Symbol) bool { - return isLateBoundName(symbol.Name()) + return symbol.Name().IsLateBoundName() } func IsPrivateIdentifierSymbol(symbol *ast.Symbol) bool { if symbol == nil { return false } - return strings.HasPrefix(symbol.Name().Value(), ast.InternalSymbolNamePrefix+"#") -} - -func isLateBoundName(symbolName ast.SymbolName) bool { - name := symbolName.Value() - return len(name) >= 2 && name[0] == '\xfe' && name[1] == '@' + return symbol.Name().IsPrivateName() } func isObjectOrArrayLiteralType(t *Type) bool { @@ -1740,7 +1735,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).Value() + return baseStr + "." + ast.GetPropertyNameForPropertyNameNode(expr.AsElementAccessExpression().ArgumentExpression).String() } case ast.IsIdentifier(expr): return expr.Text() @@ -1791,14 +1786,6 @@ func getAnyImportSyntax(node *ast.Node) *ast.Node { return importNode } -// 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(symbolName ast.SymbolName) bool { - name := symbolName.Value() - return len(name) >= 2 && name[0] == '\xFE' && name[1] != '@' && name[1] != '#' -} - func introducesArgumentsExoticObject(node *ast.Node) bool { switch node.Kind { case ast.KindMethodDeclaration, ast.KindMethodSignature, ast.KindConstructor, ast.KindGetAccessor, @@ -1811,7 +1798,7 @@ func introducesArgumentsExoticObject(node *ast.Node) bool { func symbolsToArray(symbols ast.SymbolTable) []*ast.Symbol { var result []*ast.Symbol for id, symbol := range symbols.All() { - if !isReservedMemberName(id) { + if !id.IsReservedMemberName() { result = append(result, symbol) } } diff --git a/tsc/internal/ls/autoimport/export.go b/tsc/internal/ls/autoimport/export.go index 76739b4dd0cdd..01e3d8adab82b 100644 --- a/tsc/internal/ls/autoimport/export.go +++ b/tsc/internal/ls/autoimport/export.go @@ -116,7 +116,7 @@ type Export struct { } func (e *Export) Name() ast.SymbolName { - if !e.localName.IsZero() && e.localName != ast.EmptySymbolName { + if e.localName != ast.EmptySymbolName { return e.localName } if e.ExportName == ast.InternalSymbolNameExportEquals { diff --git a/tsc/internal/ls/autoimport/extract.go b/tsc/internal/ls/autoimport/extract.go index 8102aeff327c7..9880c9d8de6a8 100644 --- a/tsc/internal/ls/autoimport/extract.go +++ b/tsc/internal/ls/autoimport/extract.go @@ -451,7 +451,7 @@ func getSyntax(symbol *ast.Symbol) ExportSyntax { } func isUnusableName(name ast.SymbolName) bool { - return name.IsZero() || name == ast.EmptySymbolName || + return name == ast.EmptySymbolName || name == ast.SymbolNameUnderscoreDefault || name == ast.InternalSymbolNameExportStar || name == ast.InternalSymbolNameDefault || diff --git a/tsc/internal/ls/autoimport/fix.go b/tsc/internal/ls/autoimport/fix.go index 3d7e6d17449cc..e81a48a95f70f 100644 --- a/tsc/internal/ls/autoimport/fix.go +++ b/tsc/internal/ls/autoimport/fix.go @@ -217,10 +217,10 @@ func addToExistingImport( case ast.KindObjectBindingPattern: bindingPattern := importClauseOrBindingPattern.AsBindingPattern() if defaultImport != nil { - addElementToBindingPattern(ct, file, bindingPattern, defaultImport.name.Value(), "default") + addElementToBindingPattern(ct, file, bindingPattern, defaultImport.name.String(), "default") } for _, namedImport := range namedImports { - addElementToBindingPattern(ct, file, bindingPattern, namedImport.name.Value(), "") + addElementToBindingPattern(ct, file, bindingPattern, namedImport.name.String(), "") } return case ast.KindImportClause: @@ -241,7 +241,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.Value()), change.NodeOptions{Suffix: ", "}) + ct.InsertNodeAt(file, core.TextPos(astnav.GetStartOfNode(importClause.AsNode(), file, false)), ct.NodeFactory.NewIdentifier(defaultImport.name.String()), change.NodeOptions{Suffix: ", "}) } if len(namedImports) > 0 { @@ -254,7 +254,7 @@ func addToExistingImport( return ct.NodeFactory.NewImportSpecifier( (!importClause.IsTypeOnly() || promoteFromTypeOnly) && shouldUseTypeOnly(namedImport.addAsTypeOnly, preferences), identifier, - ct.NodeFactory.NewIdentifier(namedImport.name.Value()), + ct.NodeFactory.NewIdentifier(namedImport.name.String()), ) }) slices.SortFunc(newSpecifiers, specifierComparer) @@ -377,7 +377,7 @@ func getNewImports( var defaultImportNode *ast.Node if defaultImport != nil { - defaultImportNode = ct.NodeFactory.NewIdentifier(defaultImport.name.Value()) + defaultImportNode = ct.NodeFactory.NewIdentifier(defaultImport.name.String()) } statements = append(statements, makeImport(ct, defaultImportNode, core.Map(namedImports, func(namedImport *newImportBinding) *ast.Node { @@ -388,7 +388,7 @@ func getNewImports( return ct.NodeFactory.NewImportSpecifier( !topLevelTypeOnly && shouldUseTypeOnly(namedImport.addAsTypeOnly, preferences), namedImportPropertyName, - ct.NodeFactory.NewIdentifier(namedImport.name.Value()), + ct.NodeFactory.NewIdentifier(namedImport.name.String()), ) }), moduleSpecifierStringLiteral, topLevelTypeOnly)) } @@ -399,7 +399,7 @@ func getNewImports( declaration = ct.NodeFactory.NewImportEqualsDeclaration( /*modifiers*/ nil, shouldUseTypeOnly(namespaceLikeImport.addAsTypeOnly, preferences), - ct.NodeFactory.NewIdentifier(namespaceLikeImport.name.Value()), + ct.NodeFactory.NewIdentifier(namespaceLikeImport.name.String()), ct.NodeFactory.NewExternalModuleReference(moduleSpecifierStringLiteral), ) } else { @@ -408,7 +408,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.Value())), + ct.NodeFactory.NewNamespaceImport(ct.NodeFactory.NewIdentifier(namespaceLikeImport.name.String())), ), moduleSpecifierStringLiteral, /*attributes*/ nil, @@ -448,7 +448,7 @@ func getNewRequires( bindingElements = append(bindingElements, changeTracker.NodeFactory.NewBindingElement( /*dotDotDotToken*/ nil, propertyName, - changeTracker.NodeFactory.NewIdentifier(namedImport.name.Value()), + changeTracker.NodeFactory.NewIdentifier(namedImport.name.String()), /*initializer*/ nil, )) } @@ -457,7 +457,7 @@ func getNewRequires( changeTracker.NodeFactory.NewBindingElement( /*dotDotDotToken*/ nil, changeTracker.NodeFactory.NewIdentifier("default"), - changeTracker.NodeFactory.NewIdentifier(defaultImport.name.Value()), + changeTracker.NodeFactory.NewIdentifier(defaultImport.name.String()), /*initializer*/ nil, ), }, bindingElements...) @@ -477,7 +477,7 @@ func getNewRequires( if namespaceLikeImport != nil { declaration := createConstEqualsRequireDeclaration( changeTracker, - changeTracker.NodeFactory.NewIdentifier(namespaceLikeImport.name.Value()), + changeTracker.NodeFactory.NewIdentifier(namespaceLikeImport.name.String()), quotedModuleSpecifier, ) statements = append(statements, declaration) @@ -591,7 +591,7 @@ func (v *View) GetFixes(export *Export, forJSX bool, isValidTypeOnlyUseSite bool AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindJsdocTypeImport, ModuleSpecifier: moduleSpecifier.AsString(), - Name: export.Name().Value(), + Name: export.Name().String(), UsagePosition: usagePosition, }, ModuleSpecifierKind: moduleSpecifierKind, @@ -605,7 +605,7 @@ func (v *View) GetFixes(export *Export, forJSX bool, isValidTypeOnlyUseSite bool addAsTypeOnly := getAddAsTypeOnly(isValidTypeOnlyUseSite, export, v.program.Options()) name := export.Name() - nameText := name.Value() + nameText := name.String() startsWithUpper := unicode.IsUpper(rune(nameText[0])) if forJSX && !startsWithUpper { if export.IsRenameable() { @@ -620,7 +620,7 @@ func (v *View) GetFixes(export *Export, forJSX bool, isValidTypeOnlyUseSite bool Kind: lsproto.AutoImportFixKindAddNew, ImportKind: importKind, ModuleSpecifier: moduleSpecifier.AsString(), - Name: name.Value(), + Name: name.String(), UseRequire: v.shouldUseRequire(), AddAsTypeOnly: addAsTypeOnly, }, @@ -663,7 +663,7 @@ func (v *View) tryUseExistingNamespaceImport(export *Export, usagePosition *lspr return &Fix{ AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindUseNamespace, - Name: export.Name().Value(), + Name: export.Name().String(), ModuleSpecifier: existingImport.moduleSpecifier, ImportKind: lsproto.ImportKindNamespace, AddAsTypeOnly: lsproto.AddAsTypeOnlyAllowed, @@ -733,7 +733,7 @@ func (v *View) tryAddToExistingImport( fix := &Fix{ AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindAddToExisting, - Name: export.Name().Value(), + Name: export.Name().String(), ImportKind: importKind, ImportIndex: int32(existingImport.index), ModuleSpecifier: existingImport.moduleSpecifier, @@ -784,7 +784,7 @@ func (v *View) tryAddToExistingImport( fix := &Fix{ AutoImportFix: &lsproto.AutoImportFix{ Kind: lsproto.AutoImportFixKindAddToExisting, - Name: export.Name().Value(), + Name: export.Name().String(), 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 dd5c481274b9b..95c731ec2dd1a 100644 --- a/tsc/internal/ls/autoimport/import_adder.go +++ b/tsc/internal/ls/autoimport/import_adder.go @@ -177,7 +177,7 @@ func (adder *importAdder) Edits() []*lsproto.TextEdit { } 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()) }) + keys := slices.SortedFunc(maps.Keys(m), func(a, b ast.SymbolName) int { return strings.Compare(a.String(), b.String()) }) result := make([]*newImportBinding, 0, len(keys)) for _, k := range keys { result = append(result, m[k]) @@ -471,12 +471,12 @@ func getNameForExportedSymbol(symbol *ast.Symbol, preferCapitalized bool) string // - export default 0 => filename converted to camelCase name := getDefaultLikeExportNameFromDeclaration(symbol) if name != ast.EmptySymbolName { - return name.Value() + return name.String() } debug.Assert(symbol.Parent() != nil, "Expected exported symbol to have module symbol as parent") return lsutil.ModuleSymbolToValidIdentifier(symbol.Parent(), preferCapitalized) } - return symbol.Name().Value() + return symbol.Name().String() } 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 3f21c54eb2910..188469d5ed0b6 100644 --- a/tsc/internal/ls/autoimport/index.go +++ b/tsc/internal/ls/autoimport/index.go @@ -26,7 +26,7 @@ func (idx *Index[T]) Find(name ast.SymbolName, caseSensitive bool) []T { if len(idx.entries) == 0 || name == ast.EmptySymbolName { return nil } - nameText := name.Value() + nameText := name.String() firstRune := core.FirstResult(utf8.DecodeRuneInString(nameText)) if firstRune == utf8.RuneError { return nil @@ -41,7 +41,7 @@ func (idx *Index[T]) Find(name ast.SymbolName, caseSensitive bool) []T { for _, entryIndex := range candidates { entry := idx.entries[entryIndex] entryName := entry.Name() - if (caseSensitive && entryName == name) || (!caseSensitive && strings.EqualFold(entryName.Value(), nameText)) { + if (caseSensitive && entryName == name) || (!caseSensitive && strings.EqualFold(entryName.String(), nameText)) { results = append(results, entry) } } @@ -87,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().Value(), prefix) { + if containsCharsInOrder(entry.Name().String(), prefix) { results = append(results, entry) } } @@ -118,7 +118,7 @@ func (idx *Index[T]) insertAsWords(value T) { idx.index = make(map[rune][]int) } - name := value.Name().Value() + name := value.Name().String() if len(name) == 0 { panic("Cannot index entry with empty name") } diff --git a/tsc/internal/ls/autoimport/view.go b/tsc/internal/ls/autoimport/view.go index 28898a3ada312..296a5c38b778f 100644 --- a/tsc/internal/ls/autoimport/view.go +++ b/tsc/internal/ls/autoimport/view.go @@ -192,10 +192,10 @@ func (v *View) GetCompletions(prefix string, position lsproto.Position, forJSX b outer: for _, e := range results { name := e.Name() - if !scanner.IsIdentifierText(name.Value(), core.LanguageVariantStandard) { + if !scanner.IsIdentifierText(name.String(), core.LanguageVariantStandard) { continue } - if forJSX && !(unicode.IsUpper(rune(name.Value()[0])) || e.IsRenameable()) { + if forJSX && !(unicode.IsUpper(rune(name.String()[0])) || e.IsRenameable()) { continue } target := e.ExportID diff --git a/tsc/internal/ls/codeactions_fixmissingtypeannotation.go b/tsc/internal/ls/codeactions_fixmissingtypeannotation.go index e7f185454adf6..f568f1c20de81 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().Value(), core.LanguageVariantStandard) { + if !scanner.IsIdentifierText(symbol.Name().String(), 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().Value()), nil, typeNode, nil) + varDecl := factory.NewVariableDeclaration(factory.NewIdentifier(symbol.Name().String()), 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) @@ -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.Value())) + newSpecifier := factory.NewImportSpecifier(false, nil, factory.NewIdentifier(symbolName.String())) 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 085b7dbd8f68b..e92289a6c0e90 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().Value(), + symbolName: umdSymbol.Name().String(), errorIdentifierText: errorIdentifierText, }) } diff --git a/tsc/internal/ls/codeactions_missingmemberfixer.go b/tsc/internal/ls/codeactions_missingmemberfixer.go index fc7e4b3b1c690..10f83e0082d98 100644 --- a/tsc/internal/ls/codeactions_missingmemberfixer.go +++ b/tsc/internal/ls/codeactions_missingmemberfixer.go @@ -332,7 +332,7 @@ func (f *missingMemberFixer) createSignatureDeclarationFromSignatures(signatures if hasRestParameter { restParameterName := "rest" if maxNonRestArgs < len(parameterNames) && parameterNames[maxNonRestArgs] != ast.EmptySymbolName { - restParameterName = parameterNames[maxNonRestArgs].Value() + restParameterName = parameterNames[maxNonRestArgs].String() } var questionToken *ast.QuestionToken @@ -464,7 +464,7 @@ func createDummyParameters(factory *ast.NodeFactory, argCount int, names []ast.S parameterNameCounts[parameterName] = count + 1 if count > 0 { - parameterName = ast.MakeSymbolName(parameterName.Value() + strconv.Itoa(count)) + parameterName = ast.MakeSymbolName(parameterName.String() + strconv.Itoa(count)) } var questionToken *ast.QuestionToken @@ -481,7 +481,7 @@ func createDummyParameters(factory *ast.NodeFactory, argCount int, names []ast.S typeNode = factory.NewKeywordTypeNode(ast.KindUnknownKeyword) } parameters = append(parameters, - factory.NewParameterDeclaration(nil /*modifiers*/, nil /*dotDotDotToken*/, factory.NewIdentifier(parameterName.Value()), questionToken, typeNode, nil /*initializer*/)) + factory.NewParameterDeclaration(nil /*modifiers*/, nil /*dotDotDotToken*/, factory.NewIdentifier(parameterName.String()), 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).Value()) + return factory.NewIdentifier(checker.GetPropertyNameFromType(nameType).String()) } } if declaration != nil && declaration.Name() != nil { return declaration.Name().Clone(factory) } if symbol != nil { - return factory.NewIdentifier(symbol.Name().Value()) + return factory.NewIdentifier(symbol.Name().String()) } return nil } diff --git a/tsc/internal/ls/findallreferences.go b/tsc/internal/ls/findallreferences.go index bd6129dd8d2d6..b1cf9eff5ac8d 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().Value())) + panic(fmt.Sprintf("Unexpected symbol at %s: %s", node.Kind.String(), symbol.Name().String())) } if decl.Parent.Kind == ast.KindTypeLiteral && decl.Parent.Parent.Kind == ast.KindUnionType { return checker.GetPropertyOfType(checker.GetTypeFromTypeNode(decl.Parent.Parent), symbol.Name()) diff --git a/tsc/internal/ls/inlay_hints.go b/tsc/internal/ls/inlay_hints.go index f8c15dd3b7992..bc50f8e2cc0ab 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().Value(), + name: restParameter.Name().String(), isRestParameter: true, } } diff --git a/tsc/internal/ls/lsutil/utilities.go b/tsc/internal/ls/lsutil/utilities.go index aca7b2a78fc43..448f8fd6c43e1 100644 --- a/tsc/internal/ls/lsutil/utilities.go +++ b/tsc/internal/ls/lsutil/utilities.go @@ -117,7 +117,7 @@ func ModuleSymbolToValidIdentifier(moduleSymbol *ast.Symbol, forceCapitalize boo if ambientModuleName, ok := ast.TryGetAmbientModuleNameFromSymbolName(moduleName); ok { moduleName = ast.MakeSymbolName(ambientModuleName) } - return ModuleSpecifierToValidIdentifier(moduleName.Value(), forceCapitalize) + return ModuleSpecifierToValidIdentifier(moduleName.String(), forceCapitalize) } func ModuleSpecifierToValidIdentifier(moduleSpecifier string, forceCapitalize bool) string { diff --git a/tsc/internal/ls/signaturehelp.go b/tsc/internal/ls/signaturehelp.go index c729df23cb500..d446eed13d611 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().Value(), ast.InternalSymbolNamePrefix) { + if callTargetSymbol != nil && !callTargetSymbol.Name().IsInternal() { if useFullPrefix { callTargetDisplayParts.WriteString(c.SymbolToStringEx(callTargetSymbol, sourceFile.AsNode(), ast.SymbolFlagsNone, checker.SymbolFormatFlagsUseAliasDefinedOutsideCurrentScope)) } else { diff --git a/tsc/internal/ls/string_completions.go b/tsc/internal/ls/string_completions.go index ee5da8c36c945..a6a2fc8fddb6a 100644 --- a/tsc/internal/ls/string_completions.go +++ b/tsc/internal/ls/string_completions.go @@ -930,7 +930,7 @@ func getAmbientModuleName(symbol *ast.Symbol) string { if declaration != nil && ast.IsModuleWithStringLiteralName(declaration) { return declaration.Name().Text() } - return stringutil.StripQuotes(symbol.Name().Value()) + return stringutil.StripQuotes(symbol.Name().String()) } func (l *LanguageService) getCompletionEntriesFromTypings( diff --git a/tsc/internal/printer/factory.go b/tsc/internal/printer/factory.go index 89595d165fad5..231806ed6a574 100644 --- a/tsc/internal/printer/factory.go +++ b/tsc/internal/printer/factory.go @@ -30,19 +30,21 @@ func NewNodeFactory(context *EmitContext) *NodeFactory { func (f *NodeFactory) newGeneratedIdentifier(kind GeneratedIdentifierFlags, text string, node *ast.Node, options AutoGenerateOptions) *ast.IdentifierNode { id := AutoGenerateId(nextAutoGenerateId.Add(1)) + var name *ast.IdentifierNode if len(text) == 0 { + prefix, suffix := removeLeadingHash(options.Prefix), removeLeadingHash(options.Suffix) switch { case node == nil: - text = fmt.Sprintf("(auto@%d)", id) + name = f.NewIdentifierFromSymbolName(ast.MakeGeneratedSymbolName(prefix, false /*forNode*/, uint64(id), suffix)) case ast.IsMemberName(node): - text = node.Text() + name = f.NewIdentifier(FormatGeneratedName(false /*privateName*/, options.Prefix, node.Text(), options.Suffix)) default: - text = fmt.Sprintf("(generated@%v)", ast.GetNodeId(f.emitContext.getNodeForGeneratedNameWorker(node, id))) + nodeId := ast.GetNodeId(f.emitContext.getNodeForGeneratedNameWorker(node, id)) + name = f.NewIdentifierFromSymbolName(ast.MakeGeneratedSymbolName(prefix, true /*forNode*/, uint64(nodeId), suffix)) } - text = FormatGeneratedName(false /*privateName*/, options.Prefix, text, options.Suffix) + } else { + name = f.NewIdentifier(text) } - - name := f.NewIdentifier(text) autoGenerate := &AutoGenerateInfo{ Id: id, Flags: kind | (options.Flags & ^GeneratedIdentifierFlagsKindMask), diff --git a/tsc/internal/printer/printer.go b/tsc/internal/printer/printer.go index 24c6ab0cf5a1f..0b69754073bf2 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.Value()) + helperName := p.getUniqueHelperName(node.Text.String()) 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.Value()) + helperName := p.getUniqueHelperName(node.Text.String()) p.emitContext.AssignCommentAndSourceMapRanges(helperName, node.AsNode()) node = helperName.AsIdentifier() } diff --git a/tsc/internal/scanner/utilities.go b/tsc/internal/scanner/utilities.go index 317d14f07be36..0da35e2d4597b 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.Value()] + return textToKeyword[node.Text.String()] } 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 244c68181de25..f90b28db87e95 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().Value()) + desc.SymbolName = ast.EscapeAllInternalSymbolNames(sym.Name().String()) } else if symbol != nil { - desc.SymbolName = ast.EscapeAllInternalSymbolNames(symbol.Name().Value()) + desc.SymbolName = ast.EscapeAllInternalSymbolNames(symbol.Name().String()) } // Tuple flag diff --git a/tsc/internal/transformers/declarations/transform.go b/tsc/internal/transformers/declarations/transform.go index fffd3df3b7d0e..bdc014fb81baf 100644 --- a/tsc/internal/transformers/declarations/transform.go +++ b/tsc/internal/transformers/declarations/transform.go @@ -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()).Value() + return tx.resolver.GetElementAccessExpressionName(node.AsElementAccessExpression()).String() } if ast.IsPropertyAccessExpression(node) { return node.Name().Text() From b7fbaac80c84d2a8e68cfc2003cc672f79f91a40 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 28 Oct 2026 12:41:29 -0700 Subject: [PATCH 10/14] Generate fixed symbol names from the TS AST generator The fixed name list lived in a standalone Go program run via go:generate, separate from the rest of our generated AST code. The Go generators that remain need to be Go for other reasons; this one did not, so move the list into tools/scripts/tsc/symbolNames.ts and emit symbolnames_generated.go from generate-go-ast.ts alongside the other AST outputs. --- Herebyfile.mjs | 9 +- tools/scripts/tsc/generate-go-ast.ts | 84 +++++- tools/scripts/tsc/symbolNames.ts | 212 +++++++++++++++ tsc/internal/ast/symbol.go | 4 +- tsc/internal/ast/symbolnames_generate.go | 300 ---------------------- tsc/internal/ast/symbolnames_generated.go | 2 +- 6 files changed, 297 insertions(+), 314 deletions(-) create mode 100644 tools/scripts/tsc/symbolNames.ts delete mode 100644 tsc/internal/ast/symbolnames_generate.go diff --git a/Herebyfile.mjs b/Herebyfile.mjs index 33f07b6b91e8a..030879256d700 100644 --- a/Herebyfile.mjs +++ b/Herebyfile.mjs @@ -473,13 +473,6 @@ export const generateBundled = goGenerateTask("generate:bundled", [{ commands: [["go", "run", "generate.go"]], }]); -export const generateSymbolNames = goGenerateTask("generate:symbolnames", [{ - file: "tsc/internal/ast/symbol.go", - inputs: ["symbolnames_generate.go"], - outputs: ["symbolnames_generated.go"], - commands: [["go", "run", "symbolnames_generate.go"]], -}]); - export const generateChecker = goGenerateTask("generate:checker", [ stringerGenerator("tsc/internal/checker/types.go", "SignatureKind", "stringer_generated.go"), ]); @@ -684,7 +677,7 @@ async function runGenerateAST() { export const generateAST = task({ name: "generate:ast", - description: "Generates AST, kind stringer, and encoder files from ast.json. Pass --force to regenerate unchanged files.", + description: "Generates AST, kind stringer, symbol name, and encoder files from ast.json and symbolNames.ts. Pass --force to regenerate unchanged files.", run: runGenerateAST, }); diff --git a/tools/scripts/tsc/generate-go-ast.ts b/tools/scripts/tsc/generate-go-ast.ts index 5e1cfa7f84cab..e472b31c0edf5 100644 --- a/tools/scripts/tsc/generate-go-ast.ts +++ b/tools/scripts/tsc/generate-go-ast.ts @@ -13,6 +13,8 @@ * - Polymorphic accessor switch statements (Expression(), Type(), etc.) * - Compact kind-indexed dispatch for shared node accessors * - Is*() type guard functions + * + * It also produces internal/ast/symbolnames_generated.go from symbolNames.ts. */ import * as path from "node:path"; @@ -32,6 +34,7 @@ import { api, kindGuardName, } from "./schema.ts"; +import { symbolNames } from "./symbolNames.ts"; // ──────────────────────────────────────────────────────────────────────────── // Load schema @@ -1502,8 +1505,82 @@ function generateKind(): string { return w.toString(); } -function writeAndFormat(filePath: string, generateContent: () => string, force: boolean) { - const generated = new GeneratedFile(filePath, [import.meta.filename, path.join(ROOT, "tools/scripts/tsc/schema.ts"), path.join(ROOT, "tools/scripts/tsc/ast.json")]); +function goStringLiteral(text: string): string { + if (!/^[\x20-\x7E]*$/.test(text)) { + throw new Error(`Fixed symbol name text must be printable ASCII: ${JSON.stringify(text)}`); + } + return `"${text.replace(/["\\]/g, "\\$&")}"`; +} + +function generateSymbolNames(): string { + const seenNames = new Set(); + const seenTexts = new Map([["", "EmptySymbolName"]]); + for (const { name, text, internal } of symbolNames) { + const fullText = internal ? "\xFE" + text : text; + if (seenNames.has(name)) { + throw new Error(`Duplicate fixed symbol name ${name}`); + } + const other = seenTexts.get(fullText); + if (other !== undefined) { + throw new Error(`${name} and ${other} have the same text ${JSON.stringify(fullText)}`); + } + seenNames.add(name); + seenTexts.set(fullText, name); + } + + const w = new CodeWriter(); + w.write("// Code generated by tools/scripts/tsc/generate-go-ast.ts. DO NOT EDIT."); + w.write(""); + w.write("package ast"); + w.write(""); + w.write("// Fixed symbol names take the first IDs in the intern table, so they are"); + w.write("// compile-time constants. Internal names carry the same tag that"); + w.write("// internedSymbolName gives them."); + w.write("const ("); + w.push(); + w.write("EmptySymbolName SymbolName = iota // The zero value."); + // A bare constant repeats the previous expression, so after an internal + // name the next plain name has to restate iota. + let repeatingIota = true; + for (const { name, text, internal, comment } of symbolNames) { + let line = name; + if (internal) { + // The marker is the byte after the prefix plus one, or zero if there is none. + const marker = text === "" ? "0" : `('${text[0] === "'" || text[0] === "\\" ? "\\" + text[0] : text[0]}' + 1)`; + line += ` SymbolName = iota | internalSymbolNameBits | ${marker}< string, force: boolean, inputs = [path.join(ROOT, "tools/scripts/tsc/schema.ts"), path.join(ROOT, "tools/scripts/tsc/ast.json")]) { + const generated = new GeneratedFile(filePath, [import.meta.filename, ...inputs]); if (generated.isCurrent(force)) return; generated.write(generateContent()); formatFilesSync([filePath]); @@ -1519,6 +1596,9 @@ export default function main(force = false) { const kindOutPath = path.join(ROOT, "tsc/internal/ast/kind_generated.go"); writeAndFormat(kindOutPath, () => generateKind() + "\n", force); + + const symbolNamesOutPath = path.join(ROOT, "tsc/internal/ast/symbolnames_generated.go"); + writeAndFormat(symbolNamesOutPath, () => generateSymbolNames() + "\n", force, [path.join(ROOT, "tools/scripts/tsc/symbolNames.ts")]); } if (process.argv[1] === fileURLToPath(import.meta.url)) { diff --git a/tools/scripts/tsc/symbolNames.ts b/tools/scripts/tsc/symbolNames.ts new file mode 100644 index 0000000000000..54d583cdfbd05 --- /dev/null +++ b/tools/scripts/tsc/symbolNames.ts @@ -0,0 +1,212 @@ +/** + * Fixed symbol names, emitted as constants in tsc/internal/ast/symbolnames_generated.go by + * generate-go-ast.ts. They take the first IDs in the intern table, in this order, after the + * empty name. Internal names get InternalSymbolNamePrefix prepended to their text. + */ +export interface FixedSymbolName { + name: string; + text: string; + internal?: boolean; + comment?: string; +} + +export const symbolNames: readonly FixedSymbolName[] = [ + { name: "SymbolNameZero", text: "0" }, + { name: "SymbolNameUnresolved", text: "<>" }, + { name: "SymbolNameAbstractModuleSource", text: "AbstractModuleSource" }, + { name: "SymbolNameArray", text: "Array" }, + { name: "SymbolNameArrayBuffer", text: "ArrayBuffer" }, + { name: "SymbolNameArrayConstructor", text: "ArrayConstructor" }, + { name: "SymbolNameArrayLike", text: "ArrayLike" }, + { name: "SymbolNameAsyncDisposable", text: "AsyncDisposable" }, + { name: "SymbolNameAsyncDisposableStack", text: "AsyncDisposableStack" }, + { name: "SymbolNameAsyncGenerator", text: "AsyncGenerator" }, + { name: "SymbolNameAsyncGeneratorFunction", text: "AsyncGeneratorFunction" }, + { name: "SymbolNameAsyncIterable", text: "AsyncIterable" }, + { name: "SymbolNameAsyncIterableIterator", text: "AsyncIterableIterator" }, + { name: "SymbolNameAsyncIterator", text: "AsyncIterator" }, + { name: "SymbolNameAsyncIteratorObject", text: "AsyncIteratorObject" }, + { name: "SymbolNameAtomics", text: "Atomics" }, + { name: "SymbolNameAwaited", text: "Awaited" }, + { name: "SymbolNameBigInt", text: "BigInt" }, + { name: "SymbolNameBigInt64Array", text: "BigInt64Array" }, + { name: "SymbolNameBigUint64Array", text: "BigUint64Array" }, + { name: "SymbolNameBoolean", text: "Boolean" }, + { name: "SymbolNameBuiltinIteratorReturn", text: "BuiltinIteratorReturn" }, + { name: "SymbolNameCallableFunction", text: "CallableFunction" }, + { name: "SymbolNameCapitalize", text: "Capitalize" }, + { name: "SymbolNameClassAccessorDecoratorContext", text: "ClassAccessorDecoratorContext" }, + { name: "SymbolNameClassAccessorDecoratorResult", text: "ClassAccessorDecoratorResult" }, + { name: "SymbolNameClassAccessorDecoratorTarget", text: "ClassAccessorDecoratorTarget" }, + { name: "SymbolNameClassDecoratorContext", text: "ClassDecoratorContext" }, + { name: "SymbolNameClassFieldDecoratorContext", text: "ClassFieldDecoratorContext" }, + { name: "SymbolNameClassGetterDecoratorContext", text: "ClassGetterDecoratorContext" }, + { name: "SymbolNameClassMethodDecoratorContext", text: "ClassMethodDecoratorContext" }, + { name: "SymbolNameClassSetterDecoratorContext", text: "ClassSetterDecoratorContext" }, + { name: "SymbolNameDataView", text: "DataView" }, + { name: "SymbolNameDate", text: "Date" }, + { name: "SymbolNameDateTimeFormat", text: "DateTimeFormat" }, + { name: "SymbolNameDisposable", text: "Disposable" }, + { name: "SymbolNameDisposableStack", text: "DisposableStack" }, + { name: "SymbolNameElement", text: "Element" }, + { name: "SymbolNameElementAttributesProperty", text: "ElementAttributesProperty" }, + { name: "SymbolNameElementChildrenAttribute", text: "ElementChildrenAttribute" }, + { name: "SymbolNameElementClass", text: "ElementClass" }, + { name: "SymbolNameElementType", text: "ElementType" }, + { name: "SymbolNameError", text: "Error" }, + { name: "SymbolNameErrorConstructor", text: "ErrorConstructor" }, + { name: "SymbolNameEventTarget", text: "EventTarget" }, + { name: "SymbolNameExtract", text: "Extract" }, + { name: "SymbolNameFloat16Array", text: "Float16Array" }, + { name: "SymbolNameFloat32Array", text: "Float32Array" }, + { name: "SymbolNameFloat64Array", text: "Float64Array" }, + { name: "SymbolNameFunction", text: "Function" }, + { name: "SymbolNameGenerator", text: "Generator" }, + { name: "SymbolNameIArguments", text: "IArguments" }, + { name: "SymbolNameImportAttributes", text: "ImportAttributes" }, + { name: "SymbolNameImportCallOptions", text: "ImportCallOptions" }, + { name: "SymbolNameImportMeta", text: "ImportMeta" }, + { name: "SymbolNameImportMetaExpression", text: "ImportMetaExpression" }, + { name: "SymbolNameInt16Array", text: "Int16Array" }, + { name: "SymbolNameInt32Array", text: "Int32Array" }, + { name: "SymbolNameInt8Array", text: "Int8Array" }, + { name: "SymbolNameIntl", text: "Intl" }, + { name: "SymbolNameIntrinsicAttributes", text: "IntrinsicAttributes" }, + { name: "SymbolNameIntrinsicClassAttributes", text: "IntrinsicClassAttributes" }, + { name: "SymbolNameIntrinsicElements", text: "IntrinsicElements" }, + { name: "SymbolNameIterable", text: "Iterable" }, + { name: "SymbolNameIterableIterator", text: "IterableIterator" }, + { name: "SymbolNameIterator", text: "Iterator" }, + { name: "SymbolNameIteratorConstructor", text: "IteratorConstructor" }, + { name: "SymbolNameIteratorObject", text: "IteratorObject" }, + { name: "SymbolNameIteratorReturnResult", text: "IteratorReturnResult" }, + { name: "SymbolNameIteratorYieldResult", text: "IteratorYieldResult" }, + { name: "SymbolNameJSON", text: "JSON" }, + { name: "SymbolNameJSX", text: "JSX" }, + { name: "SymbolNameK", text: "K" }, + { name: "SymbolNameLibraryManagedAttributes", text: "LibraryManagedAttributes" }, + { name: "SymbolNameLowercase", text: "Lowercase" }, + { name: "SymbolNameMap", text: "Map" }, + { name: "SymbolNameMapConstructor", text: "MapConstructor" }, + { name: "SymbolNameMath", text: "Math" }, + { name: "SymbolNameNaN", text: "NaN" }, + { name: "SymbolNameNewableFunction", text: "NewableFunction" }, + { name: "SymbolNameNoInfer", text: "NoInfer" }, + { name: "SymbolNameNode", text: "Node" }, + { name: "SymbolNameNodeList", text: "NodeList" }, + { name: "SymbolNameNonNullable", text: "NonNullable" }, + { name: "SymbolNameNumber", text: "Number" }, + { name: "SymbolNameNumberConstructor", text: "NumberConstructor" }, + { name: "SymbolNameNumberFormat", text: "NumberFormat" }, + { name: "SymbolNameObject", text: "Object" }, + { name: "SymbolNameObjectConstructor", text: "ObjectConstructor" }, + { name: "SymbolNameOmit", text: "Omit" }, + { name: "SymbolNamePartial", text: "Partial" }, + { name: "SymbolNamePick", text: "Pick" }, + { name: "SymbolNamePromise", text: "Promise" }, + { name: "SymbolNamePromiseConstructor", text: "PromiseConstructor" }, + { name: "SymbolNamePromiseLike", text: "PromiseLike" }, + { name: "SymbolNameRawJSON", text: "RawJSON" }, + { name: "SymbolNameReadonly", text: "Readonly" }, + { name: "SymbolNameReadonlyArray", text: "ReadonlyArray" }, + { name: "SymbolNameReadonlyMap", text: "ReadonlyMap" }, + { name: "SymbolNameReadonlySet", text: "ReadonlySet" }, + { name: "SymbolNameRecord", text: "Record" }, + { name: "SymbolNameReflect", text: "Reflect" }, + { name: "SymbolNameRegExp", text: "RegExp" }, + { name: "SymbolNameRegExpConstructor", text: "RegExpConstructor" }, + { name: "SymbolNameRegExpExecArray", text: "RegExpExecArray" }, + { name: "SymbolNameRegExpMatchArray", text: "RegExpMatchArray" }, + { name: "SymbolNameRelativeTimeFormat", text: "RelativeTimeFormat" }, + { name: "SymbolNameRequired", text: "Required" }, + { name: "SymbolNameSet", text: "Set" }, + { name: "SymbolNameSharedArrayBuffer", text: "SharedArrayBuffer" }, + { name: "SymbolNameString", text: "String" }, + { name: "SymbolNameStringConstructor", text: "StringConstructor" }, + { name: "SymbolNameSymbol", text: "Symbol" }, + { name: "SymbolNameSymbolConstructor", text: "SymbolConstructor" }, + { name: "SymbolNameT", text: "T" }, + { name: "SymbolNameTemplateStringsArray", text: "TemplateStringsArray" }, + { name: "SymbolNameThisType", text: "ThisType" }, + { name: "SymbolNameTypedPropertyDescriptor", text: "TypedPropertyDescriptor" }, + { name: "SymbolNameUint16Array", text: "Uint16Array" }, + { name: "SymbolNameUint32Array", text: "Uint32Array" }, + { name: "SymbolNameUint8Array", text: "Uint8Array" }, + { name: "SymbolNameUint8ArrayConstructor", text: "Uint8ArrayConstructor" }, + { name: "SymbolNameUint8ClampedArray", text: "Uint8ClampedArray" }, + { name: "SymbolNameUncapitalize", text: "Uncapitalize" }, + { name: "SymbolNameUppercase", text: "Uppercase" }, + { name: "SymbolNameWeakMap", text: "WeakMap" }, + { name: "SymbolNameWeakSet", text: "WeakSet" }, + { name: "SymbolNameESModule", text: "__esModule" }, + { name: "SymbolNameUnderscoreDefault", text: "_default" }, + { name: "SymbolNameAny", text: "any" }, + { name: "SymbolNameArg", text: "arg" }, + { name: "SymbolNameArgs", text: "args" }, + { name: "SymbolNameArguments", text: "arguments" }, + { name: "SymbolNameAsyncIteratorProperty", text: "asyncIterator" }, + { name: "SymbolNameBind", text: "bind" }, + { name: "SymbolNameBooleanKeyword", text: "boolean" }, + { name: "SymbolNameCaller", text: "caller" }, + { name: "SymbolNameChildren", text: "children" }, + { name: "SymbolNameClass", text: "class" }, + { name: "SymbolNameClassName", text: "className" }, + { name: "SymbolNameConst", text: "const" }, + { name: "SymbolNameContext", text: "context" }, + { name: "SymbolNameDescriptor", text: "descriptor" }, + { name: "SymbolNameDone", text: "done" }, + { name: "SymbolNameExports", text: "exports" }, + { name: "SymbolNameFor", text: "for" }, + { name: "SymbolNameGetProperty", text: "get" }, + { name: "SymbolNameGlobal", text: "global" }, + { name: "SymbolNameGlobalThis", text: "globalThis" }, + { name: "SymbolNameHasInstance", text: "hasInstance" }, + { name: "SymbolNameHtmlFor", text: "htmlFor" }, + { name: "SymbolNameIteratorProperty", text: "iterator" }, + { name: "SymbolNameLength", text: "length" }, + { name: "SymbolNameMeta", text: "meta" }, + { name: "SymbolNameModule", text: "module" }, + { name: "SymbolNameName", text: "name" }, + { name: "SymbolNameNever", text: "never" }, + { name: "SymbolNameNext", text: "next" }, + { name: "SymbolNameNumberKeyword", text: "number" }, + { name: "SymbolNameParameterIndex", text: "parameterIndex" }, + { name: "SymbolNamePrivate", text: "private" }, + { name: "SymbolNamePropertyKey", text: "propertyKey" }, + { name: "SymbolNameProps", text: "props" }, + { name: "SymbolNamePrototype", text: "prototype" }, + { name: "SymbolNameRequire", text: "require" }, + { name: "SymbolNameReturn", text: "return" }, + { name: "SymbolNameSelf", text: "self" }, + { name: "SymbolNameSetProperty", text: "set" }, + { name: "SymbolNameStatic", text: "static" }, + { name: "SymbolNameStringKeyword", text: "string" }, + { name: "SymbolNameTarget", text: "target" }, + { name: "SymbolNameThen", text: "then" }, + { name: "SymbolNameThrow", text: "throw" }, + { name: "SymbolNameUndefined", text: "undefined" }, + { name: "SymbolNameUnknown", text: "unknown" }, + { name: "SymbolNameValue", text: "value" }, + { name: "SymbolNameWith", text: "with" }, + { name: "SymbolNameWritable", text: "writable" }, + { name: "InternalSymbolNameCall", text: "call", internal: true, comment: "Call signatures" }, + { name: "InternalSymbolNameConstructor", text: "constructor", internal: true, comment: "Constructor implementations" }, + { name: "InternalSymbolNameNew", text: "new", internal: true, comment: "Constructor signatures" }, + { name: "InternalSymbolNameIndex", text: "index", internal: true, comment: "Index signatures" }, + { name: "InternalSymbolNameExportStar", text: "export", internal: true, comment: "Module export * declarations" }, + { name: "InternalSymbolNameGlobal", text: "global", internal: true, comment: "Global self-reference" }, + { name: "InternalSymbolNameMissing", text: "missing", internal: true, comment: "Indicates missing symbol" }, + { name: "InternalSymbolNameType", text: "type", internal: true, comment: "Anonymous type literal symbol" }, + { name: "InternalSymbolNameObject", text: "object", internal: true, comment: "Anonymous object literal declaration" }, + { name: "InternalSymbolNameJSXAttributes", text: "jsxAttributes", internal: true, comment: "Anonymous JSX attributes object literal declaration" }, + { name: "InternalSymbolNameClass", text: "class", internal: true, comment: "Unnamed class expression" }, + { name: "InternalSymbolNameFunction", text: "function", internal: true, comment: "Unnamed function expression" }, + { name: "InternalSymbolNameComputed", text: "computed", internal: true, comment: "Computed property name declaration with dynamic name" }, + { name: "InternalSymbolNameAssignmentDeclaration", text: "assignment", internal: true, comment: "Assignment declarations" }, + { name: "InternalSymbolNameInstantiationExpression", text: "instantiationExpression", internal: true, comment: "Instantiation expressions" }, + { name: "InternalSymbolNameImportAttributes", text: "importAttributes", internal: true }, + { name: "InternalSymbolNameExportEquals", text: "export=", comment: "Export assignment symbol" }, + { name: "InternalSymbolNameDefault", text: "default", comment: "Default export symbol (technically not wholly internal, but included here for usability)" }, + { name: "InternalSymbolNameThis", text: "this" }, + { name: "InternalSymbolNameModuleExports", text: "module.exports" }, +]; diff --git a/tsc/internal/ast/symbol.go b/tsc/internal/ast/symbol.go index 1c777464b1d81..d9310307f8ee6 100644 --- a/tsc/internal/ast/symbol.go +++ b/tsc/internal/ast/symbol.go @@ -176,9 +176,7 @@ func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags { // and tag internal names. See symbolname_derived.go. // // Fixed names, such as SymbolNamePrototype, are constants generated from the -// list in symbolnames_generate.go. -// -//go:generate npx hereby generate:symbolnames +// list in tools/scripts/tsc/symbolNames.ts by `npx hereby generate:ast`. type SymbolName uint64 func MakeSymbolName(text string) SymbolName { diff --git a/tsc/internal/ast/symbolnames_generate.go b/tsc/internal/ast/symbolnames_generate.go deleted file mode 100644 index 7ef74d6848656..0000000000000 --- a/tsc/internal/ast/symbolnames_generate.go +++ /dev/null @@ -1,300 +0,0 @@ -//go:build ignore - -// This program generates symbolnames_generated.go, which declares the fixed -// symbol names as constants and seeds the intern table with their texts. -// Add new fixed names to the list below and run `npx hereby generate:symbolnames`. - -package main - -import ( - "bytes" - "fmt" - "go/format" - "log" - "os" - "strconv" - "strings" - "unicode/utf8" -) - -const internal = "\xFE" // InternalSymbolNamePrefix - -var names = []struct{ name, text, comment string }{ - {"SymbolNameZero", "0", ""}, - {"SymbolNameUnresolved", "<>", ""}, - {"SymbolNameAbstractModuleSource", "AbstractModuleSource", ""}, - {"SymbolNameArray", "Array", ""}, - {"SymbolNameArrayBuffer", "ArrayBuffer", ""}, - {"SymbolNameArrayConstructor", "ArrayConstructor", ""}, - {"SymbolNameArrayLike", "ArrayLike", ""}, - {"SymbolNameAsyncDisposable", "AsyncDisposable", ""}, - {"SymbolNameAsyncDisposableStack", "AsyncDisposableStack", ""}, - {"SymbolNameAsyncGenerator", "AsyncGenerator", ""}, - {"SymbolNameAsyncGeneratorFunction", "AsyncGeneratorFunction", ""}, - {"SymbolNameAsyncIterable", "AsyncIterable", ""}, - {"SymbolNameAsyncIterableIterator", "AsyncIterableIterator", ""}, - {"SymbolNameAsyncIterator", "AsyncIterator", ""}, - {"SymbolNameAsyncIteratorObject", "AsyncIteratorObject", ""}, - {"SymbolNameAtomics", "Atomics", ""}, - {"SymbolNameAwaited", "Awaited", ""}, - {"SymbolNameBigInt", "BigInt", ""}, - {"SymbolNameBigInt64Array", "BigInt64Array", ""}, - {"SymbolNameBigUint64Array", "BigUint64Array", ""}, - {"SymbolNameBoolean", "Boolean", ""}, - {"SymbolNameBuiltinIteratorReturn", "BuiltinIteratorReturn", ""}, - {"SymbolNameCallableFunction", "CallableFunction", ""}, - {"SymbolNameCapitalize", "Capitalize", ""}, - {"SymbolNameClassAccessorDecoratorContext", "ClassAccessorDecoratorContext", ""}, - {"SymbolNameClassAccessorDecoratorResult", "ClassAccessorDecoratorResult", ""}, - {"SymbolNameClassAccessorDecoratorTarget", "ClassAccessorDecoratorTarget", ""}, - {"SymbolNameClassDecoratorContext", "ClassDecoratorContext", ""}, - {"SymbolNameClassFieldDecoratorContext", "ClassFieldDecoratorContext", ""}, - {"SymbolNameClassGetterDecoratorContext", "ClassGetterDecoratorContext", ""}, - {"SymbolNameClassMethodDecoratorContext", "ClassMethodDecoratorContext", ""}, - {"SymbolNameClassSetterDecoratorContext", "ClassSetterDecoratorContext", ""}, - {"SymbolNameDataView", "DataView", ""}, - {"SymbolNameDate", "Date", ""}, - {"SymbolNameDateTimeFormat", "DateTimeFormat", ""}, - {"SymbolNameDisposable", "Disposable", ""}, - {"SymbolNameDisposableStack", "DisposableStack", ""}, - {"SymbolNameElement", "Element", ""}, - {"SymbolNameElementAttributesProperty", "ElementAttributesProperty", ""}, - {"SymbolNameElementChildrenAttribute", "ElementChildrenAttribute", ""}, - {"SymbolNameElementClass", "ElementClass", ""}, - {"SymbolNameElementType", "ElementType", ""}, - {"SymbolNameError", "Error", ""}, - {"SymbolNameErrorConstructor", "ErrorConstructor", ""}, - {"SymbolNameEventTarget", "EventTarget", ""}, - {"SymbolNameExtract", "Extract", ""}, - {"SymbolNameFloat16Array", "Float16Array", ""}, - {"SymbolNameFloat32Array", "Float32Array", ""}, - {"SymbolNameFloat64Array", "Float64Array", ""}, - {"SymbolNameFunction", "Function", ""}, - {"SymbolNameGenerator", "Generator", ""}, - {"SymbolNameIArguments", "IArguments", ""}, - {"SymbolNameImportAttributes", "ImportAttributes", ""}, - {"SymbolNameImportCallOptions", "ImportCallOptions", ""}, - {"SymbolNameImportMeta", "ImportMeta", ""}, - {"SymbolNameImportMetaExpression", "ImportMetaExpression", ""}, - {"SymbolNameInt16Array", "Int16Array", ""}, - {"SymbolNameInt32Array", "Int32Array", ""}, - {"SymbolNameInt8Array", "Int8Array", ""}, - {"SymbolNameIntl", "Intl", ""}, - {"SymbolNameIntrinsicAttributes", "IntrinsicAttributes", ""}, - {"SymbolNameIntrinsicClassAttributes", "IntrinsicClassAttributes", ""}, - {"SymbolNameIntrinsicElements", "IntrinsicElements", ""}, - {"SymbolNameIterable", "Iterable", ""}, - {"SymbolNameIterableIterator", "IterableIterator", ""}, - {"SymbolNameIterator", "Iterator", ""}, - {"SymbolNameIteratorConstructor", "IteratorConstructor", ""}, - {"SymbolNameIteratorObject", "IteratorObject", ""}, - {"SymbolNameIteratorReturnResult", "IteratorReturnResult", ""}, - {"SymbolNameIteratorYieldResult", "IteratorYieldResult", ""}, - {"SymbolNameJSON", "JSON", ""}, - {"SymbolNameJSX", "JSX", ""}, - {"SymbolNameK", "K", ""}, - {"SymbolNameLibraryManagedAttributes", "LibraryManagedAttributes", ""}, - {"SymbolNameLowercase", "Lowercase", ""}, - {"SymbolNameMap", "Map", ""}, - {"SymbolNameMapConstructor", "MapConstructor", ""}, - {"SymbolNameMath", "Math", ""}, - {"SymbolNameNaN", "NaN", ""}, - {"SymbolNameNewableFunction", "NewableFunction", ""}, - {"SymbolNameNoInfer", "NoInfer", ""}, - {"SymbolNameNode", "Node", ""}, - {"SymbolNameNodeList", "NodeList", ""}, - {"SymbolNameNonNullable", "NonNullable", ""}, - {"SymbolNameNumber", "Number", ""}, - {"SymbolNameNumberConstructor", "NumberConstructor", ""}, - {"SymbolNameNumberFormat", "NumberFormat", ""}, - {"SymbolNameObject", "Object", ""}, - {"SymbolNameObjectConstructor", "ObjectConstructor", ""}, - {"SymbolNameOmit", "Omit", ""}, - {"SymbolNamePartial", "Partial", ""}, - {"SymbolNamePick", "Pick", ""}, - {"SymbolNamePromise", "Promise", ""}, - {"SymbolNamePromiseConstructor", "PromiseConstructor", ""}, - {"SymbolNamePromiseLike", "PromiseLike", ""}, - {"SymbolNameRawJSON", "RawJSON", ""}, - {"SymbolNameReadonly", "Readonly", ""}, - {"SymbolNameReadonlyArray", "ReadonlyArray", ""}, - {"SymbolNameReadonlyMap", "ReadonlyMap", ""}, - {"SymbolNameReadonlySet", "ReadonlySet", ""}, - {"SymbolNameRecord", "Record", ""}, - {"SymbolNameReflect", "Reflect", ""}, - {"SymbolNameRegExp", "RegExp", ""}, - {"SymbolNameRegExpConstructor", "RegExpConstructor", ""}, - {"SymbolNameRegExpExecArray", "RegExpExecArray", ""}, - {"SymbolNameRegExpMatchArray", "RegExpMatchArray", ""}, - {"SymbolNameRelativeTimeFormat", "RelativeTimeFormat", ""}, - {"SymbolNameRequired", "Required", ""}, - {"SymbolNameSet", "Set", ""}, - {"SymbolNameSharedArrayBuffer", "SharedArrayBuffer", ""}, - {"SymbolNameString", "String", ""}, - {"SymbolNameStringConstructor", "StringConstructor", ""}, - {"SymbolNameSymbol", "Symbol", ""}, - {"SymbolNameSymbolConstructor", "SymbolConstructor", ""}, - {"SymbolNameT", "T", ""}, - {"SymbolNameTemplateStringsArray", "TemplateStringsArray", ""}, - {"SymbolNameThisType", "ThisType", ""}, - {"SymbolNameTypedPropertyDescriptor", "TypedPropertyDescriptor", ""}, - {"SymbolNameUint16Array", "Uint16Array", ""}, - {"SymbolNameUint32Array", "Uint32Array", ""}, - {"SymbolNameUint8Array", "Uint8Array", ""}, - {"SymbolNameUint8ArrayConstructor", "Uint8ArrayConstructor", ""}, - {"SymbolNameUint8ClampedArray", "Uint8ClampedArray", ""}, - {"SymbolNameUncapitalize", "Uncapitalize", ""}, - {"SymbolNameUppercase", "Uppercase", ""}, - {"SymbolNameWeakMap", "WeakMap", ""}, - {"SymbolNameWeakSet", "WeakSet", ""}, - {"SymbolNameESModule", "__esModule", ""}, - {"SymbolNameUnderscoreDefault", "_default", ""}, - {"SymbolNameAny", "any", ""}, - {"SymbolNameArg", "arg", ""}, - {"SymbolNameArgs", "args", ""}, - {"SymbolNameArguments", "arguments", ""}, - {"SymbolNameAsyncIteratorProperty", "asyncIterator", ""}, - {"SymbolNameBind", "bind", ""}, - {"SymbolNameBooleanKeyword", "boolean", ""}, - {"SymbolNameCaller", "caller", ""}, - {"SymbolNameChildren", "children", ""}, - {"SymbolNameClass", "class", ""}, - {"SymbolNameClassName", "className", ""}, - {"SymbolNameConst", "const", ""}, - {"SymbolNameContext", "context", ""}, - {"SymbolNameDescriptor", "descriptor", ""}, - {"SymbolNameDone", "done", ""}, - {"SymbolNameExports", "exports", ""}, - {"SymbolNameFor", "for", ""}, - {"SymbolNameGetProperty", "get", ""}, - {"SymbolNameGlobal", "global", ""}, - {"SymbolNameGlobalThis", "globalThis", ""}, - {"SymbolNameHasInstance", "hasInstance", ""}, - {"SymbolNameHtmlFor", "htmlFor", ""}, - {"SymbolNameIteratorProperty", "iterator", ""}, - {"SymbolNameLength", "length", ""}, - {"SymbolNameMeta", "meta", ""}, - {"SymbolNameModule", "module", ""}, - {"SymbolNameName", "name", ""}, - {"SymbolNameNever", "never", ""}, - {"SymbolNameNext", "next", ""}, - {"SymbolNameNumberKeyword", "number", ""}, - {"SymbolNameParameterIndex", "parameterIndex", ""}, - {"SymbolNamePrivate", "private", ""}, - {"SymbolNamePropertyKey", "propertyKey", ""}, - {"SymbolNameProps", "props", ""}, - {"SymbolNamePrototype", "prototype", ""}, - {"SymbolNameRequire", "require", ""}, - {"SymbolNameReturn", "return", ""}, - {"SymbolNameSelf", "self", ""}, - {"SymbolNameSetProperty", "set", ""}, - {"SymbolNameStatic", "static", ""}, - {"SymbolNameStringKeyword", "string", ""}, - {"SymbolNameTarget", "target", ""}, - {"SymbolNameThen", "then", ""}, - {"SymbolNameThrow", "throw", ""}, - {"SymbolNameUndefined", "undefined", ""}, - {"SymbolNameUnknown", "unknown", ""}, - {"SymbolNameValue", "value", ""}, - {"SymbolNameWith", "with", ""}, - {"SymbolNameWritable", "writable", ""}, - {"InternalSymbolNameCall", internal + "call", "Call signatures"}, - {"InternalSymbolNameConstructor", internal + "constructor", "Constructor implementations"}, - {"InternalSymbolNameNew", internal + "new", "Constructor signatures"}, - {"InternalSymbolNameIndex", internal + "index", "Index signatures"}, - {"InternalSymbolNameExportStar", internal + "export", "Module export * declarations"}, - {"InternalSymbolNameGlobal", internal + "global", "Global self-reference"}, - {"InternalSymbolNameMissing", internal + "missing", "Indicates missing symbol"}, - {"InternalSymbolNameType", internal + "type", "Anonymous type literal symbol"}, - {"InternalSymbolNameObject", internal + "object", "Anonymous object literal declaration"}, - {"InternalSymbolNameJSXAttributes", internal + "jsxAttributes", "Anonymous JSX attributes object literal declaration"}, - {"InternalSymbolNameClass", internal + "class", "Unnamed class expression"}, - {"InternalSymbolNameFunction", internal + "function", "Unnamed function expression"}, - {"InternalSymbolNameComputed", internal + "computed", "Computed property name declaration with dynamic name"}, - {"InternalSymbolNameAssignmentDeclaration", internal + "assignment", "Assignment declarations"}, - {"InternalSymbolNameInstantiationExpression", internal + "instantiationExpression", "Instantiation expressions"}, - {"InternalSymbolNameImportAttributes", internal + "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", ""}, -} - -func main() { - log.SetFlags(log.LstdFlags | log.Lshortfile) - - seenNames := map[string]bool{} - seenTexts := map[string]string{"": "EmptySymbolName"} - for _, n := range names { - if seenNames[n.name] { - log.Fatalf("duplicate fixed symbol name %s", n.name) - } - if other, ok := seenTexts[n.text]; ok { - log.Fatalf("%s and %s have the same text %q", n.name, other, n.text) - } - seenNames[n.name] = true - seenTexts[n.text] = n.name - } - - var code bytes.Buffer - code.WriteString("// Code generated by symbolnames_generate.go; DO NOT EDIT.\n\n") - code.WriteString("package ast\n\n") - code.WriteString("// Fixed symbol names take the first IDs in the intern table, so they are\n") - code.WriteString("// compile-time constants. Internal names carry the same tag that\n") - code.WriteString("// internedSymbolName gives them.\n") - code.WriteString("const (\n") - code.WriteString("\tEmptySymbolName SymbolName = iota // The zero value.\n") - repeatingIota := true - for _, n := range names { - code.WriteString("\t" + n.name) - if rest, ok := strings.CutPrefix(n.text, internal); ok { - marker := "0" - if rest != "" { - marker = "(" + strconv.QuoteRuneToASCII(rune(rest[0])) + " + 1)" - if rest[0] >= utf8.RuneSelf { - marker = fmt.Sprintf("0x%x", int(rest[0])+1) - } - } - code.WriteString(" SymbolName = iota | internalSymbolNameBits | " + marker + "< Date: Wed, 28 Oct 2026 14:39:54 -0700 Subject: [PATCH 11/14] Separate interner lookup and insert state onto different cache lines Lookups only read the slot tables and chunk pointers, while inserts write the shard locks, counts, and next ID. The shard stride wasn't a multiple of 64 and Go only guarantees 8-byte alignment, so neighbouring shards shared lines, and nextID shared a line with the first chunk pointers. Inserts on one core kept evicting lines that lookups on every other core needed. Group the read-mostly fields together, ahead of padded shards. --- tsc/internal/ast/symbolname_intern.go | 40 +++++++++++++++------------ 1 file changed, 23 insertions(+), 17 deletions(-) diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go index 1704606f938fb..a245727c57a08 100644 --- a/tsc/internal/ast/symbolname_intern.go +++ b/tsc/internal/ast/symbolname_intern.go @@ -28,26 +28,31 @@ const ( type symbolNameChunk [symbolNameChunkSize]string +// Lookups only read tables and chunks; inserts write the shard locks, counts, +// and nextID. Keeping the two groups on separate cache lines stops inserts on +// one core from evicting lines that lookups on every other core need. The +// table is one large allocation, so it starts on a page boundary. +type symbolNameTable struct { + tables [symbolNameShardCount]atomic.Pointer[[]atomic.Uint64] + chunks [symbolNameMaxChunks]atomic.Pointer[symbolNameChunk] + nextID atomic.Uint32 + _ [60]byte + shards [symbolNameShardCount]symbolNameShard +} + 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] + _ [48]byte } var symbolNames = newSymbolNameTable() func newSymbolNameTable() *symbolNameTable { t := &symbolNameTable{} - for i := range t.shards { + for i := range t.tables { slots := make([]atomic.Uint64, symbolNameInitialSlots) - t.shards[i].table.Store(&slots) + t.tables[i].Store(&slots) } for want := SymbolName(1); want < SymbolName(len(fixedSymbolNameTexts)); want++ { text := fixedSymbolNameTexts[want] @@ -58,7 +63,7 @@ func newSymbolNameTable() *symbolNameTable { panic("fixed symbol name has a derived form: " + text) } hash := hashSymbolNameText(text) - if id := t.insert(&t.shards[hash&(symbolNameShardCount-1)], hash, text); SymbolName(id) != want { + if id := t.insert(hash, text); SymbolName(id) != want { panic("duplicate fixed symbol name: " + text) } } @@ -92,20 +97,21 @@ func (t *symbolNameTable) make(text string, hash uint64) SymbolName { if text == "" { return EmptySymbolName } - shard := &t.shards[hash&(symbolNameShardCount-1)] - if id := t.lookup(*shard.table.Load(), hash, text); id != 0 { + if id := t.lookup(*t.tables[hash&(symbolNameShardCount-1)].Load(), hash, text); id != 0 { return internedSymbolName(id, text) } if name, ok := parseDerivedName(text); ok { return name } - return internedSymbolName(t.insert(shard, hash, text), text) + return internedSymbolName(t.insert(hash, text), text) } -func (t *symbolNameTable) insert(shard *symbolNameShard, hash uint64, text string) uint32 { +func (t *symbolNameTable) insert(hash uint64, text string) uint32 { + table := &t.tables[hash&(symbolNameShardCount-1)] + shard := &t.shards[hash&(symbolNameShardCount-1)] shard.mu.Lock() defer shard.mu.Unlock() - slots := *shard.table.Load() + slots := *table.Load() if id := t.lookup(slots, hash, text); id != 0 { return id } @@ -116,7 +122,7 @@ func (t *symbolNameTable) insert(shard *symbolNameShard, hash uint64, text strin storeSymbolNameSlot(grown, t.hashOf(uint32(v)), v) } } - shard.table.Store(&grown) + table.Store(&grown) slots = grown } id := t.allocate(string([]byte(text))) From 758e34cbcead2da23341eeae8cec0082e484ab35 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:40:07 -0700 Subject: [PATCH 12/14] Store interned symbol name text in a pointer-free arena Each interned name held a heap string in a chunk of string headers, so a cache hit loaded the chunk header and then the string data, and every new name was a small GC-visible allocation. Store names as length- prefixed records in pointer-free chunks instead and use the record's offset as its ID; text is then one dependent load and the GC never scans it. Each shard bump-allocates from its own chunk, claimed with an atomic counter, so inserts on different shards don't contend. Records too large for a shared chunk get a dedicated run of chunks. Fixed names are inserted first, so their IDs are offsets the AST generator can compute; initialization panics if they disagree. The InternalSymbolName enum now reads its members from the same list. --- .../typescript/enums/internalSymbolName.d.ts | 2 +- .../typescript/enums/internalSymbolName.js | 2 +- tools/scripts/tsc/generate-enums.ts | 48 +- tools/scripts/tsc/generate-go-ast.ts | 49 +- tsc/internal/ast/symbol_test.go | 21 + tsc/internal/ast/symbolname_intern.go | 139 ++- tsc/internal/ast/symbolnames_generated.go | 805 +++++++++--------- 7 files changed, 577 insertions(+), 489 deletions(-) diff --git a/packages/typescript/enums/internalSymbolName.d.ts b/packages/typescript/enums/internalSymbolName.d.ts index 65ce23420d560..4a7339e394b59 100644 --- a/packages/typescript/enums/internalSymbolName.d.ts +++ b/packages/typescript/enums/internalSymbolName.d.ts @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/symbolnames_generated.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/symbolNames.ts. DO NOT EDIT. export declare enum InternalSymbolName { Call = "__call", diff --git a/packages/typescript/enums/internalSymbolName.js b/packages/typescript/enums/internalSymbolName.js index 2ebe82d9d47f9..f2075c1cfcbf1 100644 --- a/packages/typescript/enums/internalSymbolName.js +++ b/packages/typescript/enums/internalSymbolName.js @@ -1,4 +1,4 @@ -// Code generated by tools/scripts/tsc/generate-enums.ts from tsc/internal/ast/symbolnames_generated.go. DO NOT EDIT. +// Code generated by tools/scripts/tsc/generate-enums.ts from tools/scripts/tsc/symbolNames.ts. DO NOT EDIT. export var InternalSymbolName; (function (InternalSymbolName) { InternalSymbolName["Call"] = "__call"; diff --git a/tools/scripts/tsc/generate-enums.ts b/tools/scripts/tsc/generate-enums.ts index bed4b249aa95d..523b8c3e1e939 100644 --- a/tools/scripts/tsc/generate-enums.ts +++ b/tools/scripts/tsc/generate-enums.ts @@ -13,6 +13,7 @@ import { import generateOptions from "./generate-options.ts"; import { options } from "./options.ts"; import { api } from "./schema.ts"; +import { symbolNames } from "./symbolNames.ts"; function runOutput(command: string, args: readonly string[]) { return run(command, args, { captureOutput: true, cwd: ROOT }); @@ -75,8 +76,21 @@ export const enumDefs = [ { name: "CompletionItemKind", goPrefix: "CompletionItemKind", goFile: "tsc/internal/lsp/lsproto/lsp_generated.go", outDir: "packages/typescript/enums" }, { name: "EmitOnly", goPrefix: "Emit", goFile: "tsc/internal/compiler/emitter.go", outDir: "packages/typescript/enums", excludeMembers: ["OnlyBuilderSignature"] }, // String enum: Go stores internal names with a "\xFE" sentinel prefix, but the escaped - // form sent over the wire uses "__" (see EscapeSymbolName), so map the sentinel accordingly. - { name: "InternalSymbolName", goPrefix: "InternalSymbolName", goFile: "tsc/internal/ast/symbolnames_generated.go", outDir: "packages/typescript/enums", stringEnum: true, valueReplacements: { InternalSymbolNamePrefix: "__" } }, + // form sent over the wire uses "__" (see EscapeSymbolName). + { + name: "InternalSymbolName", + goPrefix: "InternalSymbolName", + goFile: "tsc/internal/ast/symbolnames_generated.go", + outDir: "packages/typescript/enums", + stringEnum: true, + metadata: { + file: "tools/scripts/tsc/symbolNames.ts", + members: symbolNames.filter(n => n.name.startsWith("InternalSymbolName")).map(n => ({ + name: n.name.slice("InternalSymbolName".length), + value: JSON.stringify(n.internal ? "__" + n.text : n.text), + })), + }, + }, ] satisfies EnumDef[]; function syntaxKindMembers(): EnumMember[] { @@ -84,7 +98,7 @@ function syntaxKindMembers(): EnumMember[] { return [...members, { name: "Count", value: String(members.length) }, ...api.kindMarkers()]; } -function parseGoDeclarationBlock(block: string, def: EnumDef): EnumMember[] { +function parseGoConstBlock(block: string, def: EnumDef): EnumMember[] { const prefix = def.goPrefix; const members: EnumMember[] = []; let iotaCounter = 0; @@ -103,9 +117,7 @@ function parseGoDeclarationBlock(block: string, def: EnumDef): EnumMember[] { } // Match: PrefixName Type = value or PrefixName = value - // or, in a keyed composite literal: PrefixName: value, or PrefixName & mask: value, - const fullMatch = line.match(new RegExp(`^(${prefix}\\w+)\\s+(?:\\S+\\s*)?=\\s*(.+)$`)) - ?? (def.stringEnum ? line.match(new RegExp(`^(${prefix}\\w+)(?:\\s*&\\s*\\w+)?:\\s*(.+?),$`)) : null); + const fullMatch = line.match(new RegExp(`^(${prefix}\\w+)\\s+(?:\\S+\\s*)?=\\s*(.+)$`)); // Match bare iota continuation: just PrefixName const bareMatch = !fullMatch && iotaExpression !== undefined ? line.match(new RegExp(`^(${prefix}\\w+)$`)) @@ -280,12 +292,11 @@ function translateGoNumericExpression(expression: string, prefix: string): strin } /** - * Resolve a Go string expression, optionally interned with `MakeSymbolName`, + * Resolve a Go string-constant expression (e.g. `Prefix + "call"` or `"export="`) * 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)) { @@ -309,14 +320,10 @@ interface EnumMember { function parseGoEnum(def: EnumDef): EnumMember[] { const source = fs.readFileSync(path.join(ROOT, def.goFile), "utf-8"); - // Numeric enums come from const blocks. String enums come from var blocks or - // keyed composite literals, such as the texts of constant symbol names. - const declarationBlockRegex = /(const|var)\s*\(([\s\S]*?)\n\)|var\s+\w+\s*=\s*[^{\n]*\{([\s\S]*?)\n\}/g; - - for (const match of source.matchAll(declarationBlockRegex)) { - const isConst = match[1] === "const"; - if (isConst === !!def.stringEnum) continue; - const members = parseGoDeclarationBlock(match[2] ?? match[3], def).filter(member => !def.excludeMembers?.includes(member.name)); + const constBlockRegex = /const\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)); if (members.length > 0) return topoSortMembers(members); } @@ -380,6 +387,14 @@ export function generateEnum(def: EnumDef): { members: EnumMember[]; code: strin const enumValuesGeneratedGoPath = path.join(ROOT, "tsc/internal/api/enum_values_generated.go"); +export const outputs = [ + enumValuesGeneratedGoPath, + ...enumDefs.flatMap(def => { + const camelName = def.name.charAt(0).toLowerCase() + def.name.slice(1); + return [path.join(ROOT, def.outDir, `${camelName}.enum.ts`), path.join(ROOT, def.outDir, `${camelName}.ts`)]; + }), +]; + interface GeneratedEnum { def: EnumDef; code: string; @@ -507,7 +522,6 @@ export default async function generateEnums(force = false) { const generatedGoFile = new GeneratedFile(enumValuesGeneratedGoPath, [...inputs, ...enumDefs.map(def => path.join(ROOT, def.goFile))]); const generatedFiles = [generatedGoFile, ...enumFiles.flatMap(({ typeFile, runtimeFile }) => [typeFile, runtimeFile])]; if (generatedFiles.every(file => file.isCurrent(force))) { - console.log("Enums are up to date."); return; } const ts = await import("typescript"); diff --git a/tools/scripts/tsc/generate-go-ast.ts b/tools/scripts/tsc/generate-go-ast.ts index e472b31c0edf5..fca10e32a7819 100644 --- a/tools/scripts/tsc/generate-go-ast.ts +++ b/tools/scripts/tsc/generate-go-ast.ts @@ -1528,52 +1528,53 @@ function generateSymbolNames(): string { seenTexts.set(fullText, name); } + // A name's ID is the offset, in 8-byte units, of its record in the intern + // table's text arena: a 4-byte length followed by the text. The fixed + // names are inserted first, in this order, so their IDs are known here; + // the table checks that they match. See symbolname_intern.go. + const recordUnits = (text: string) => Math.ceil((4 + Buffer.byteLength(text, "latin1")) / 8); + let nextID = recordUnits(""); + const w = new CodeWriter(); w.write("// Code generated by tools/scripts/tsc/generate-go-ast.ts. DO NOT EDIT."); w.write(""); w.write("package ast"); w.write(""); - w.write("// Fixed symbol names take the first IDs in the intern table, so they are"); - w.write("// compile-time constants. Internal names carry the same tag that"); + w.write("// Fixed symbol names are inserted into the intern table first, so their IDs"); + w.write("// are compile-time constants. Internal names carry the same tag that"); w.write("// internedSymbolName gives them."); w.write("const ("); w.push(); - w.write("EmptySymbolName SymbolName = iota // The zero value."); - // A bare constant repeats the previous expression, so after an internal - // name the next plain name has to restate iota. - let repeatingIota = true; + w.write("EmptySymbolName SymbolName = 0 // The zero value."); + const ids: number[] = []; for (const { name, text, internal, comment } of symbolNames) { - let line = name; + const id = nextID; + ids.push(id); + nextID += recordUnits(internal ? "\xFE" + text : text); + let line = `${name} SymbolName = ${id}`; if (internal) { // The marker is the byte after the prefix plus one, or zero if there is none. const marker = text === "" ? "0" : `('${text[0] === "'" || text[0] === "\\" ? "\\" + text[0] : text[0]}' + 1)`; - line += ` SymbolName = iota | internalSymbolNameBits | ${marker}< { + w.write(`{${ids[i]}, ${internal ? "InternalSymbolNamePrefix + " : ""}${goStringLiteral(text)}},`); + }); w.pop(); w.write("}"); return w.toString(); diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index 3c2ce3ef8fd28..e95d3b1c23b69 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -77,6 +77,27 @@ func TestConcurrentSymbolNameInterning(t *testing.T) { } } +func TestLongSymbolNames(t *testing.T) { + t.Parallel() + // Fill shards past their chunks, then intern names that need a chunk of + // their own or a run of several. + var texts []string + for i := range 5000 { + texts = append(texts, strconv.Itoa(i)+strings.Repeat("m", 300)) + } + for _, n := range []int{4000, 5000, 16 << 10, 40 << 10} { + texts = append(texts, strings.Repeat("x", n-1)+"y") + } + names := make([]ast.SymbolName, len(texts)) + for i, text := range texts { + names[i] = ast.MakeSymbolName(text) + } + for i, text := range texts { + assert.Assert(t, names[i] == ast.MakeSymbolName(strings.Clone(text))) + assert.Equal(t, names[i].String(), text) + } +} + func TestPreinternedSymbolNames(t *testing.T) { t.Parallel() for text, name := range map[string]ast.SymbolName{ diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go index a245727c57a08..cb2504bc184db 100644 --- a/tsc/internal/ast/symbolname_intern.go +++ b/tsc/internal/ast/symbolname_intern.go @@ -3,47 +3,66 @@ package ast import ( "sync" "sync/atomic" + "unsafe" ) // Symbol names are interned into a process-wide table and identified by an // ID; ID 0 is the empty name, and the fixed names generated in -// symbolnames_generated.go take the IDs after it. Interned names are never -// freed. Names synthesized from symbol and node IDs are not interned; see +// symbolnames_generated.go are inserted next. Interned names are never freed. +// Names synthesized from symbol and node IDs are not interned; see // symbolname_derived.go. IDs contain no pointers, so nodes, symbol tables, and // caches that hold them cost the garbage collector nothing to scan. // -// 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. +// Texts are stored in a pointer-free arena as records of a 4-byte length +// followed by the text, aligned to 8-byte units, and an ID is its record's +// offset in units. Looking up an ID's text is then a single dependent load, +// which matters because every intern hit compares texts. The arena is split +// into fixed-size chunks so records never move. Each shard appends records to +// its own chunk, so inserts into different shards don't contend; a record +// longer than a quarter chunk gets its own run of contiguous chunks. +// +// 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 + + symbolNameUnitBytes = 8 + symbolNameRecordHeader = 4 + symbolNameChunkUnitBits = 11 + symbolNameChunkUnits = 1 << symbolNameChunkUnitBits + symbolNameChunkBytes = symbolNameChunkUnits * symbolNameUnitBytes + symbolNameMaxUnits = 1 << derivedNameNumShift + symbolNameMaxChunks = symbolNameMaxUnits / symbolNameChunkUnits ) -type symbolNameChunk [symbolNameChunkSize]string +type symbolNameChunk [symbolNameChunkBytes]byte // Lookups only read tables and chunks; inserts write the shard locks, counts, -// and nextID. Keeping the two groups on separate cache lines stops inserts on -// one core from evicting lines that lookups on every other core need. The -// table is one large allocation, so it starts on a page boundary. +// and the arena cursor. Keeping the two groups on separate cache lines stops +// inserts on one core from evicting lines that lookups on every other core +// need. The table is one large allocation, so it starts on a page boundary. type symbolNameTable struct { - tables [symbolNameShardCount]atomic.Pointer[[]atomic.Uint64] - chunks [symbolNameMaxChunks]atomic.Pointer[symbolNameChunk] - nextID atomic.Uint32 - _ [60]byte - shards [symbolNameShardCount]symbolNameShard + tables [symbolNameShardCount]atomic.Pointer[[]atomic.Uint64] + chunks [symbolNameMaxChunks]atomic.Pointer[symbolNameChunk] + nextChunk atomic.Uint32 + _ [60]byte + shards [symbolNameShardCount]symbolNameShard } type symbolNameShard struct { mu sync.Mutex count int - _ [48]byte + arena symbolNameArena + _ [40]byte +} + +// symbolNameArena is a bump allocator over the units of the current chunk. +type symbolNameArena struct { + next, end uint32 } var symbolNames = newSymbolNameTable() @@ -54,24 +73,29 @@ func newSymbolNameTable() *symbolNameTable { slots := make([]atomic.Uint64, symbolNameInitialSlots) t.tables[i].Store(&slots) } - for want := SymbolName(1); want < SymbolName(len(fixedSymbolNameTexts)); want++ { - text := fixedSymbolNameTexts[want] - if text == "" { + // The empty name's record is the zeroed first unit, and the fixed names + // follow it in order. + fixedArena := &symbolNameArena{} + t.newChunks(fixedArena, 1) + fixedArena.next = 1 + for _, fixed := range fixedSymbolNames { + if fixed.text == "" { panic("fixed symbol name has no text") } - if _, _, _, ok := splitDerivedName(text); ok { - panic("fixed symbol name has a derived form: " + text) + if _, _, _, ok := splitDerivedName(fixed.text); ok { + panic("fixed symbol name has a derived form: " + fixed.text) } - hash := hashSymbolNameText(text) - if id := t.insert(hash, text); SymbolName(id) != want { - panic("duplicate fixed symbol name: " + text) + if id := t.insert(hashSymbolNameText(fixed.text), fixed.text, fixedArena); id != fixed.id { + panic("fixed symbol name has the wrong ID: " + fixed.text) } } return t } func (t *symbolNameTable) text(id uint32) string { - return t.chunks[id>>symbolNameChunkBits].Load()[id&(symbolNameChunkSize-1)] + chunk := t.chunks[id>>symbolNameChunkUnitBits].Load() + record := unsafe.Pointer(&chunk[(id&(symbolNameChunkUnits-1))*symbolNameUnitBytes]) + return unsafe.String((*byte)(unsafe.Add(record, symbolNameRecordHeader)), *(*uint32)(record)) } func (t *symbolNameTable) lookup(slots []atomic.Uint64, hash uint64, text string) uint32 { @@ -103,10 +127,11 @@ func (t *symbolNameTable) make(text string, hash uint64) SymbolName { if name, ok := parseDerivedName(text); ok { return name } - return internedSymbolName(t.insert(hash, text), text) + return internedSymbolName(t.insert(hash, text, nil), text) } -func (t *symbolNameTable) insert(hash uint64, text string) uint32 { +// insert appends new texts to arena, or to the shard's arena if nil. +func (t *symbolNameTable) insert(hash uint64, text string, arena *symbolNameArena) uint32 { table := &t.tables[hash&(symbolNameShardCount-1)] shard := &t.shards[hash&(symbolNameShardCount-1)] shard.mu.Lock() @@ -125,7 +150,10 @@ func (t *symbolNameTable) insert(hash uint64, text string) uint32 { table.Store(&grown) slots = grown } - id := t.allocate(string([]byte(text))) + if arena == nil { + arena = &shard.arena + } + id := t.allocate(arena, text) storeSymbolNameSlot(slots, hash, hash>>32<<32|uint64(id)) shard.count++ return id @@ -135,23 +163,46 @@ 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") +func (t *symbolNameTable) allocate(arena *symbolNameArena, text string) uint32 { + if len(text) > symbolNameMaxUnits*symbolNameUnitBytes { + panic("symbol name too long") } - chunkSlot := &t.chunks[id>>symbolNameChunkBits] - chunk := chunkSlot.Load() - if chunk == nil { - chunk = new(symbolNameChunk) - if !chunkSlot.CompareAndSwap(nil, chunk) { - chunk = chunkSlot.Load() - } + units := uint32((symbolNameRecordHeader + len(text) + symbolNameUnitBytes - 1) / symbolNameUnitBytes) + var id uint32 + switch { + case units > symbolNameChunkUnits/4: + var own symbolNameArena + id = t.newChunks(&own, (units+symbolNameChunkUnits-1)/symbolNameChunkUnits) + case arena.next+units > arena.end: + id = t.newChunks(arena, 1) + arena.next = id + units + default: + id = arena.next + arena.next += units } - chunk[id&(symbolNameChunkSize-1)] = text + chunk := t.chunks[id>>symbolNameChunkUnitBits].Load() + record := unsafe.Pointer(&chunk[(id&(symbolNameChunkUnits-1))*symbolNameUnitBytes]) + *(*uint32)(record) = uint32(len(text)) + copy(unsafe.Slice((*byte)(unsafe.Add(record, symbolNameRecordHeader)), len(text)), text) return id } +// newChunks points arena at a new run of count contiguous chunks and returns +// the run's first unit. +func (t *symbolNameTable) newChunks(arena *symbolNameArena, count uint32) uint32 { + first := t.nextChunk.Add(count) - count + if uint64(first)+uint64(count) > symbolNameMaxChunks { + panic("too many symbol names") + } + run := make([]symbolNameChunk, count) + for i := range run { + t.chunks[first+uint32(i)].Store(&run[i]) + } + arena.next = first << symbolNameChunkUnitBits + arena.end = arena.next + count<> symbolNameShardBits) & mask; ; i = (i + 1) & mask { diff --git a/tsc/internal/ast/symbolnames_generated.go b/tsc/internal/ast/symbolnames_generated.go index f584e1ce0f4d2..1ee236b24f317 100644 --- a/tsc/internal/ast/symbolnames_generated.go +++ b/tsc/internal/ast/symbolnames_generated.go @@ -2,410 +2,411 @@ package ast -// Fixed symbol names take the first IDs in the intern table, so they are -// compile-time constants. Internal names carry the same tag that +// Fixed symbol names are inserted into the intern table first, so their IDs +// are compile-time constants. Internal names carry the same tag that // internedSymbolName gives them. const ( - EmptySymbolName SymbolName = iota // The zero value. - SymbolNameZero - SymbolNameUnresolved - SymbolNameAbstractModuleSource - SymbolNameArray - SymbolNameArrayBuffer - SymbolNameArrayConstructor - SymbolNameArrayLike - SymbolNameAsyncDisposable - SymbolNameAsyncDisposableStack - SymbolNameAsyncGenerator - SymbolNameAsyncGeneratorFunction - SymbolNameAsyncIterable - SymbolNameAsyncIterableIterator - SymbolNameAsyncIterator - SymbolNameAsyncIteratorObject - SymbolNameAtomics - SymbolNameAwaited - SymbolNameBigInt - SymbolNameBigInt64Array - SymbolNameBigUint64Array - SymbolNameBoolean - SymbolNameBuiltinIteratorReturn - SymbolNameCallableFunction - SymbolNameCapitalize - SymbolNameClassAccessorDecoratorContext - SymbolNameClassAccessorDecoratorResult - SymbolNameClassAccessorDecoratorTarget - SymbolNameClassDecoratorContext - SymbolNameClassFieldDecoratorContext - SymbolNameClassGetterDecoratorContext - SymbolNameClassMethodDecoratorContext - SymbolNameClassSetterDecoratorContext - SymbolNameDataView - SymbolNameDate - SymbolNameDateTimeFormat - SymbolNameDisposable - SymbolNameDisposableStack - SymbolNameElement - SymbolNameElementAttributesProperty - SymbolNameElementChildrenAttribute - SymbolNameElementClass - SymbolNameElementType - SymbolNameError - SymbolNameErrorConstructor - SymbolNameEventTarget - SymbolNameExtract - SymbolNameFloat16Array - SymbolNameFloat32Array - SymbolNameFloat64Array - SymbolNameFunction - SymbolNameGenerator - SymbolNameIArguments - SymbolNameImportAttributes - SymbolNameImportCallOptions - SymbolNameImportMeta - SymbolNameImportMetaExpression - SymbolNameInt16Array - SymbolNameInt32Array - SymbolNameInt8Array - SymbolNameIntl - SymbolNameIntrinsicAttributes - SymbolNameIntrinsicClassAttributes - SymbolNameIntrinsicElements - SymbolNameIterable - SymbolNameIterableIterator - SymbolNameIterator - SymbolNameIteratorConstructor - SymbolNameIteratorObject - SymbolNameIteratorReturnResult - SymbolNameIteratorYieldResult - SymbolNameJSON - SymbolNameJSX - SymbolNameK - SymbolNameLibraryManagedAttributes - SymbolNameLowercase - SymbolNameMap - SymbolNameMapConstructor - SymbolNameMath - SymbolNameNaN - SymbolNameNewableFunction - SymbolNameNoInfer - SymbolNameNode - SymbolNameNodeList - SymbolNameNonNullable - SymbolNameNumber - SymbolNameNumberConstructor - SymbolNameNumberFormat - SymbolNameObject - SymbolNameObjectConstructor - SymbolNameOmit - SymbolNamePartial - SymbolNamePick - SymbolNamePromise - SymbolNamePromiseConstructor - SymbolNamePromiseLike - SymbolNameRawJSON - SymbolNameReadonly - SymbolNameReadonlyArray - SymbolNameReadonlyMap - SymbolNameReadonlySet - SymbolNameRecord - SymbolNameReflect - SymbolNameRegExp - SymbolNameRegExpConstructor - SymbolNameRegExpExecArray - SymbolNameRegExpMatchArray - SymbolNameRelativeTimeFormat - SymbolNameRequired - SymbolNameSet - SymbolNameSharedArrayBuffer - SymbolNameString - SymbolNameStringConstructor - SymbolNameSymbol - SymbolNameSymbolConstructor - SymbolNameT - SymbolNameTemplateStringsArray - SymbolNameThisType - SymbolNameTypedPropertyDescriptor - SymbolNameUint16Array - SymbolNameUint32Array - SymbolNameUint8Array - SymbolNameUint8ArrayConstructor - SymbolNameUint8ClampedArray - SymbolNameUncapitalize - SymbolNameUppercase - SymbolNameWeakMap - SymbolNameWeakSet - SymbolNameESModule - SymbolNameUnderscoreDefault - SymbolNameAny - SymbolNameArg - SymbolNameArgs - SymbolNameArguments - SymbolNameAsyncIteratorProperty - SymbolNameBind - SymbolNameBooleanKeyword - SymbolNameCaller - SymbolNameChildren - SymbolNameClass - SymbolNameClassName - SymbolNameConst - SymbolNameContext - SymbolNameDescriptor - SymbolNameDone - SymbolNameExports - SymbolNameFor - SymbolNameGetProperty - SymbolNameGlobal - SymbolNameGlobalThis - SymbolNameHasInstance - SymbolNameHtmlFor - SymbolNameIteratorProperty - SymbolNameLength - SymbolNameMeta - SymbolNameModule - SymbolNameName - SymbolNameNever - SymbolNameNext - SymbolNameNumberKeyword - SymbolNameParameterIndex - SymbolNamePrivate - SymbolNamePropertyKey - SymbolNameProps - SymbolNamePrototype - SymbolNameRequire - SymbolNameReturn - SymbolNameSelf - SymbolNameSetProperty - SymbolNameStatic - SymbolNameStringKeyword - SymbolNameTarget - SymbolNameThen - SymbolNameThrow - SymbolNameUndefined - SymbolNameUnknown - SymbolNameValue - SymbolNameWith - SymbolNameWritable - InternalSymbolNameCall SymbolName = iota | internalSymbolNameBits | ('c'+1)<>", - SymbolNameAbstractModuleSource: "AbstractModuleSource", - SymbolNameArray: "Array", - SymbolNameArrayBuffer: "ArrayBuffer", - SymbolNameArrayConstructor: "ArrayConstructor", - SymbolNameArrayLike: "ArrayLike", - SymbolNameAsyncDisposable: "AsyncDisposable", - SymbolNameAsyncDisposableStack: "AsyncDisposableStack", - SymbolNameAsyncGenerator: "AsyncGenerator", - SymbolNameAsyncGeneratorFunction: "AsyncGeneratorFunction", - SymbolNameAsyncIterable: "AsyncIterable", - SymbolNameAsyncIterableIterator: "AsyncIterableIterator", - SymbolNameAsyncIterator: "AsyncIterator", - SymbolNameAsyncIteratorObject: "AsyncIteratorObject", - SymbolNameAtomics: "Atomics", - SymbolNameAwaited: "Awaited", - SymbolNameBigInt: "BigInt", - SymbolNameBigInt64Array: "BigInt64Array", - SymbolNameBigUint64Array: "BigUint64Array", - SymbolNameBoolean: "Boolean", - SymbolNameBuiltinIteratorReturn: "BuiltinIteratorReturn", - SymbolNameCallableFunction: "CallableFunction", - SymbolNameCapitalize: "Capitalize", - SymbolNameClassAccessorDecoratorContext: "ClassAccessorDecoratorContext", - SymbolNameClassAccessorDecoratorResult: "ClassAccessorDecoratorResult", - SymbolNameClassAccessorDecoratorTarget: "ClassAccessorDecoratorTarget", - SymbolNameClassDecoratorContext: "ClassDecoratorContext", - SymbolNameClassFieldDecoratorContext: "ClassFieldDecoratorContext", - SymbolNameClassGetterDecoratorContext: "ClassGetterDecoratorContext", - SymbolNameClassMethodDecoratorContext: "ClassMethodDecoratorContext", - SymbolNameClassSetterDecoratorContext: "ClassSetterDecoratorContext", - SymbolNameDataView: "DataView", - SymbolNameDate: "Date", - SymbolNameDateTimeFormat: "DateTimeFormat", - SymbolNameDisposable: "Disposable", - SymbolNameDisposableStack: "DisposableStack", - SymbolNameElement: "Element", - SymbolNameElementAttributesProperty: "ElementAttributesProperty", - SymbolNameElementChildrenAttribute: "ElementChildrenAttribute", - SymbolNameElementClass: "ElementClass", - SymbolNameElementType: "ElementType", - SymbolNameError: "Error", - SymbolNameErrorConstructor: "ErrorConstructor", - SymbolNameEventTarget: "EventTarget", - SymbolNameExtract: "Extract", - SymbolNameFloat16Array: "Float16Array", - SymbolNameFloat32Array: "Float32Array", - SymbolNameFloat64Array: "Float64Array", - SymbolNameFunction: "Function", - SymbolNameGenerator: "Generator", - SymbolNameIArguments: "IArguments", - SymbolNameImportAttributes: "ImportAttributes", - SymbolNameImportCallOptions: "ImportCallOptions", - SymbolNameImportMeta: "ImportMeta", - SymbolNameImportMetaExpression: "ImportMetaExpression", - SymbolNameInt16Array: "Int16Array", - SymbolNameInt32Array: "Int32Array", - SymbolNameInt8Array: "Int8Array", - SymbolNameIntl: "Intl", - SymbolNameIntrinsicAttributes: "IntrinsicAttributes", - SymbolNameIntrinsicClassAttributes: "IntrinsicClassAttributes", - SymbolNameIntrinsicElements: "IntrinsicElements", - SymbolNameIterable: "Iterable", - SymbolNameIterableIterator: "IterableIterator", - SymbolNameIterator: "Iterator", - SymbolNameIteratorConstructor: "IteratorConstructor", - SymbolNameIteratorObject: "IteratorObject", - SymbolNameIteratorReturnResult: "IteratorReturnResult", - SymbolNameIteratorYieldResult: "IteratorYieldResult", - SymbolNameJSON: "JSON", - SymbolNameJSX: "JSX", - SymbolNameK: "K", - SymbolNameLibraryManagedAttributes: "LibraryManagedAttributes", - SymbolNameLowercase: "Lowercase", - SymbolNameMap: "Map", - SymbolNameMapConstructor: "MapConstructor", - SymbolNameMath: "Math", - SymbolNameNaN: "NaN", - SymbolNameNewableFunction: "NewableFunction", - SymbolNameNoInfer: "NoInfer", - SymbolNameNode: "Node", - SymbolNameNodeList: "NodeList", - SymbolNameNonNullable: "NonNullable", - SymbolNameNumber: "Number", - SymbolNameNumberConstructor: "NumberConstructor", - SymbolNameNumberFormat: "NumberFormat", - SymbolNameObject: "Object", - SymbolNameObjectConstructor: "ObjectConstructor", - SymbolNameOmit: "Omit", - SymbolNamePartial: "Partial", - SymbolNamePick: "Pick", - SymbolNamePromise: "Promise", - SymbolNamePromiseConstructor: "PromiseConstructor", - SymbolNamePromiseLike: "PromiseLike", - SymbolNameRawJSON: "RawJSON", - SymbolNameReadonly: "Readonly", - SymbolNameReadonlyArray: "ReadonlyArray", - SymbolNameReadonlyMap: "ReadonlyMap", - SymbolNameReadonlySet: "ReadonlySet", - SymbolNameRecord: "Record", - SymbolNameReflect: "Reflect", - SymbolNameRegExp: "RegExp", - SymbolNameRegExpConstructor: "RegExpConstructor", - SymbolNameRegExpExecArray: "RegExpExecArray", - SymbolNameRegExpMatchArray: "RegExpMatchArray", - SymbolNameRelativeTimeFormat: "RelativeTimeFormat", - SymbolNameRequired: "Required", - SymbolNameSet: "Set", - SymbolNameSharedArrayBuffer: "SharedArrayBuffer", - SymbolNameString: "String", - SymbolNameStringConstructor: "StringConstructor", - SymbolNameSymbol: "Symbol", - SymbolNameSymbolConstructor: "SymbolConstructor", - SymbolNameT: "T", - SymbolNameTemplateStringsArray: "TemplateStringsArray", - SymbolNameThisType: "ThisType", - SymbolNameTypedPropertyDescriptor: "TypedPropertyDescriptor", - SymbolNameUint16Array: "Uint16Array", - SymbolNameUint32Array: "Uint32Array", - SymbolNameUint8Array: "Uint8Array", - SymbolNameUint8ArrayConstructor: "Uint8ArrayConstructor", - SymbolNameUint8ClampedArray: "Uint8ClampedArray", - SymbolNameUncapitalize: "Uncapitalize", - SymbolNameUppercase: "Uppercase", - SymbolNameWeakMap: "WeakMap", - SymbolNameWeakSet: "WeakSet", - SymbolNameESModule: "__esModule", - SymbolNameUnderscoreDefault: "_default", - SymbolNameAny: "any", - SymbolNameArg: "arg", - SymbolNameArgs: "args", - SymbolNameArguments: "arguments", - SymbolNameAsyncIteratorProperty: "asyncIterator", - SymbolNameBind: "bind", - SymbolNameBooleanKeyword: "boolean", - SymbolNameCaller: "caller", - SymbolNameChildren: "children", - SymbolNameClass: "class", - SymbolNameClassName: "className", - SymbolNameConst: "const", - SymbolNameContext: "context", - SymbolNameDescriptor: "descriptor", - SymbolNameDone: "done", - SymbolNameExports: "exports", - SymbolNameFor: "for", - SymbolNameGetProperty: "get", - SymbolNameGlobal: "global", - SymbolNameGlobalThis: "globalThis", - SymbolNameHasInstance: "hasInstance", - SymbolNameHtmlFor: "htmlFor", - SymbolNameIteratorProperty: "iterator", - SymbolNameLength: "length", - SymbolNameMeta: "meta", - SymbolNameModule: "module", - SymbolNameName: "name", - SymbolNameNever: "never", - SymbolNameNext: "next", - SymbolNameNumberKeyword: "number", - SymbolNameParameterIndex: "parameterIndex", - SymbolNamePrivate: "private", - SymbolNamePropertyKey: "propertyKey", - SymbolNameProps: "props", - SymbolNamePrototype: "prototype", - SymbolNameRequire: "require", - SymbolNameReturn: "return", - SymbolNameSelf: "self", - SymbolNameSetProperty: "set", - SymbolNameStatic: "static", - SymbolNameStringKeyword: "string", - SymbolNameTarget: "target", - SymbolNameThen: "then", - SymbolNameThrow: "throw", - SymbolNameUndefined: "undefined", - SymbolNameUnknown: "unknown", - SymbolNameValue: "value", - SymbolNameWith: "with", - SymbolNameWritable: "writable", - InternalSymbolNameCall & derivedNameBaseMask: InternalSymbolNamePrefix + "call", - InternalSymbolNameConstructor & derivedNameBaseMask: InternalSymbolNamePrefix + "constructor", - InternalSymbolNameNew & derivedNameBaseMask: InternalSymbolNamePrefix + "new", - InternalSymbolNameIndex & derivedNameBaseMask: InternalSymbolNamePrefix + "index", - InternalSymbolNameExportStar & derivedNameBaseMask: InternalSymbolNamePrefix + "export", - InternalSymbolNameGlobal & derivedNameBaseMask: InternalSymbolNamePrefix + "global", - InternalSymbolNameMissing & derivedNameBaseMask: InternalSymbolNamePrefix + "missing", - InternalSymbolNameType & derivedNameBaseMask: InternalSymbolNamePrefix + "type", - InternalSymbolNameObject & derivedNameBaseMask: InternalSymbolNamePrefix + "object", - InternalSymbolNameJSXAttributes & derivedNameBaseMask: InternalSymbolNamePrefix + "jsxAttributes", - InternalSymbolNameClass & derivedNameBaseMask: InternalSymbolNamePrefix + "class", - InternalSymbolNameFunction & derivedNameBaseMask: InternalSymbolNamePrefix + "function", - InternalSymbolNameComputed & derivedNameBaseMask: InternalSymbolNamePrefix + "computed", - InternalSymbolNameAssignmentDeclaration & derivedNameBaseMask: InternalSymbolNamePrefix + "assignment", - InternalSymbolNameInstantiationExpression & derivedNameBaseMask: InternalSymbolNamePrefix + "instantiationExpression", - InternalSymbolNameImportAttributes & derivedNameBaseMask: InternalSymbolNamePrefix + "importAttributes", - InternalSymbolNameExportEquals: "export=", - InternalSymbolNameDefault: "default", - InternalSymbolNameThis: "this", - InternalSymbolNameModuleExports: "module.exports", +var fixedSymbolNames = [...]struct { + id uint32 + text string +}{ + {1, "0"}, + {2, "<>"}, + {5, "AbstractModuleSource"}, + {8, "Array"}, + {10, "ArrayBuffer"}, + {12, "ArrayConstructor"}, + {15, "ArrayLike"}, + {17, "AsyncDisposable"}, + {20, "AsyncDisposableStack"}, + {23, "AsyncGenerator"}, + {26, "AsyncGeneratorFunction"}, + {30, "AsyncIterable"}, + {33, "AsyncIterableIterator"}, + {37, "AsyncIterator"}, + {40, "AsyncIteratorObject"}, + {43, "Atomics"}, + {45, "Awaited"}, + {47, "BigInt"}, + {49, "BigInt64Array"}, + {52, "BigUint64Array"}, + {55, "Boolean"}, + {57, "BuiltinIteratorReturn"}, + {61, "CallableFunction"}, + {64, "Capitalize"}, + {66, "ClassAccessorDecoratorContext"}, + {71, "ClassAccessorDecoratorResult"}, + {75, "ClassAccessorDecoratorTarget"}, + {79, "ClassDecoratorContext"}, + {83, "ClassFieldDecoratorContext"}, + {87, "ClassGetterDecoratorContext"}, + {91, "ClassMethodDecoratorContext"}, + {95, "ClassSetterDecoratorContext"}, + {99, "DataView"}, + {101, "Date"}, + {102, "DateTimeFormat"}, + {105, "Disposable"}, + {107, "DisposableStack"}, + {110, "Element"}, + {112, "ElementAttributesProperty"}, + {116, "ElementChildrenAttribute"}, + {120, "ElementClass"}, + {122, "ElementType"}, + {124, "Error"}, + {126, "ErrorConstructor"}, + {129, "EventTarget"}, + {131, "Extract"}, + {133, "Float16Array"}, + {135, "Float32Array"}, + {137, "Float64Array"}, + {139, "Function"}, + {141, "Generator"}, + {143, "IArguments"}, + {145, "ImportAttributes"}, + {148, "ImportCallOptions"}, + {151, "ImportMeta"}, + {153, "ImportMetaExpression"}, + {156, "Int16Array"}, + {158, "Int32Array"}, + {160, "Int8Array"}, + {162, "Intl"}, + {163, "IntrinsicAttributes"}, + {166, "IntrinsicClassAttributes"}, + {170, "IntrinsicElements"}, + {173, "Iterable"}, + {175, "IterableIterator"}, + {178, "Iterator"}, + {180, "IteratorConstructor"}, + {183, "IteratorObject"}, + {186, "IteratorReturnResult"}, + {189, "IteratorYieldResult"}, + {192, "JSON"}, + {193, "JSX"}, + {194, "K"}, + {195, "LibraryManagedAttributes"}, + {199, "Lowercase"}, + {201, "Map"}, + {202, "MapConstructor"}, + {205, "Math"}, + {206, "NaN"}, + {207, "NewableFunction"}, + {210, "NoInfer"}, + {212, "Node"}, + {213, "NodeList"}, + {215, "NonNullable"}, + {217, "Number"}, + {219, "NumberConstructor"}, + {222, "NumberFormat"}, + {224, "Object"}, + {226, "ObjectConstructor"}, + {229, "Omit"}, + {230, "Partial"}, + {232, "Pick"}, + {233, "Promise"}, + {235, "PromiseConstructor"}, + {238, "PromiseLike"}, + {240, "RawJSON"}, + {242, "Readonly"}, + {244, "ReadonlyArray"}, + {247, "ReadonlyMap"}, + {249, "ReadonlySet"}, + {251, "Record"}, + {253, "Reflect"}, + {255, "RegExp"}, + {257, "RegExpConstructor"}, + {260, "RegExpExecArray"}, + {263, "RegExpMatchArray"}, + {266, "RelativeTimeFormat"}, + {269, "Required"}, + {271, "Set"}, + {272, "SharedArrayBuffer"}, + {275, "String"}, + {277, "StringConstructor"}, + {280, "Symbol"}, + {282, "SymbolConstructor"}, + {285, "T"}, + {286, "TemplateStringsArray"}, + {289, "ThisType"}, + {291, "TypedPropertyDescriptor"}, + {295, "Uint16Array"}, + {297, "Uint32Array"}, + {299, "Uint8Array"}, + {301, "Uint8ArrayConstructor"}, + {305, "Uint8ClampedArray"}, + {308, "Uncapitalize"}, + {310, "Uppercase"}, + {312, "WeakMap"}, + {314, "WeakSet"}, + {316, "__esModule"}, + {318, "_default"}, + {320, "any"}, + {321, "arg"}, + {322, "args"}, + {323, "arguments"}, + {325, "asyncIterator"}, + {328, "bind"}, + {329, "boolean"}, + {331, "caller"}, + {333, "children"}, + {335, "class"}, + {337, "className"}, + {339, "const"}, + {341, "context"}, + {343, "descriptor"}, + {345, "done"}, + {346, "exports"}, + {348, "for"}, + {349, "get"}, + {350, "global"}, + {352, "globalThis"}, + {354, "hasInstance"}, + {356, "htmlFor"}, + {358, "iterator"}, + {360, "length"}, + {362, "meta"}, + {363, "module"}, + {365, "name"}, + {366, "never"}, + {368, "next"}, + {369, "number"}, + {371, "parameterIndex"}, + {374, "private"}, + {376, "propertyKey"}, + {378, "props"}, + {380, "prototype"}, + {382, "require"}, + {384, "return"}, + {386, "self"}, + {387, "set"}, + {388, "static"}, + {390, "string"}, + {392, "target"}, + {394, "then"}, + {395, "throw"}, + {397, "undefined"}, + {399, "unknown"}, + {401, "value"}, + {403, "with"}, + {404, "writable"}, + {406, InternalSymbolNamePrefix + "call"}, + {408, InternalSymbolNamePrefix + "constructor"}, + {410, InternalSymbolNamePrefix + "new"}, + {411, InternalSymbolNamePrefix + "index"}, + {413, InternalSymbolNamePrefix + "export"}, + {415, InternalSymbolNamePrefix + "global"}, + {417, InternalSymbolNamePrefix + "missing"}, + {419, InternalSymbolNamePrefix + "type"}, + {421, InternalSymbolNamePrefix + "object"}, + {423, InternalSymbolNamePrefix + "jsxAttributes"}, + {426, InternalSymbolNamePrefix + "class"}, + {428, InternalSymbolNamePrefix + "function"}, + {430, InternalSymbolNamePrefix + "computed"}, + {432, InternalSymbolNamePrefix + "assignment"}, + {434, InternalSymbolNamePrefix + "instantiationExpression"}, + {438, InternalSymbolNamePrefix + "importAttributes"}, + {441, "export="}, + {443, "default"}, + {445, "this"}, + {446, "module.exports"}, } From 77b99e530f290722f013ec1b676249b0d07e4a23 Mon Sep 17 00:00:00 2001 From: Jake Bailey <5341706+jakebailey@users.noreply.github.com> Date: Wed, 28 Oct 2026 14:40:12 -0700 Subject: [PATCH 13/14] Widen interned symbol name IDs to 32 bits With arena offsets as IDs, the 26-bit base ID field capped the table at 512MB of name text. Give the base ID the full low 32 bits, the most the hash slots can hold, and shrink derived-name numbers to 29 bits; larger numbers already fall back to interning the full text. A flat array of chunk pointers for 32GB of arena would be 16MB, so find chunks through a two-level directory whose small top level stays in cache. --- tsc/internal/ast/symbol_test.go | 28 +++++++++++----------- tsc/internal/ast/symbolname_derived.go | 6 ++--- tsc/internal/ast/symbolname_intern.go | 32 ++++++++++++++++++++------ 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/tsc/internal/ast/symbol_test.go b/tsc/internal/ast/symbol_test.go index e95d3b1c23b69..ac8377770c98f 100644 --- a/tsc/internal/ast/symbol_test.go +++ b/tsc/internal/ast/symbol_test.go @@ -119,21 +119,21 @@ func TestPreinternedSymbolNames(t *testing.T) { func TestDerivedSymbolNames(t *testing.T) { t.Parallel() - const maxNum = 1<<35 - 1 + const maxNum = 1<<29 - 1 for text, name := range map[string]ast.SymbolName{ - "\xFE#12@#value": ast.MakePrivateSymbolName(12, "#value"), - "\xFE#0@": ast.MakePrivateSymbolName(0, ""), - "\xFE@iterator@7": ast.MakeUniqueESSymbolName(ast.SymbolNameIteratorProperty, 7), - "\xFE@a@b@7": ast.MakeUniqueESSymbolName(ast.MakeSymbolName("a@b"), 7), - "\xFE\"*.css\"pattern@9": ast.MakeModulePatternSymbolName("*.css", 9), - "(auto@3)": ast.MakeGeneratedSymbolName("", false, 3, ""), - "_(generated@4)_1": ast.MakeGeneratedSymbolName("_", true, 4, "_1"), - "(auto@(auto@5)": ast.MakeGeneratedSymbolName("(auto@", false, 5, ""), - "(auto@1)(auto@2)": ast.MakeGeneratedSymbolName("(auto@1)", false, 2, ""), - "\xFE#" + "34359738367@#x": ast.MakePrivateSymbolName(maxNum, "#x"), - "\xFE#" + "34359738368@#x": ast.MakePrivateSymbolName(maxNum+1, "#x"), - "\xFE@\xFE#1@#x@2": ast.MakeUniqueESSymbolName(ast.MakePrivateSymbolName(1, "#x"), 2), - "\xFEx(auto@1)": ast.MakeGeneratedSymbolName("\xFEx", false, 1, ""), + "\xFE#12@#value": ast.MakePrivateSymbolName(12, "#value"), + "\xFE#0@": ast.MakePrivateSymbolName(0, ""), + "\xFE@iterator@7": ast.MakeUniqueESSymbolName(ast.SymbolNameIteratorProperty, 7), + "\xFE@a@b@7": ast.MakeUniqueESSymbolName(ast.MakeSymbolName("a@b"), 7), + "\xFE\"*.css\"pattern@9": ast.MakeModulePatternSymbolName("*.css", 9), + "(auto@3)": ast.MakeGeneratedSymbolName("", false, 3, ""), + "_(generated@4)_1": ast.MakeGeneratedSymbolName("_", true, 4, "_1"), + "(auto@(auto@5)": ast.MakeGeneratedSymbolName("(auto@", false, 5, ""), + "(auto@1)(auto@2)": ast.MakeGeneratedSymbolName("(auto@1)", false, 2, ""), + "\xFE#" + "536870911@#x": ast.MakePrivateSymbolName(maxNum, "#x"), + "\xFE#" + "536870912@#x": ast.MakePrivateSymbolName(maxNum+1, "#x"), + "\xFE@\xFE#1@#x@2": ast.MakeUniqueESSymbolName(ast.MakePrivateSymbolName(1, "#x"), 2), + "\xFEx(auto@1)": ast.MakeGeneratedSymbolName("\xFEx", false, 1, ""), } { t.Run(text, func(t *testing.T) { t.Parallel() diff --git a/tsc/internal/ast/symbolname_derived.go b/tsc/internal/ast/symbolname_derived.go index f75550153df04..ac7c33ccf6224 100644 --- a/tsc/internal/ast/symbolname_derived.go +++ b/tsc/internal/ast/symbolname_derived.go @@ -14,8 +14,8 @@ import ( // the SymbolName itself and renders its text on demand: // // bits 61-63: kind (0 for plain interned names) -// bits 26-60: number -// bits 0-25: interned ID of the base text (always an interned name) +// bits 32-60: number +// bits 0-31: interned ID of the base text (always an interned name) // // Names must be equal exactly when their texts are equal, so MakeSymbolName // parses text that has a derived form into that form and never interns it. @@ -40,7 +40,7 @@ const ( const ( derivedNameKindShift = 61 - derivedNameNumShift = 26 + derivedNameNumShift = 32 derivedNameNumMax = 1<<(derivedNameKindShift-derivedNameNumShift) - 1 derivedNameBaseMask = 1<>symbolNameDirBits].Load()[index&(symbolNameDirSize-1)].Load() +} + func (t *symbolNameTable) text(id uint32) string { - chunk := t.chunks[id>>symbolNameChunkUnitBits].Load() + chunk := t.chunk(id >> symbolNameChunkUnitBits) record := unsafe.Pointer(&chunk[(id&(symbolNameChunkUnits-1))*symbolNameUnitBytes]) return unsafe.String((*byte)(unsafe.Add(record, symbolNameRecordHeader)), *(*uint32)(record)) } @@ -164,7 +174,7 @@ func (t *symbolNameTable) hashOf(id uint32) uint64 { } func (t *symbolNameTable) allocate(arena *symbolNameArena, text string) uint32 { - if len(text) > symbolNameMaxUnits*symbolNameUnitBytes { + if len(text) > 1<<30 { panic("symbol name too long") } units := uint32((symbolNameRecordHeader + len(text) + symbolNameUnitBytes - 1) / symbolNameUnitBytes) @@ -180,7 +190,7 @@ func (t *symbolNameTable) allocate(arena *symbolNameArena, text string) uint32 { id = arena.next arena.next += units } - chunk := t.chunks[id>>symbolNameChunkUnitBits].Load() + chunk := t.chunk(id >> symbolNameChunkUnitBits) record := unsafe.Pointer(&chunk[(id&(symbolNameChunkUnits-1))*symbolNameUnitBytes]) *(*uint32)(record) = uint32(len(text)) copy(unsafe.Slice((*byte)(unsafe.Add(record, symbolNameRecordHeader)), len(text)), text) @@ -196,7 +206,15 @@ func (t *symbolNameTable) newChunks(arena *symbolNameArena, count uint32) uint32 } run := make([]symbolNameChunk, count) for i := range run { - t.chunks[first+uint32(i)].Store(&run[i]) + index := first + uint32(i) + dir := t.dirs[index>>symbolNameDirBits].Load() + if dir == nil { + dir = new(symbolNameDir) + if !t.dirs[index>>symbolNameDirBits].CompareAndSwap(nil, dir) { + dir = t.dirs[index>>symbolNameDirBits].Load() + } + } + dir[index&(symbolNameDirSize-1)].Store(&run[i]) } arena.next = first << symbolNameChunkUnitBits arena.end = arena.next + count< Date: Wed, 28 Oct 2026 15:51:49 -0700 Subject: [PATCH 14/14] Give interner write state its own cache-line-aligned allocation The read-mostly and written halves of the table were kept apart by padding inside one struct, which relied on the table starting on a cache line. With the two-level directory the table is small enough to get a size-class allocation, and since it holds pointers the runtime puts an 8-byte header before it, so the shards were 8 bytes off. Move the shards and chunk counter into a separate pointer-free allocation, which has no header and a size class that's a multiple of 64 bytes. --- tsc/internal/ast/symbolname_intern.go | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/tsc/internal/ast/symbolname_intern.go b/tsc/internal/ast/symbolname_intern.go index a751107b6c9b0..5a6137c82da55 100644 --- a/tsc/internal/ast/symbolname_intern.go +++ b/tsc/internal/ast/symbolname_intern.go @@ -48,15 +48,20 @@ type symbolNameChunk [symbolNameChunkBytes]byte type symbolNameDir [symbolNameDirSize]atomic.Pointer[symbolNameChunk] // Lookups only read tables and chunks; inserts write the shard locks, counts, -// and the arena cursor. Keeping the two groups on separate cache lines stops +// and arena cursors. Keeping the two groups on separate cache lines stops // inserts on one core from evicting lines that lookups on every other core -// need. The table is one large allocation, so it starts on a page boundary. +// need. The written state is a separate pointer-free allocation: the runtime +// puts no header before those, and its size class is a multiple of 64 bytes, +// so each shard gets a cache line of its own. type symbolNameTable struct { - tables [symbolNameShardCount]atomic.Pointer[[]atomic.Uint64] - dirs [(symbolNameMaxChunks + symbolNameDirSize) / symbolNameDirSize]atomic.Pointer[symbolNameDir] - nextChunk atomic.Uint32 - _ [60]byte + tables [symbolNameShardCount]atomic.Pointer[[]atomic.Uint64] + dirs [(symbolNameMaxChunks + symbolNameDirSize) / symbolNameDirSize]atomic.Pointer[symbolNameDir] + writes *symbolNameWrites +} + +type symbolNameWrites struct { shards [symbolNameShardCount]symbolNameShard + nextChunk atomic.Uint32 } type symbolNameShard struct { @@ -74,7 +79,7 @@ type symbolNameArena struct { var symbolNames = newSymbolNameTable() func newSymbolNameTable() *symbolNameTable { - t := &symbolNameTable{} + t := &symbolNameTable{writes: new(symbolNameWrites)} for i := range t.tables { slots := make([]atomic.Uint64, symbolNameInitialSlots) t.tables[i].Store(&slots) @@ -143,7 +148,7 @@ func (t *symbolNameTable) make(text string, hash uint64) SymbolName { // insert appends new texts to arena, or to the shard's arena if nil. func (t *symbolNameTable) insert(hash uint64, text string, arena *symbolNameArena) uint32 { table := &t.tables[hash&(symbolNameShardCount-1)] - shard := &t.shards[hash&(symbolNameShardCount-1)] + shard := &t.writes.shards[hash&(symbolNameShardCount-1)] shard.mu.Lock() defer shard.mu.Unlock() slots := *table.Load() @@ -200,7 +205,7 @@ func (t *symbolNameTable) allocate(arena *symbolNameArena, text string) uint32 { // newChunks points arena at a new run of count contiguous chunks and returns // the run's first unit. func (t *symbolNameTable) newChunks(arena *symbolNameArena, count uint32) uint32 { - first := t.nextChunk.Add(count) - count + first := t.writes.nextChunk.Add(count) - count if uint64(first)+uint64(count) > symbolNameMaxChunks { panic("too many symbol names") }