182 lines
5.7 KiB
Go
182 lines
5.7 KiB
Go
package ls
|
|
|
|
import (
|
|
"context"
|
|
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/ast"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/checker"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/collections"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/scanner"
|
|
)
|
|
|
|
func (l *LanguageService) getExportInfos(
|
|
ctx context.Context,
|
|
ch *checker.Checker,
|
|
importingFile *ast.SourceFile,
|
|
preferences *UserPreferences,
|
|
exportMapKey ExportInfoMapKey,
|
|
) []*SymbolExportInfo {
|
|
expInfoMap := NewExportInfoMap(l.GetProgram().GetGlobalTypingsCacheLocation())
|
|
moduleCount := 0
|
|
symbolNameMatch := func(symbolName string) bool {
|
|
return symbolName == exportMapKey.SymbolName
|
|
}
|
|
forEachExternalModuleToImportFrom(
|
|
ch,
|
|
l.GetProgram(),
|
|
preferences,
|
|
// /*useAutoImportProvider*/ true,
|
|
func(moduleSymbol *ast.Symbol, moduleFile *ast.SourceFile, ch *checker.Checker, isFromPackageJson bool) {
|
|
if moduleCount = moduleCount + 1; moduleCount%100 == 0 && ctx.Err() != nil {
|
|
return
|
|
}
|
|
if moduleFile == nil && moduleSymbol.Name != exportMapKey.AmbientModuleName {
|
|
return
|
|
}
|
|
seenExports := collections.Set[string]{}
|
|
defaultInfo := getDefaultLikeExportInfo(moduleSymbol, ch)
|
|
var exportingModuleSymbol *ast.Symbol
|
|
if defaultInfo != nil {
|
|
exportingModuleSymbol = defaultInfo.exportingModuleSymbol
|
|
// Note: I think we shouldn't actually see resolved module symbols here, but weird merges
|
|
// can cause it to happen: see 'completionsImport_mergedReExport.ts'
|
|
if isImportableSymbol(exportingModuleSymbol, ch) {
|
|
expInfoMap.add(
|
|
importingFile.Path(),
|
|
exportingModuleSymbol,
|
|
core.IfElse(defaultInfo.exportKind == ExportKindDefault, ast.InternalSymbolNameDefault, ast.InternalSymbolNameExportEquals),
|
|
moduleSymbol,
|
|
moduleFile,
|
|
defaultInfo.exportKind,
|
|
isFromPackageJson,
|
|
ch,
|
|
symbolNameMatch,
|
|
nil,
|
|
)
|
|
}
|
|
}
|
|
ch.ForEachExportAndPropertyOfModule(moduleSymbol, func(exported *ast.Symbol, key string) {
|
|
if exported != exportingModuleSymbol && isImportableSymbol(exported, ch) && seenExports.AddIfAbsent(key) {
|
|
expInfoMap.add(
|
|
importingFile.Path(),
|
|
exported,
|
|
key,
|
|
moduleSymbol,
|
|
moduleFile,
|
|
ExportKindNamed,
|
|
isFromPackageJson,
|
|
ch,
|
|
symbolNameMatch,
|
|
nil,
|
|
)
|
|
}
|
|
})
|
|
})
|
|
return expInfoMap.get(importingFile.Path(), ch, exportMapKey)
|
|
}
|
|
|
|
func (l *LanguageService) searchExportInfosForCompletions(
|
|
ctx context.Context,
|
|
ch *checker.Checker,
|
|
importingFile *ast.SourceFile,
|
|
preferences *UserPreferences,
|
|
isForImportStatementCompletion bool,
|
|
isRightOfOpenTag bool,
|
|
isTypeOnlyLocation bool,
|
|
lowerCaseTokenText string,
|
|
action func([]*SymbolExportInfo, string, bool, ExportInfoMapKey) []*SymbolExportInfo,
|
|
) {
|
|
symbolNameMatches := map[string]bool{}
|
|
symbolNameMatch := func(symbolName string) bool {
|
|
if !scanner.IsIdentifierText(symbolName, importingFile.LanguageVariant) {
|
|
return false
|
|
}
|
|
if b, ok := symbolNameMatches[symbolName]; ok {
|
|
return b
|
|
}
|
|
if isNonContextualKeyword(scanner.StringToToken(symbolName)) {
|
|
symbolNameMatches[symbolName] = false
|
|
return false
|
|
}
|
|
// Do not try to auto-import something with a lowercase first letter for a JSX tag
|
|
firstChar := rune(symbolName[0])
|
|
if isRightOfOpenTag && (firstChar < 'A' || firstChar > 'Z') {
|
|
symbolNameMatches[symbolName] = false
|
|
return false
|
|
}
|
|
|
|
symbolNameMatches[symbolName] = charactersFuzzyMatchInString(symbolName, lowerCaseTokenText)
|
|
return symbolNameMatches[symbolName]
|
|
}
|
|
flagMatch := func(targetFlags ast.SymbolFlags) bool {
|
|
if !isTypeOnlyLocation && !isForImportStatementCompletion && (targetFlags&ast.SymbolFlagsValue) == 0 {
|
|
return false
|
|
}
|
|
if isTypeOnlyLocation && (targetFlags&(ast.SymbolFlagsModule|ast.SymbolFlagsType) == 0) {
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
expInfoMap := NewExportInfoMap(l.GetProgram().GetGlobalTypingsCacheLocation())
|
|
moduleCount := 0
|
|
forEachExternalModuleToImportFrom(
|
|
ch,
|
|
l.GetProgram(),
|
|
preferences,
|
|
// /*useAutoImportProvider*/ true,
|
|
func(moduleSymbol *ast.Symbol, moduleFile *ast.SourceFile, ch *checker.Checker, isFromPackageJson bool) {
|
|
if moduleCount = moduleCount + 1; moduleCount%100 == 0 && ctx.Err() != nil {
|
|
return
|
|
}
|
|
seenExports := collections.Set[string]{}
|
|
defaultInfo := getDefaultLikeExportInfo(moduleSymbol, ch)
|
|
// Note: I think we shouldn't actually see resolved module symbols here, but weird merges
|
|
// can cause it to happen: see 'completionsImport_mergedReExport.ts'
|
|
if defaultInfo != nil && isImportableSymbol(defaultInfo.exportingModuleSymbol, ch) {
|
|
expInfoMap.add(
|
|
importingFile.Path(),
|
|
defaultInfo.exportingModuleSymbol,
|
|
core.IfElse(defaultInfo.exportKind == ExportKindDefault, ast.InternalSymbolNameDefault, ast.InternalSymbolNameExportEquals),
|
|
moduleSymbol,
|
|
moduleFile,
|
|
defaultInfo.exportKind,
|
|
isFromPackageJson,
|
|
ch,
|
|
symbolNameMatch,
|
|
flagMatch,
|
|
)
|
|
}
|
|
var exportingModuleSymbol *ast.Symbol
|
|
if defaultInfo != nil {
|
|
exportingModuleSymbol = defaultInfo.exportingModuleSymbol
|
|
}
|
|
ch.ForEachExportAndPropertyOfModule(moduleSymbol, func(exported *ast.Symbol, key string) {
|
|
if exported != exportingModuleSymbol && isImportableSymbol(exported, ch) && seenExports.AddIfAbsent(key) {
|
|
expInfoMap.add(
|
|
importingFile.Path(),
|
|
exported,
|
|
key,
|
|
moduleSymbol,
|
|
moduleFile,
|
|
ExportKindNamed,
|
|
isFromPackageJson,
|
|
ch,
|
|
symbolNameMatch,
|
|
flagMatch,
|
|
)
|
|
}
|
|
})
|
|
})
|
|
expInfoMap.search(
|
|
ch,
|
|
importingFile.Path(),
|
|
/*preferCapitalized*/ isRightOfOpenTag,
|
|
func(symbolName string, targetFlags ast.SymbolFlags) bool {
|
|
return symbolNameMatch(symbolName) && flagMatch(targetFlags)
|
|
},
|
|
action,
|
|
)
|
|
}
|