remove unused packages

This commit is contained in:
Egor Aristov 2025-10-15 19:22:57 +03:00
parent b7ee86ab1d
commit dc4c800ad4
Signed by: egor3f
GPG Key ID: 40482A264AAEC85F
4 changed files with 0 additions and 3625 deletions

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
package binder
import (
"runtime"
"testing"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/parser"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/testutil/fixtures"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/tspath"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/vfs/osvfs"
)
func BenchmarkBind(b *testing.B) {
for _, f := range fixtures.BenchFixtures {
b.Run(f.Name(), func(b *testing.B) {
f.SkipIfNotExist(b)
fileName := tspath.GetNormalizedAbsolutePath(f.Path(), "/")
path := tspath.ToPath(fileName, "/", osvfs.FS().UseCaseSensitiveFileNames())
sourceText := f.ReadFile(b)
compilerOptions := &core.CompilerOptions{Target: core.ScriptTargetESNext, Module: core.ModuleKindNodeNext}
sourceAffecting := compilerOptions.SourceFileAffecting()
parseOptions := ast.SourceFileParseOptions{
FileName: fileName,
Path: path,
CompilerOptions: sourceAffecting,
JSDocParsingMode: ast.JSDocParsingModeParseAll,
}
scriptKind := core.GetScriptKindFromFileName(fileName)
sourceFiles := make([]*ast.SourceFile, b.N)
for i := range b.N {
sourceFiles[i] = parser.ParseSourceFile(parseOptions, sourceText, scriptKind)
}
// The above parses do a lot of work; ensure GC is finished before we start collecting performance data.
// GC must be called twice to allow things to settle.
runtime.GC()
runtime.GC()
b.ResetTimer()
for i := range b.N {
BindSourceFile(sourceFiles[i])
}
})
}
}

View File

