Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions tsc/internal/api/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ func getSourceFileSymbolIndex(sourceFile *ast.SourceFile) map[SymbolID]*ast.Symb
index := make(map[SymbolID]*ast.Symbol, file.SymbolCount)
var addSymbol func(*ast.Symbol)
addSymbol = func(symbol *ast.Symbol) {
if symbol == nil || symbol.Flags&ast.SymbolFlagsTransient != 0 {
if symbol == nil || symbol.Flags()&ast.SymbolFlagsTransient != 0 {
return
}
compilerdebug.Assert(ast.GetSourceFileOfSymbol(symbol) == file)
Expand All @@ -67,9 +67,9 @@ func getSourceFileSymbolIndex(sourceFile *ast.SourceFile) map[SymbolID]*ast.Symb
return
}
index[id] = symbol
addSymbol(symbol.Parent)
addSymbol(symbol.ExportSymbol)
for _, table := range []ast.SymbolTable{symbol.Members, symbol.Exports} {
addSymbol(symbol.Parent())
addSymbol(symbol.ExportSymbol())
for _, table := range []ast.SymbolTable{symbol.Members(), symbol.Exports()} {
for _, child := range table {
addSymbol(child)
}
Expand Down Expand Up @@ -203,7 +203,7 @@ func (sd *snapshotData) getOrCreateProjectRegistry(projectID project.ID) *projec
// symbol is owned by its snapshot. Content-mapped outputs live in a cache that cannot yet be
// addressed by file key, so their binder symbols remain snapshot-owned.
func symbolOwnerFile(symbol *ast.Symbol) *ast.SourceFile {
if symbol.Flags&ast.SymbolFlagsTransient != 0 {
if symbol.Flags()&ast.SymbolFlagsTransient != 0 {
return nil
}
file := ast.GetSourceFileOfSymbol(symbol)
Expand Down Expand Up @@ -248,25 +248,25 @@ func newFileSymbolResponse(symbol *ast.Symbol) *SymbolResponse {
func buildSymbolResponse(symbol *ast.Symbol, reference SymbolReference, owner *ast.SourceFile) *SymbolResponse {
resp := &SymbolResponse{
Reference: reference,
Name: ast.EscapeSymbolName(symbol.Name),
Flags: uint32(symbol.Flags),
CheckFlags: uint32(symbol.CheckFlags),
Parent: newSymbolReference(symbol.Parent),
ExportSymbol: newSymbolReference(symbol.ExportSymbol),
Name: ast.EscapeSymbolName(symbol.Name()),
Flags: uint32(symbol.Flags()),
CheckFlags: uint32(symbol.CheckFlags()),
Parent: newSymbolReference(symbol.Parent()),
ExportSymbol: newSymbolReference(symbol.ExportSymbol()),
}
if owner != nil {
// A client resolves a file-owned symbol's relationships through its own source file.
compilerdebug.Assert(symbol.Parent == nil || symbolOwnerFile(symbol.Parent) == owner, "File-owned symbol parent belongs to another owner")
compilerdebug.Assert(symbol.ExportSymbol == nil || symbolOwnerFile(symbol.ExportSymbol) == owner, "File-owned export symbol belongs to another owner")
compilerdebug.Assert(symbol.Parent() == nil || symbolOwnerFile(symbol.Parent()) == owner, "File-owned symbol parent belongs to another owner")
compilerdebug.Assert(symbol.ExportSymbol() == nil || symbolOwnerFile(symbol.ExportSymbol()) == owner, "File-owned export symbol belongs to another owner")
}
if len(symbol.Declarations) > 0 {
resp.Declarations = make([]NodeHandle, len(symbol.Declarations))
for i, decl := range symbol.Declarations {
if len(symbol.Declarations()) > 0 {
resp.Declarations = make([]NodeHandle, len(symbol.Declarations()))
for i, decl := range symbol.Declarations() {
resp.Declarations[i] = symbolNodeHandleFrom(decl, owner)
}
}
if symbol.ValueDeclaration != nil {
resp.ValueDeclaration = symbolNodeHandleFrom(symbol.ValueDeclaration, owner)
if symbol.ValueDeclaration() != nil {
resp.ValueDeclaration = symbolNodeHandleFrom(symbol.ValueDeclaration(), owner)
}
return resp
}
Expand Down Expand Up @@ -3071,26 +3071,26 @@ func (s *Session) handleGetTypesAtPositions(ctx context.Context, params *GetType

// @gen-proto-nullable
func (s *Session) handleGetParentOfSymbol(_ context.Context, params *GetSymbolPropertyParams) (*SymbolResponse, error) {
return s.resolveSymbolPropertyOfSymbol(params, func(sym *ast.Symbol) *ast.Symbol { return sym.Parent })
return s.resolveSymbolPropertyOfSymbol(params, func(sym *ast.Symbol) *ast.Symbol { return sym.Parent() })
}

// @gen-proto-nullable
func (s *Session) handleGetMembersOfSymbol(ctx context.Context, params *GetSymbolPropertyParams) ([]*SymbolResponse, error) {
return s.resolveSymbolTablePropertyOfSymbol(ctx, params, func(symbol *ast.Symbol) ast.SymbolTable {
return symbol.Members
return symbol.Members()
})
}

// @gen-proto-nullable
func (s *Session) handleGetExportsOfSymbol(ctx context.Context, params *GetSymbolPropertyParams) ([]*SymbolResponse, error) {
return s.resolveSymbolTablePropertyOfSymbol(ctx, params, func(symbol *ast.Symbol) ast.SymbolTable {
return symbol.Exports
return symbol.Exports()
})
}

// @gen-proto-nullable
func (s *Session) handleGetExportSymbolOfSymbol(_ context.Context, params *GetSymbolPropertyParams) (*SymbolResponse, error) {
return s.resolveSymbolPropertyOfSymbol(params, func(sym *ast.Symbol) *ast.Symbol { return sym.ExportSymbol })
return s.resolveSymbolPropertyOfSymbol(params, func(sym *ast.Symbol) *ast.Symbol { return sym.ExportSymbol() })
}

// @gen-proto-nullable
Expand Down Expand Up @@ -3469,20 +3469,20 @@ func (s *Session) resolveSymbolTablePropertyOfSymbol(ctx context.Context, params
slices.SortFunc(symbols, func(left *ast.Symbol, right *ast.Symbol) int {
compilerdebug.Assert(ast.GetSourceFileOfSymbol(left) == file)
compilerdebug.Assert(ast.GetSourceFileOfSymbol(right) == file)
leftHasDeclaration := len(left.Declarations) != 0
rightHasDeclaration := len(right.Declarations) != 0
leftHasDeclaration := len(left.Declarations()) != 0
rightHasDeclaration := len(right.Declarations()) != 0
if leftHasDeclaration != rightHasDeclaration {
if leftHasDeclaration {
return -1
}
return 1
}
if leftHasDeclaration {
if order := cmp.Compare(left.Declarations[0].Pos(), right.Declarations[0].Pos()); order != 0 {
if order := cmp.Compare(left.Declarations()[0].Pos(), right.Declarations()[0].Pos()); order != 0 {
return order
}
}
if order := cmp.Compare(left.Name, right.Name); order != 0 {
if order := cmp.Compare(left.Name(), right.Name()); order != 0 {
return order
}
return cmp.Compare(ast.GetSymbolId(left), ast.GetSymbolId(right))
Expand Down Expand Up @@ -4214,9 +4214,9 @@ func (s *Session) handleGetWellKnownSymbols(ctx context.Context, params *GetIntr
unknownSymbol := setup.checker.GetUnknownSymbol()
undefinedSymbol := setup.checker.GetUndefinedSymbol()
argumentsSymbol := setup.checker.GetArgumentsSymbol()
compilerdebug.Assert(unknownSymbol.Flags&ast.SymbolFlagsTransient != 0)
compilerdebug.Assert(undefinedSymbol.Flags&ast.SymbolFlagsTransient != 0)
compilerdebug.Assert(argumentsSymbol.Flags&ast.SymbolFlagsTransient != 0)
compilerdebug.Assert(unknownSymbol.Flags()&ast.SymbolFlagsTransient != 0)
compilerdebug.Assert(undefinedSymbol.Flags()&ast.SymbolFlagsTransient != 0)
compilerdebug.Assert(argumentsSymbol.Flags()&ast.SymbolFlagsTransient != 0)
unknown, _ := setup.sd.registerSymbol(unknownSymbol, setup.projectID)
undefined, _ := setup.sd.registerSymbol(undefinedSymbol, setup.projectID)
arguments, _ := setup.sd.registerSymbol(argumentsSymbol, setup.projectID)
Expand Down
13 changes: 6 additions & 7 deletions tsc/internal/api/session_symbolresponse_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,11 +59,10 @@ func TestTransientSymbolWithFileDeclarationIsSnapshotOwned(t *testing.T) {
t.Parallel()
sourceFile := parseAndBind(t, "/file.ts", `export class C { property = 1 }`)
class := sourceFile.Statements.Nodes[0]
symbol := &ast.Symbol{
Flags: ast.SymbolFlagsClass | ast.SymbolFlagsTransient,
Name: "C",
Declarations: []*ast.Node{class},
}
symbol := &ast.Symbol{}
symbol.SetFlags(ast.SymbolFlagsClass | ast.SymbolFlagsTransient)
symbol.SetName("C")
symbol.SetDeclarations([]*ast.Node{class})
sd := newTestSnapshotData()

response := sd.newSymbolResponse(symbol, "/tsconfig.json")
Expand All @@ -86,7 +85,7 @@ func TestSymbolReferencesIdentifyOwnerWithoutDescriptor(t *testing.T) {
assert.Assert(t, !strings.Contains(string(encoded), "contentHash"))

// A file-owned symbol's relationships are references into the same file.
member := class.Members["property"]
member := class.Members()["property"]
response := newFileSymbolResponse(member)
assert.DeepEqual(t, response.Parent, reference)
}
Expand All @@ -110,6 +109,6 @@ func TestContentMappedSymbolsAreSnapshotOwned(t *testing.T) {
assert.NilError(t, err)
assert.Equal(t, resolved, class)

reference := newSymbolReference(class.Members["property"])
reference := newSymbolReference(class.Members()["property"])
assert.Equal(t, reference.File, "")
}
76 changes: 48 additions & 28 deletions tsc/internal/ast/symbol.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,60 +7,80 @@ import (
"github.com/microsoft/TypeScript/tsc/internal/debug"
)

// Symbol

// Symbol stores binding information. Its accessors expose the stored values
// without copying declaration slices or symbol tables.
type Symbol struct {
Flags SymbolFlags
CheckFlags CheckFlags // Non-zero only in transient symbols created by Checker
Name string
Declarations []*Node
ValueDeclaration *Node
Members SymbolTable
Exports SymbolTable
flags SymbolFlags
checkFlags CheckFlags // Non-zero only in transient symbols created by Checker
name string
declarations []*Node
valueDeclaration *Node
members SymbolTable
exports SymbolTable
id atomic.Uint64
Parent *Symbol
ExportSymbol *Symbol
parent *Symbol
exportSymbol *Symbol
}

func (s *Symbol) Flags() SymbolFlags { return s.flags }
func (s *Symbol) CheckFlags() CheckFlags { return s.checkFlags }
func (s *Symbol) Name() string { return s.name }
func (s *Symbol) Declarations() []*Node { return s.declarations }
func (s *Symbol) ValueDeclaration() *Node { return s.valueDeclaration }
func (s *Symbol) Members() SymbolTable { return s.members }
func (s *Symbol) Exports() SymbolTable { return s.exports }
func (s *Symbol) Parent() *Symbol { return s.parent }
func (s *Symbol) ExportSymbol() *Symbol { return s.exportSymbol }

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.name = value }
func (s *Symbol) SetDeclarations(value []*Node) { s.declarations = value }
func (s *Symbol) SetValueDeclaration(value *Node) { s.valueDeclaration = value }
func (s *Symbol) SetMembers(value SymbolTable) { s.members = value }
func (s *Symbol) SetExports(value SymbolTable) { s.exports = value }
func (s *Symbol) SetParent(value *Symbol) { s.parent = value }
func (s *Symbol) SetExportSymbol(value *Symbol) { s.exportSymbol = value }

// GetSourceFileOfSymbol returns the owning file of a published binder symbol, or
// nil for a non-file-owned symbol, even if it borrows declarations from a file.
// Ownership recovery walks only the first declaration's AST parents.
func GetSourceFileOfSymbol(symbol *Symbol) *SourceFile {
debug.Assert(symbol != nil, "Expected a symbol")
if symbol.Flags&SymbolFlagsTransient != 0 {
if symbol.Flags()&SymbolFlagsTransient != 0 {
return nil
}
if len(symbol.Declarations) == 0 {
if len(symbol.Declarations()) == 0 {
// A class's implicit prototype has no declaration of its own.
debug.Assert(symbol.Flags&SymbolFlagsPrototype != 0, "File-bound symbol has no declarations")
debug.Assert(symbol.Parent != nil && symbol.Parent.Flags&SymbolFlagsClass != 0, "Prototype has no declaring class")
symbol = symbol.Parent
debug.Assert(symbol.Flags&SymbolFlagsTransient == 0, "Prototype parent is not file-bound")
debug.Assert(len(symbol.Declarations) != 0, "Prototype parent has no declarations")
debug.Assert(symbol.Flags()&SymbolFlagsPrototype != 0, "File-bound symbol has no declarations")
debug.Assert(symbol.Parent() != nil && symbol.Parent().Flags()&SymbolFlagsClass != 0, "Prototype has no declaring class")
symbol = symbol.Parent()
debug.Assert(symbol.Flags()&SymbolFlagsTransient == 0, "Prototype parent is not file-bound")
debug.Assert(len(symbol.Declarations()) != 0, "Prototype parent has no declarations")
}
file := GetSourceFileOfNode(symbol.Declarations[0])
file := GetSourceFileOfNode(symbol.Declarations()[0])
debug.Assert(file != nil, "File-bound declaration has no source file")
return file
}

func (s *Symbol) IsExternalModule() bool {
return s.Flags&SymbolFlagsModule != 0 && IsAmbientModuleSymbolName(s.Name)
return s.Flags()&SymbolFlagsModule != 0 && IsAmbientModuleSymbolName(s.Name())
}

func (s *Symbol) IsStatic() bool {
if s.ValueDeclaration == nil {
if s.ValueDeclaration() == nil {
return false
}
modifierFlags := s.ValueDeclaration.ModifierFlags()
modifierFlags := s.ValueDeclaration().ModifierFlags()
return modifierFlags&ModifierFlagsStatic != 0
}

// See comment on `declareModuleMember` in `binder.go`.
func (s *Symbol) CombinedLocalAndExportSymbolFlags() SymbolFlags {
if s.ExportSymbol != nil {
return s.Flags | s.ExportSymbol.Flags
if s.ExportSymbol() != nil {
return s.Flags() | s.ExportSymbol().Flags()
}
return s.Flags
return s.Flags()
}

// SymbolTable
Expand Down Expand Up @@ -93,10 +113,10 @@ const (
)

func SymbolName(symbol *Symbol) string {
if symbol.ValueDeclaration != nil && IsPrivateIdentifierClassElementDeclaration(symbol.ValueDeclaration) {
return symbol.ValueDeclaration.Name().Text()
if symbol.ValueDeclaration() != nil && IsPrivateIdentifierClassElementDeclaration(symbol.ValueDeclaration()) {
return symbol.ValueDeclaration().Name().Text()
}
return symbol.Name
return symbol.Name()
}

// EscapeAllInternalSymbolNames replaces internal symbol name markers ("\xFE") with "__".
Expand Down
Loading
Loading