@ -1,503 +0,0 @@
package binder
import (
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/diagnostics"
)
type NameResolver struct {
CompilerOptions *core.CompilerOptions
GetSymbolOfDeclaration func(node *ast.Node) *ast.Symbol
Error func(location *ast.Node, message *diagnostics.Message, args ...any) *ast.Diagnostic
Globals ast.SymbolTable
ArgumentsSymbol *ast.Symbol
RequireSymbol *ast.Symbol
GetModuleSymbol func(sourceFile *ast.Node) *ast.Symbol
Lookup func(symbols ast.SymbolTable, name string, 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)
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 {
var result *ast.Symbol
var lastLocation *ast.Node
var lastSelfReferenceLocation *ast.Node
var propertyWithInvalidInitializer *ast.Node
var associatedDeclarationForContainingInitializerOrBindingName *ast.Node
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"
loop:
for location != nil {
if nameIsConst && ast.IsConstAssertion(location) {
// `const` in an `as const` has no symbol, but issues no error because there is no *actual* lookup of the type
// (it refers to the constant type of the expression instead)
return nil
}
if ast.IsModuleOrEnumDeclaration(location) && lastLocation != nil && location.Name() == lastLocation {
// If lastLocation is the name of a namespace or enum, skip the parent since it will have is own locals that could
// conflict.
lastLocation = location
location = location.Parent
}
locals := location.Locals()
// Locals of a source file are not in scope (because they get merged into the global symbol table)
if locals != nil && !ast.IsGlobalSourceFile(location) {
result = r.lookup(locals, name, meaning)
if result != nil {
useResult := true
if ast.IsFunctionLike(location) && lastLocation != nil && lastLocation != location.Body() {
// symbol lookup restrictions for function-like declarations
// - Type parameters of a function are in scope in the entire function declaration, including the parameter
// list and return type. However, local types are only in scope in the function body.
// - parameters are only in the scope of function body
if meaning&result.Flags&ast.SymbolFlagsType != 0 {
useResult = result.Flags&ast.SymbolFlagsTypeParameter != 0 && (lastLocation == location.Type() || ast.IsParameterLike(lastLocation))
}
if meaning&result.Flags&ast.SymbolFlagsVariable != 0 {
// expression inside parameter will lookup as normal variable scope when targeting es2015+
if r.useOuterVariableScopeInParameter(result, location, lastLocation) {
useResult = false
} else if result.Flags&ast.SymbolFlagsFunctionScopedVariable != 0 {
// parameters are visible only inside function body, parameter list and return type
// technically for parameter list case here we might mix parameters and variables declared in function,
// however it is detected separately when checking initializers of parameters
// to make sure that they reference no variables declared after them.
useResult = lastLocation.Kind == ast.KindParameter ||
lastLocation.Flags&ast.NodeFlagsSynthesized != 0 ||
lastLocation == location.Type() && ast.FindAncestor(result.ValueDeclaration, ast.IsParameter) != nil
}
}
} else if location.Kind == ast.KindConditionalType {
// A type parameter declared using 'infer T' in a conditional type is visible only in
// the true branch of the conditional type.
useResult = lastLocation == location.AsConditionalTypeNode().TrueType
}
if useResult {
break loop
}
result = nil
}
}
withinDeferredContext = withinDeferredContext || getIsDeferredContext(location, lastLocation)
switch location.Kind {
case ast.KindSourceFile:
if !ast.IsExternalOrCommonJSModule(location.AsSourceFile()) {
break
}
fallthrough
case ast.KindModuleDeclaration:
moduleExports := r.getSymbolOfDeclaration(location).Exports
if ast.IsSourceFile(location) || (ast.IsModuleDeclaration(location) && location.Flags&ast.NodeFlagsAmbient != 0 && !ast.IsGlobalScopeAugmentation(location)) {
// It's an external module. First see if the module has an export default and if the local
// name of that export default matches.
result = moduleExports[ast.InternalSymbolNameDefault]
if result != nil {
localSymbol := GetLocalSymbolForExportDefault(result)
if localSymbol != nil && result.Flags&meaning != 0 && localSymbol.Name == name {
break loop
}
result = nil
}
// Because of module/namespace merging, a module's exports are in scope,
// yet we never want to treat an export specifier as putting a member in scope.
// Therefore, if the name we find is purely an export specifier, it is not actually considered in scope.
// Two things to note about this:
// 1. We have to check this without calling getSymbol. The problem with calling getSymbol
// on an export specifier is that it might find the export specifier itself, and try to
// resolve it as an alias. This will cause the checker to consider the export specifier
// a circular alias reference when it might not be.
// 2. We check === SymbolFlags.Alias in order to check that the symbol is *purely*
// an alias. If we used &, we'd be throwing out symbols that have non alias aspects,
// which is not the desired behavior.
moduleExport := moduleExports[name]
if moduleExport != nil && moduleExport.Flags == ast.SymbolFlagsAlias && (ast.GetDeclarationOfKind(moduleExport, ast.KindExportSpecifier) != nil || ast.GetDeclarationOfKind(moduleExport, ast.KindNamespaceExport) != nil) {
break
}
}
if name != ast.InternalSymbolNameDefault {
result = r.lookup(moduleExports, name, meaning&ast.SymbolFlagsModuleMember)
if result != nil {
break loop
}
}
case ast.KindEnumDeclaration:
result = r.lookup(r.getSymbolOfDeclaration(location).Exports, name, meaning&ast.SymbolFlagsEnumMember)
if result != nil {
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, r.getSymbolOfDeclaration(location).Name+"."+name)
}
break loop
}
case ast.KindPropertyDeclaration:
if !ast.IsStatic(location) {
ctor := ast.FindConstructorDeclaration(location.Parent)
if ctor != nil && ctor.Locals() != nil {
if r.lookup(ctor.Locals(), name, meaning&ast.SymbolFlagsValue) != nil {
// Remember the property node, it will be used later to report appropriate error
propertyWithInvalidInitializer = location
}
}
}
case ast.KindClassDeclaration, ast.KindClassExpression, ast.KindInterfaceDeclaration:
result = r.lookup(r.getSymbolOfDeclaration(location).Members, name, meaning&ast.SymbolFlagsType)
if result != nil {
if !isTypeParameterSymbolDeclaredInContainer(result, location) {
// ignore type parameters not declared in this container
result = nil
break
}
if lastLocation != nil && ast.IsStatic(lastLocation) {
// TypeScript 1.0 spec (April 2014): 3.4.1
// The scope of a type parameter extends over the entire declaration with which the type
// parameter list is associated, with the exception of static member declarations in classes.
if nameNotFoundMessage != nil {
r.error(originalLocation, diagnostics.Static_members_cannot_reference_class_type_parameters)
}
return nil
}
break loop
}
if ast.IsClassExpression(location) && meaning&ast.SymbolFlagsClass != 0 {
className := location.Name()
if className != nil && name == className.Text() {
result = location.Symbol()
break loop
}
}
case ast.KindExpressionWithTypeArguments:
if lastLocation == location.AsExpressionWithTypeArguments().Expression && ast.IsHeritageClause(location.Parent) && location.Parent.AsHeritageClause().Token == ast.KindExtendsKeyword {
container := location.Parent.Parent
if ast.IsClassLike(container) {
result = r.lookup(r.getSymbolOfDeclaration(container).Members, name, meaning&ast.SymbolFlagsType)
if result != nil {
if nameNotFoundMessage != nil {
r.error(originalLocation, diagnostics.Base_class_expressions_cannot_reference_class_type_parameters)
}
return nil
}
}
}
// It is not legal to reference a class's own type parameters from a computed property name that
// belongs to the class. For example:
//
// function foo<T>() { return '' }
// class C<T> { // <-- Class's own type parameter T
// [foo<T>()]() { } // <-- Reference to T from class's own computed property
// }
case ast.KindComputedPropertyName:
grandparent = location.Parent.Parent
if ast.IsClassLike(grandparent) || ast.IsInterfaceDeclaration(grandparent) {
// A reference to this grandparent's type parameters would be an error
result = r.lookup(r.getSymbolOfDeclaration(grandparent).Members, name, meaning&ast.SymbolFlagsType)
if result != nil {
if nameNotFoundMessage != nil {
r.error(originalLocation, diagnostics.A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type)
}
return nil
}
}
case ast.KindArrowFunction:
// when targeting ES6 or higher there is no 'arguments' in an arrow function
// for lower compile targets the resolved symbol is used to emit an error
if r.CompilerOptions.GetEmitScriptTarget() >= core.ScriptTargetES2015 {
break
}
fallthrough
case ast.KindMethodDeclaration, ast.KindConstructor, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindFunctionDeclaration:
if meaning&ast.SymbolFlagsVariable != 0 && name == "arguments" {
result = r.argumentsSymbol()
break loop
}
case ast.KindFunctionExpression:
if meaning&ast.SymbolFlagsVariable != 0 && name == "arguments" {
result = r.argumentsSymbol()
break loop
}
if meaning&ast.SymbolFlagsFunction != 0 {
functionName := location.AsFunctionExpression().Name()
if functionName != nil && name == functionName.AsIdentifier().Text {
result = location.AsFunctionExpression().Symbol
break loop
}
}
case ast.KindDecorator:
// Decorators are resolved at the class declaration. Resolving at the parameter
// or member would result in looking up locals in the method.
//
// function y() {}
// class C {
// method(@y x, y) {} // <-- decorator y should be resolved at the class declaration, not the parameter.
// }
//
if location.Parent != nil && location.Parent.Kind == ast.KindParameter {
location = location.Parent
}
// function y() {}
// class C {
// @y method(x, y) {} // <-- decorator y should be resolved at the class declaration, not the method.
// }
//
// class Decorators are resolved outside of the class to avoid referencing type parameters of that class.
//
// type T = number;
// declare function y(x: T): any;
// @param(1 as T) // <-- T should resolve to the type alias outside of class C
// class C<T> {}
if location.Parent != nil && (ast.IsClassElement(location.Parent) || location.Parent.Kind == ast.KindClassDeclaration) {
location = location.Parent
}
case ast.KindParameter:
parameterDeclaration := location.AsParameterDeclaration()
if lastLocation != nil && (lastLocation == parameterDeclaration.Initializer ||
lastLocation == parameterDeclaration.Name() && ast.IsBindingPattern(lastLocation)) {
if associatedDeclarationForContainingInitializerOrBindingName == nil {
associatedDeclarationForContainingInitializerOrBindingName = location
}
}
case ast.KindBindingElement:
bindingElement := location.AsBindingElement()
if lastLocation != nil && (lastLocation == bindingElement.Initializer ||
lastLocation == bindingElement.Name() && ast.IsBindingPattern(lastLocation)) {
if ast.IsPartOfParameterDeclaration(location) && associatedDeclarationForContainingInitializerOrBindingName == nil {
associatedDeclarationForContainingInitializerOrBindingName = location
}
}
case ast.KindInferType:
if meaning&ast.SymbolFlagsTypeParameter != 0 {
parameterName := location.AsInferTypeNode().TypeParameter.AsTypeParameter().Name()
if parameterName != nil && name == parameterName.AsIdentifier().Text {
result = location.AsInferTypeNode().TypeParameter.AsTypeParameter().Symbol
break loop
}
}
case ast.KindExportSpecifier:
exportSpecifier := location.AsExportSpecifier()
if lastLocation != nil && lastLocation == exportSpecifier.PropertyName && location.Parent.Parent.AsExportDeclaration().ModuleSpecifier != nil {
location = location.Parent.Parent.Parent
}
}
if isSelfReferenceLocation(location, lastLocation) {
lastSelfReferenceLocation = location
}
lastLocation = location
location = location.Parent
}
// We just climbed up parents looking for the name, meaning that we started in a descendant node of `lastLocation`.
// If `result === lastSelfReferenceLocation.symbol`, that means that we are somewhere inside `lastSelfReferenceLocation` looking up a name, and resolving to `lastLocation` itself.
// That means that this is a self-reference of `lastLocation`, and shouldn't count this when considering whether `lastLocation` is used.
if isUse && result != nil && (lastSelfReferenceLocation == nil || result != lastSelfReferenceLocation.Symbol()) {
if r.SymbolReferenced != nil {
r.SymbolReferenced(result, meaning)
}
}
if result == nil {
if lastLocation != nil &&
lastLocation.Kind == ast.KindSourceFile &&
lastLocation.AsSourceFile().CommonJSModuleIndicator != nil &&
name == "exports" &&
meaning&lastLocation.Symbol().Flags != 0 {
return lastLocation.Symbol()
}
if lastLocation != nil &&
r.GetModuleSymbol != nil &&
lastLocation.Kind == ast.KindSourceFile &&
lastLocation.AsSourceFile().CommonJSModuleIndicator != nil &&
name == "module" &&
originalLocation.Parent != nil &&
ast.IsModuleExportsAccessExpression(originalLocation.Parent) &&
meaning&lastLocation.Symbol().Flags != 0 {
return r.GetModuleSymbol(lastLocation)
}
if !excludeGlobals {
result = r.lookup(r.Globals, name, meaning|ast.SymbolFlagsGlobalLookup)
}
}
if result == nil {
if originalLocation != nil && ast.IsInJSFile(originalLocation) && originalLocation.Parent != nil {
if ast.IsRequireCall(originalLocation.Parent, false /*requireStringLiteralLikeArgument*/) {
return r.RequireSymbol
}
}
}
if nameNotFoundMessage != nil {
if propertyWithInvalidInitializer != nil && r.OnPropertyWithInvalidInitializer != nil && r.OnPropertyWithInvalidInitializer(originalLocation, name, propertyWithInvalidInitializer, result) {
return nil
}
if result == nil {
if r.OnFailedToResolveSymbol != nil {
r.OnFailedToResolveSymbol(originalLocation, name, meaning, nameNotFoundMessage)
}
} else {
if r.OnSuccessfullyResolvedSymbol != nil {
r.OnSuccessfullyResolvedSymbol(originalLocation, result, meaning, lastLocation, associatedDeclarationForContainingInitializerOrBindingName, withinDeferredContext)
}
}
}
return result
}
func (r *NameResolver) useOuterVariableScopeInParameter(result *ast.Symbol, location *ast.Node, lastLocation *ast.Node) bool {
if ast.IsParameter(lastLocation) {
body := location.Body()
if body != nil && result.ValueDeclaration != nil && result.ValueDeclaration.Pos() >= body.Pos() && result.ValueDeclaration.End() <= body.End() {
// check for several cases where we introduce temporaries that require moving the name/initializer of the parameter to the body
// - static field in a class expression
// - optional chaining pre-es2020
// - nullish coalesce pre-es2020
// - spread assignment in binding pattern pre-es2017
target := r.CompilerOptions.GetEmitScriptTarget()
if target >= core.ScriptTargetES2015 {
functionLocation := location
declarationRequiresScopeChange := core.TSUnknown
if r.GetRequiresScopeChangeCache != nil {
declarationRequiresScopeChange = r.GetRequiresScopeChangeCache(functionLocation)
}
if declarationRequiresScopeChange == core.TSUnknown {
declarationRequiresScopeChange = core.IfElse(core.Some(functionLocation.Parameters(), r.requiresScopeChange), core.TSTrue, core.TSFalse)
if r.SetRequiresScopeChangeCache != nil {
r.SetRequiresScopeChangeCache(functionLocation, declarationRequiresScopeChange)
}
}
return declarationRequiresScopeChange != core.TSTrue
}
}
}
return false
}
func (r *NameResolver) requiresScopeChange(node *ast.Node) bool {
d := node.AsParameterDeclaration()
return r.requiresScopeChangeWorker(d.Name()) || d.Initializer != nil && r.requiresScopeChangeWorker(d.Initializer)
}
func (r *NameResolver) requiresScopeChangeWorker(node *ast.Node) bool {
switch node.Kind {
case ast.KindArrowFunction, ast.KindFunctionExpression, ast.KindFunctionDeclaration, ast.KindConstructor:
return false
case ast.KindMethodDeclaration, ast.KindGetAccessor, ast.KindSetAccessor, ast.KindPropertyAssignment:
return r.requiresScopeChangeWorker(node.Name())
case ast.KindPropertyDeclaration:
if ast.HasStaticModifier(node) {
return !r.CompilerOptions.GetEmitStandardClassFields()
}
return r.requiresScopeChangeWorker(node.AsPropertyDeclaration().Name())
default:
if ast.IsNullishCoalesce(node) || ast.IsOptionalChain(node) {
return r.CompilerOptions.GetEmitScriptTarget() < core.ScriptTargetES2020
}
if ast.IsBindingElement(node) && node.AsBindingElement().DotDotDotToken != nil && ast.IsObjectBindingPattern(node.Parent) {
return r.CompilerOptions.GetEmitScriptTarget() < core.ScriptTargetES2017
}
if ast.IsTypeNode(node) {
return false
}
return node.ForEachChild(r.requiresScopeChangeWorker)
}
}
func (r *NameResolver) error(location *ast.Node, message *diagnostics.Message, args ...any) {
if r.Error != nil {
r.Error(location, message, args...)
}
// Default implementation does not report errors
}
func (r *NameResolver) getSymbolOfDeclaration(node *ast.Node) *ast.Symbol {
if r.GetSymbolOfDeclaration != nil {
return r.GetSymbolOfDeclaration(node)
}
// Default implementation does not support merged symbols
return node.Symbol()
}
func (r *NameResolver) lookup(symbols ast.SymbolTable, name string, meaning ast.SymbolFlags) *ast.Symbol {
if r.Lookup != nil {
return r.Lookup(symbols, name, meaning)
}
// Default implementation does not support following aliases or merged symbols
if meaning != 0 {
symbol := symbols[name]
if symbol != nil {
if symbol.Flags&meaning != 0 {
return symbol
}
}
}
return nil
}
func (r *NameResolver) argumentsSymbol() *ast.Symbol {
if r.ArgumentsSymbol == nil {
// Default implementation synthesizes a transient symbol for `arguments`
r.ArgumentsSymbol = &ast.Symbol{Name: "arguments", Flags: ast.SymbolFlagsProperty | ast.SymbolFlagsTransient}
}
return r.ArgumentsSymbol
}
func GetLocalSymbolForExportDefault(symbol *ast.Symbol) *ast.Symbol {
if !isExportDefaultSymbol(symbol) || len(symbol.Declarations) == 0 {
return nil
}
for _, decl := range symbol.Declarations {
localSymbol := decl.LocalSymbol()
if localSymbol != nil {
return localSymbol
}
}
return nil
}
func isExportDefaultSymbol(symbol *ast.Symbol) bool {
return symbol != nil && len(symbol.Declarations) > 0 && ast.HasSyntacticModifier(symbol.Declarations[0], ast.ModifierFlagsDefault)
}
func getIsDeferredContext(location *ast.Node, lastLocation *ast.Node) bool {
if location.Kind != ast.KindArrowFunction && location.Kind != ast.KindFunctionExpression {
// initializers in instance property declaration of class like entities are executed in constructor and thus deferred
// A name is evaluated within the enclosing scope - so it shouldn't count as deferred
return ast.IsTypeQueryNode(location) ||
(ast.IsFunctionLikeDeclaration(location) || location.Kind == ast.KindPropertyDeclaration && !ast.IsStatic(location)) &&
(lastLocation == nil || lastLocation != location.Name())
}
if lastLocation != nil && lastLocation == location.Name() {
return false
}
// generator functions and async functions are not inlined in control flow when immediately invoked
if location.BodyData().AsteriskToken != nil || ast.HasSyntacticModifier(location, ast.ModifierFlagsAsync) {
return true
}
return ast.GetImmediatelyInvokedFunctionExpression(location) == nil
}
func isTypeParameterSymbolDeclaredInContainer(symbol *ast.Symbol, container *ast.Node) bool {
for _, decl := range symbol.Declarations {
if decl.Kind == ast.KindTypeParameter {
parent := decl.Parent
if parent == container {
return true
}
}
}
return false
}
func isSelfReferenceLocation(node *ast.Node, lastLocation *ast.Node) bool {
switch node.Kind {
case ast.KindParameter:
return lastLocation != nil && lastLocation == node.Name()
case ast.KindFunctionDeclaration, ast.KindClassDeclaration, ast.KindInterfaceDeclaration, ast.KindEnumDeclaration,
ast.KindTypeAliasDeclaration, ast.KindJSTypeAliasDeclaration, ast.KindModuleDeclaration: // For `namespace N { N; }`
return true
}
return false
}

View File

@ -1,251 +0,0 @@
package binder
import (
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/diagnostics"
)
type ReferenceResolver interface {
GetReferencedExportContainer(node *ast.IdentifierNode, prefixLocals bool) *ast.Node
GetReferencedImportDeclaration(node *ast.IdentifierNode) *ast.Declaration
GetReferencedValueDeclaration(node *ast.IdentifierNode) *ast.Declaration
GetReferencedValueDeclarations(node *ast.IdentifierNode) []*ast.Declaration
GetElementAccessExpressionName(expression *ast.ElementAccessExpression) string
}
type ReferenceResolverHooks struct {
ResolveName func(location *ast.Node, name string, 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)
}
var _ ReferenceResolver = &referenceResolver{}
type referenceResolver struct {
resolver *NameResolver
options *core.CompilerOptions
hooks ReferenceResolverHooks
}
func NewReferenceResolver(options *core.CompilerOptions, hooks ReferenceResolverHooks) ReferenceResolver {
return &referenceResolver{
options: options,
hooks: hooks,
}
}
func (r *referenceResolver) getResolvedSymbol(node *ast.Node) *ast.Symbol {
if node != nil {
if r.hooks.GetResolvedSymbol != nil {
return r.hooks.GetResolvedSymbol(node)
}
}
return nil
}
func (r *referenceResolver) getMergedSymbol(symbol *ast.Symbol) *ast.Symbol {
if symbol != nil {
if r.hooks.GetMergedSymbol != nil {
return r.hooks.GetMergedSymbol(symbol)
}
return symbol
}
return nil
}
func (r *referenceResolver) getParentOfSymbol(symbol *ast.Symbol) *ast.Symbol {
if symbol != nil {
if r.hooks.GetParentOfSymbol != nil {
return r.hooks.GetParentOfSymbol(symbol)
}
return symbol.Parent
}
return nil
}
func (r *referenceResolver) getSymbolOfDeclaration(declaration *ast.Declaration) *ast.Symbol {
if declaration != nil {
if r.hooks.GetSymbolOfDeclaration != nil {
return r.hooks.GetSymbolOfDeclaration(declaration)
}
return declaration.Symbol()
}
return nil
}
func (r *referenceResolver) getReferencedValueSymbol(reference *ast.IdentifierNode, startInDeclarationContainer bool) *ast.Symbol {
resolvedSymbol := r.getResolvedSymbol(reference)
if resolvedSymbol != nil {
return resolvedSymbol
}
location := reference
if startInDeclarationContainer && reference.Parent != nil && ast.IsDeclaration(reference.Parent) && reference.Parent.Name() == reference {
location = ast.GetDeclarationContainer(reference.Parent)
}
if r.hooks.ResolveName != nil {
return r.hooks.ResolveName(location, reference.Text(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)
}
if r.resolver == nil {
r.resolver = &NameResolver{
CompilerOptions: r.options,
}
}
return r.resolver.Resolve(location, reference.Text(), ast.SymbolFlagsExportValue|ast.SymbolFlagsValue|ast.SymbolFlagsAlias, nil /*nameNotFoundMessage*/, false /*isUse*/, false /*excludeGlobals*/)
}
func (r *referenceResolver) isTypeOnlyAliasDeclaration(symbol *ast.Symbol) bool {
if symbol != nil {
if r.hooks.GetTypeOnlyAliasDeclaration != nil {
return r.hooks.GetTypeOnlyAliasDeclaration(symbol, ast.SymbolFlagsValue) != nil
}
node := r.getDeclarationOfAliasSymbol(symbol)
for node != nil {
switch node.Kind {
case ast.KindImportEqualsDeclaration, ast.KindExportDeclaration:
return node.IsTypeOnly()
case ast.KindImportClause, ast.KindImportSpecifier, ast.KindExportSpecifier:
if node.IsTypeOnly() {
return true
}
node = node.Parent
continue
case ast.KindNamedImports, ast.KindNamedExports:
node = node.Parent
continue
}
break
}
}
return false
}
func (r *referenceResolver) getDeclarationOfAliasSymbol(symbol *ast.Symbol) *ast.Declaration {
return core.FindLast(symbol.Declarations, ast.IsAliasSymbolDeclaration)
}
func (r *referenceResolver) getExportSymbolOfValueSymbolIfExported(symbol *ast.Symbol) *ast.Symbol {
if symbol != nil {
if r.hooks.GetExportSymbolOfValueSymbolIfExported != nil {
return r.hooks.GetExportSymbolOfValueSymbolIfExported(symbol)
}
if symbol.Flags&ast.SymbolFlagsExportValue != 0 && symbol.ExportSymbol != nil {
symbol = symbol.ExportSymbol
}
return r.getMergedSymbol(symbol)
}
return nil
}
func (r *referenceResolver) GetReferencedExportContainer(node *ast.IdentifierNode, prefixLocals bool) *ast.Node /*SourceFile|ModuleDeclaration|EnumDeclaration*/ {
// When resolving the export for the name of a module or enum
// declaration, we need to start resolution at the declaration's container.
// Otherwise, we could incorrectly resolve the export as the
// declaration if it contains an exported member with the same name.
startInDeclarationContainer := node.Parent != nil && (node.Parent.Kind == ast.KindModuleDeclaration || node.Parent.Kind == ast.KindEnumDeclaration) && node == node.Parent.Name()
if symbol := r.getReferencedValueSymbol(node, startInDeclarationContainer); symbol != nil {
if symbol.Flags&ast.SymbolFlagsExportValue != 0 {
// If we reference an exported entity within the same module declaration, then whether
// we prefix depends on the kind of entity. SymbolFlags.ExportHasLocal encompasses all the
// kinds that we do NOT prefix.
exportSymbol := r.getMergedSymbol(symbol.ExportSymbol)
if !prefixLocals && exportSymbol.Flags&ast.SymbolFlagsExportHasLocal != 0 && exportSymbol.Flags&ast.SymbolFlagsVariable == 0 {
return nil
}
symbol = exportSymbol
}
parentSymbol := r.getParentOfSymbol(symbol)
if parentSymbol != nil {
if parentSymbol.Flags&ast.SymbolFlagsValueModule != 0 && parentSymbol.ValueDeclaration != nil && parentSymbol.ValueDeclaration.Kind == ast.KindSourceFile {
symbolFile := parentSymbol.ValueDeclaration.AsSourceFile()
referenceFile := ast.GetSourceFileOfNode(node)
// If `node` accesses an export and that export isn't in the same file, then symbol is a namespace export, so return nil.
symbolIsUmdExport := symbolFile != referenceFile
if symbolIsUmdExport {
return nil
}
return symbolFile.AsNode()
}
isMatchingContainer := func(n *ast.Node) bool {
return (n.Kind == ast.KindModuleDeclaration || n.Kind == ast.KindEnumDeclaration) && r.getSymbolOfDeclaration(n) == parentSymbol
}
if container := ast.FindAncestor(symbol.ValueDeclaration, isMatchingContainer); container != nil {
return container
}
return ast.FindAncestor(node.Parent, isMatchingContainer)
}
}
return nil
}
func (r *referenceResolver) GetReferencedImportDeclaration(node *ast.IdentifierNode) *ast.Declaration {
if symbol := r.getReferencedValueSymbol(node, false /*startInDeclarationContainer*/); symbol != nil {
// We should only get the declaration of an alias if there isn't a local value
// declaration for the symbol
if ast.IsNonLocalAlias(symbol, ast.SymbolFlagsValue /*excludes*/) && !r.isTypeOnlyAliasDeclaration(symbol) {
return r.getDeclarationOfAliasSymbol(symbol)
}
}
return nil
}
func (r *referenceResolver) GetReferencedValueDeclaration(node *ast.IdentifierNode) *ast.Declaration {
if symbol := r.getReferencedValueSymbol(node, false /*startInDeclarationContainer*/); symbol != nil {
return r.getExportSymbolOfValueSymbolIfExported(symbol).ValueDeclaration
}
return nil
}
func (r *referenceResolver) GetReferencedValueDeclarations(node *ast.IdentifierNode) []*ast.Declaration {
var declarations []*ast.Declaration
if symbol := r.getReferencedValueSymbol(node, false /*startInDeclarationContainer*/); symbol != nil {
symbol = r.getExportSymbolOfValueSymbolIfExported(symbol)
for _, declaration := range symbol.Declarations {
switch declaration.Kind {
case ast.KindVariableDeclaration,
ast.KindParameter,
ast.KindBindingElement,
ast.KindPropertyDeclaration,
ast.KindPropertyAssignment,
ast.KindShorthandPropertyAssignment,
ast.KindEnumMember,
ast.KindObjectLiteralExpression,
ast.KindFunctionDeclaration,
ast.KindFunctionExpression,
ast.KindArrowFunction,
ast.KindClassDeclaration,
ast.KindClassExpression,
ast.KindEnumDeclaration,
ast.KindMethodDeclaration,
ast.KindGetAccessor,
ast.KindSetAccessor,
ast.KindModuleDeclaration:
declarations = append(declarations, declaration)
}
}
}
return declarations
}
func (r *referenceResolver) GetElementAccessExpressionName(expression *ast.ElementAccessExpression) string {
if expression != nil {
if r.hooks.GetElementAccessExpressionName != nil {
if name, ok := r.hooks.GetElementAccessExpressionName(expression); ok {
return name
}
}
}
return ""
}