diff --git a/internal/fourslash/_scripts/failingTests.txt b/internal/fourslash/_scripts/failingTests.txt index 24d93fb43a..a3851e759e 100644 --- a/internal/fourslash/_scripts/failingTests.txt +++ b/internal/fourslash/_scripts/failingTests.txt @@ -168,13 +168,9 @@ TestDoubleUnderscoreCompletions TestEditJsdocType TestExportDefaultClass TestExportDefaultFunction -TestFindAllReferencesDynamicImport1 -TestFindAllReferencesUmdModuleAsGlobalConst -TestFindAllRefsExportEquals TestFindAllRefsForDefaultExport03 TestFindAllRefsForModule TestFindAllRefsModuleDotExports -TestFindAllRefs_importType_typeofImport TestFindReferencesBindingPatternInJsdocNoCrash1 TestFindReferencesBindingPatternInJsdocNoCrash2 TestGenericCombinatorWithConstraints1 @@ -262,7 +258,6 @@ TestJsdocTypedefTag TestJsdocTypedefTag2 TestJsdocTypedefTagNamespace TestJsdocTypedefTagServices -TestJsxFindAllReferencesOnRuntimeImportWithPaths1 TestLetQuickInfoAndCompletionList TestLocalFunction TestMemberListInReopenedEnum @@ -436,7 +431,6 @@ TestQuickinfoWrongComment TestRecursiveInternalModuleImport TestReferencesForStatementKeywords TestReferencesInEmptyFile -TestReferencesIsAvailableThroughGlobalNoCrash TestRegexDetection TestRenameForAliasingExport02 TestRenameFromNodeModulesDep1 @@ -461,7 +455,6 @@ TestTripleSlashRefPathCompletionExtensionsAllowJSFalse TestTripleSlashRefPathCompletionExtensionsAllowJSTrue TestTripleSlashRefPathCompletionHiddenFile TestTripleSlashRefPathCompletionRootdirs -TestTslibFindAllReferencesOnRuntimeImportWithPaths1 TestTsxCompletion14 TestTsxCompletion15 TestTsxCompletionNonTagLessThan diff --git a/internal/fourslash/tests/documentHighlightImportPath_test.go b/internal/fourslash/tests/documentHighlightImportPath_test.go new file mode 100644 index 0000000000..229d8b5a13 --- /dev/null +++ b/internal/fourslash/tests/documentHighlightImportPath_test.go @@ -0,0 +1,21 @@ +package fourslash_test + +import ( + "testing" + + "github.com/microsoft/typescript-go/internal/fourslash" + "github.com/microsoft/typescript-go/internal/testutil" +) + +func TestDocumentHighlightImportPath(t *testing.T) { + t.Parallel() + + defer testutil.RecoverAndFail(t, "Panic on fourslash test") + const content = `// @Filename: /a.ts +export const x = 0; + +// @Filename: /b.ts +import { x } from "[|./a|]";` + f := fourslash.NewFourslash(t, nil /*capabilities*/, content) + f.VerifyBaselineDocumentHighlights(t, nil /*preferences*/, f.Ranges()[0]) +} diff --git a/internal/fourslash/tests/gen/findAllReferencesDynamicImport1_test.go b/internal/fourslash/tests/gen/findAllReferencesDynamicImport1_test.go index a3cbb55949..a6637254e1 100644 --- a/internal/fourslash/tests/gen/findAllReferencesDynamicImport1_test.go +++ b/internal/fourslash/tests/gen/findAllReferencesDynamicImport1_test.go @@ -9,7 +9,7 @@ import ( func TestFindAllReferencesDynamicImport1(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: foo.ts export function foo() { return "foo"; } diff --git a/internal/fourslash/tests/gen/findAllReferencesUmdModuleAsGlobalConst_test.go b/internal/fourslash/tests/gen/findAllReferencesUmdModuleAsGlobalConst_test.go index 2000320574..c0a0b67b70 100644 --- a/internal/fourslash/tests/gen/findAllReferencesUmdModuleAsGlobalConst_test.go +++ b/internal/fourslash/tests/gen/findAllReferencesUmdModuleAsGlobalConst_test.go @@ -9,7 +9,7 @@ import ( func TestFindAllReferencesUmdModuleAsGlobalConst(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: /node_modules/@types/three/three-core.d.ts export class Vector3 { diff --git a/internal/fourslash/tests/gen/findAllRefsExportEquals_test.go b/internal/fourslash/tests/gen/findAllRefsExportEquals_test.go index dfee6a23bf..56070c7f4e 100644 --- a/internal/fourslash/tests/gen/findAllRefsExportEquals_test.go +++ b/internal/fourslash/tests/gen/findAllRefsExportEquals_test.go @@ -9,7 +9,7 @@ import ( func TestFindAllRefsExportEquals(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: /a.ts type /*0*/T = number; diff --git a/internal/fourslash/tests/gen/findAllRefs_importType_typeofImport_test.go b/internal/fourslash/tests/gen/findAllRefs_importType_typeofImport_test.go index 08792f35a8..02e749e266 100644 --- a/internal/fourslash/tests/gen/findAllRefs_importType_typeofImport_test.go +++ b/internal/fourslash/tests/gen/findAllRefs_importType_typeofImport_test.go @@ -9,7 +9,7 @@ import ( func TestFindAllRefs_importType_typeofImport(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: /a.ts export const x = 0; diff --git a/internal/fourslash/tests/gen/jsxFindAllReferencesOnRuntimeImportWithPaths1_test.go b/internal/fourslash/tests/gen/jsxFindAllReferencesOnRuntimeImportWithPaths1_test.go index 21d0c0ed94..83a9c2d649 100644 --- a/internal/fourslash/tests/gen/jsxFindAllReferencesOnRuntimeImportWithPaths1_test.go +++ b/internal/fourslash/tests/gen/jsxFindAllReferencesOnRuntimeImportWithPaths1_test.go @@ -9,7 +9,7 @@ import ( func TestJsxFindAllReferencesOnRuntimeImportWithPaths1(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: project/src/foo.ts import * as x from /**/"@foo/dir/jsx-runtime"; diff --git a/internal/fourslash/tests/gen/referencesIsAvailableThroughGlobalNoCrash_test.go b/internal/fourslash/tests/gen/referencesIsAvailableThroughGlobalNoCrash_test.go index 0ea3c6e347..d7f6558e51 100644 --- a/internal/fourslash/tests/gen/referencesIsAvailableThroughGlobalNoCrash_test.go +++ b/internal/fourslash/tests/gen/referencesIsAvailableThroughGlobalNoCrash_test.go @@ -9,7 +9,7 @@ import ( func TestReferencesIsAvailableThroughGlobalNoCrash(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: /packages/playwright-core/bundles/utils/node_modules/@types/debug/index.d.ts declare var debug: debug.Debug & { debug: debug.Debug; default: debug.Debug }; diff --git a/internal/fourslash/tests/gen/tslibFindAllReferencesOnRuntimeImportWithPaths1_test.go b/internal/fourslash/tests/gen/tslibFindAllReferencesOnRuntimeImportWithPaths1_test.go index 872403577e..0abd8e3240 100644 --- a/internal/fourslash/tests/gen/tslibFindAllReferencesOnRuntimeImportWithPaths1_test.go +++ b/internal/fourslash/tests/gen/tslibFindAllReferencesOnRuntimeImportWithPaths1_test.go @@ -9,7 +9,7 @@ import ( func TestTslibFindAllReferencesOnRuntimeImportWithPaths1(t *testing.T) { t.Parallel() - t.Skip() + defer testutil.RecoverAndFail(t, "Panic on fourslash test") const content = `// @Filename: project/src/foo.ts import * as x from /**/"tslib"; diff --git a/internal/ls/findallreferences.go b/internal/ls/findallreferences.go index d30a4035cf..259e091bbd 100644 --- a/internal/ls/findallreferences.go +++ b/internal/ls/findallreferences.go @@ -621,7 +621,7 @@ func (l *LanguageService) getReferencedSymbolsForNode(ctx context.Context, posit } if moduleSymbol := checker.GetMergedSymbol(resolvedRef.file.Symbol); moduleSymbol != nil { - return getReferencedSymbolsForModule(program, moduleSymbol /*excludeImportTypeOfExportEquals*/, false, sourceFiles, sourceFilesSet) + return getReferencedSymbolsForModule(ctx, program, moduleSymbol /*excludeImportTypeOfExportEquals*/, false, sourceFiles, sourceFilesSet) } // !!! not implemented @@ -669,11 +669,11 @@ func (l *LanguageService) getReferencedSymbolsForNode(ctx context.Context, posit } if symbol.Name == ast.InternalSymbolNameExportEquals { - return getReferencedSymbolsForModule(program, symbol.Parent, false /*excludeImportTypeOfExportEquals*/, sourceFiles, sourceFilesSet) + return getReferencedSymbolsForModule(ctx, program, symbol.Parent, false /*excludeImportTypeOfExportEquals*/, sourceFiles, sourceFilesSet) } moduleReferences := l.getReferencedSymbolsForModuleIfDeclaredBySourceFile(ctx, symbol, program, sourceFiles, checker, options, sourceFilesSet) // !!! cancellationToken - if moduleReferences != nil && symbol.Flags&ast.SymbolFlagsTransient != 0 { + if moduleReferences != nil && symbol.Flags&ast.SymbolFlagsTransient == 0 { return moduleReferences } @@ -696,7 +696,7 @@ func (l *LanguageService) getReferencedSymbolsForModuleIfDeclaredBySourceFile(ct } exportEquals := symbol.Exports[ast.InternalSymbolNameExportEquals] // If exportEquals != nil, we're about to add references to `import("mod")` anyway, so don't double-count them. - moduleReferences := getReferencedSymbolsForModule(program, symbol, exportEquals != nil, sourceFiles, sourceFilesSet) + moduleReferences := getReferencedSymbolsForModule(ctx, program, symbol, exportEquals != nil, sourceFiles, sourceFilesSet) if exportEquals == nil || !sourceFilesSet.Has(moduleSourceFileName) { return moduleReferences } @@ -727,8 +727,7 @@ func getReferencedSymbolsSpecial(node *ast.Node, sourceFiles []*ast.SourceFile) } if ast.IsImportMeta(node.Parent) && node.Parent.Name() == node { - // !!! unimplemented - return nil // getAllReferencesForImportMeta(sourceFiles /*, cancellationToken*/) + return getAllReferencesForImportMeta(sourceFiles) } if node.Kind == ast.KindStaticKeyword && node.Parent.Kind == ast.KindClassStaticBlockDeclaration { @@ -887,6 +886,22 @@ func getReferencesForSuperKeyword(superKeyword *ast.Node) []*SymbolAndEntries { return []*SymbolAndEntries{NewSymbolAndEntries(definitionKindSymbol, nil, searchSpaceNode.Symbol(), references)} } +func getAllReferencesForImportMeta(sourceFiles []*ast.SourceFile) []*SymbolAndEntries { + references := core.FlatMap(sourceFiles, func(sourceFile *ast.SourceFile) []*referenceEntry { + return core.MapNonNil(getPossibleSymbolReferenceNodes(sourceFile, "meta", sourceFile.AsNode()), func(node *ast.Node) *referenceEntry { + parent := node.Parent + if ast.IsImportMeta(parent) { + return newNodeEntry(parent) + } + return nil + }) + }) + if len(references) == 0 { + return nil + } + return []*SymbolAndEntries{{definition: &Definition{Kind: definitionKindKeyword, node: references[0].node}, references: references}} +} + func getAllReferencesForKeyword(sourceFiles []*ast.SourceFile, keywordKind ast.Kind, filterReadOnlyTypeOperator bool) []*SymbolAndEntries { // references is a list of NodeEntry references := core.FlatMap(sourceFiles, func(sourceFile *ast.SourceFile) []*referenceEntry { @@ -958,6 +973,33 @@ func getPossibleSymbolReferencePositions(sourceFile *ast.SourceFile, symbolName return positions } +// findFirstJsxNode recursively searches for the first JSX element, self-closing element, or fragment +func findFirstJsxNode(root *ast.Node) *ast.Node { + var visit func(*ast.Node) *ast.Node + visit = func(node *ast.Node) *ast.Node { + // Check if this is a JSX node we're looking for + switch node.Kind { + case ast.KindJsxElement, ast.KindJsxSelfClosingElement, ast.KindJsxFragment: + return node + } + + // Skip subtree if it doesn't contain JSX + if node.SubtreeFacts()&ast.SubtreeContainsJsx == 0 { + return nil + } + + // Traverse children to find JSX node + var result *ast.Node + node.ForEachChild(func(child *ast.Node) bool { + result = visit(child) + return result != nil // Stop if found + }) + return result + } + + return visit(root) +} + func getReferencesForNonModule(referencedFile *ast.SourceFile, program *compiler.Program) []*referenceEntry { // !!! not implemented return []*referenceEntry{} @@ -975,8 +1017,104 @@ func getMergedAliasedSymbolOfNamespaceExportDeclaration(node *ast.Node, symbol * return nil } -func getReferencedSymbolsForModule(program *compiler.Program, symbol *ast.Symbol, excludeImportTypeOfExportEquals bool, sourceFiles []*ast.SourceFile, sourceFilesSet *collections.Set[string]) []*SymbolAndEntries { - // !!! not implemented +func getReferencedSymbolsForModule(ctx context.Context, program *compiler.Program, symbol *ast.Symbol, excludeImportTypeOfExportEquals bool, sourceFiles []*ast.SourceFile, sourceFilesSet *collections.Set[string]) []*SymbolAndEntries { + debug.Assert(symbol.ValueDeclaration != nil) + + checker, done := program.GetTypeChecker(ctx) + defer done() + + moduleRefs := findModuleReferences(program, sourceFiles, symbol, checker) + references := core.MapNonNil(moduleRefs, func(reference ModuleReference) *referenceEntry { + switch reference.kind { + case ModuleReferenceKindImport: + parent := reference.literal.Parent + if ast.IsLiteralTypeNode(parent) { + importType := parent.Parent + if ast.IsImportTypeNode(importType) { + importTypeNode := importType.AsImportTypeNode() + if excludeImportTypeOfExportEquals && importTypeNode.Qualifier == nil { + return nil + } + } + } + // import("foo") with no qualifier will reference the `export =` of the module, which may be referenced anyway. + return newNodeEntry(reference.literal) + case ModuleReferenceKindImplicit: + // For implicit references (e.g., JSX runtime imports), return the first JSX node, + // the first statement, or the whole file + var rangeNode *ast.Node + + // Skip the JSX search for tslib imports + if reference.literal.Text() != "tslib" { + rangeNode = findFirstJsxNode(reference.referencingFile.AsNode()) + } + + if rangeNode == nil { + if reference.referencingFile.Statements != nil && len(reference.referencingFile.Statements.Nodes) > 0 { + rangeNode = reference.referencingFile.Statements.Nodes[0] + } else { + rangeNode = reference.referencingFile.AsNode() + } + } + return newNodeEntry(rangeNode) + case ModuleReferenceKindReference: + // or + // We can't easily create a proper range entry here without access to LanguageService, + // but we can create a node-based entry pointing to the source file which will be resolved later + return newNodeEntry(reference.referencingFile.AsNode()) + } + return nil + }) + + // Add references to the module declarations themselves + if len(symbol.Declarations) > 0 { + for _, decl := range symbol.Declarations { + switch decl.Kind { + case ast.KindSourceFile: + // Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.) + continue + case ast.KindModuleDeclaration: + if sourceFilesSet.Has(ast.GetSourceFileOfNode(decl).FileName()) { + references = append(references, newNodeEntry(decl.AsModuleDeclaration().Name())) + } + default: + // This may be merged with something. + debug.Assert(symbol.Flags&ast.SymbolFlagsTransient != 0, "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration.") + } + } + } + + // Handle export equals declarations + exported := symbol.Exports[ast.InternalSymbolNameExportEquals] + if exported != nil && len(exported.Declarations) > 0 { + for _, decl := range exported.Declarations { + sourceFile := ast.GetSourceFileOfNode(decl) + if sourceFilesSet.Has(sourceFile.FileName()) { + var node *ast.Node + // At `module.exports = ...`, reference node is `module` + if ast.IsBinaryExpression(decl) && ast.IsPropertyAccessExpression(decl.AsBinaryExpression().Left) { + node = decl.AsBinaryExpression().Left.AsPropertyAccessExpression().Expression + } else if ast.IsExportAssignment(decl) { + // Find the export keyword + node = findChildOfKind(decl, ast.KindExportKeyword, sourceFile) + debug.Assert(node != nil, "Expected to find export keyword") + } else { + node = ast.GetNameOfDeclaration(decl) + if node == nil { + node = decl + } + } + references = append(references, newNodeEntry(node)) + } + } + } + + if len(references) > 0 { + return []*SymbolAndEntries{{ + definition: &Definition{Kind: definitionKindSymbol, symbol: symbol}, + references: references, + }} + } return nil } @@ -1030,6 +1168,24 @@ func getReferenceAtPosition(sourceFile *ast.SourceFile, position int, program *c } // -- Core algorithm for find all references -- +func getSpecialSearchKind(node *ast.Node) string { + if node == nil { + return "none" + } + switch node.Kind { + case ast.KindConstructor, ast.KindConstructorKeyword: + return "constructor" + case ast.KindIdentifier: + if ast.IsClassLike(node.Parent) { + debug.Assert(node.Parent.Name() == node) + return "class" + } + fallthrough + default: + return "none" + } +} + func getReferencedSymbolsForSymbol(originalSymbol *ast.Symbol, node *ast.Node, sourceFiles []*ast.SourceFile, sourceFilesSet *collections.Set[string], checker *checker.Checker, options refOptions) []*SymbolAndEntries { // Core find-all-references algorithm for a normal symbol. @@ -1050,8 +1206,7 @@ func getReferencedSymbolsForSymbol(originalSymbol *ast.Symbol, node *ast.Node, s // state.getReferencesAtExportSpecifier(exportSpecifier.Name(), symbol, exportSpecifier.AsExportSpecifier(), state.createSearch(node, originalSymbol, comingFromUnknown /*comingFrom*/, "", nil), true /*addReferencesHere*/, true /*alwaysGetReferences*/) } else if node != nil && node.Kind == ast.KindDefaultKeyword && symbol.Name == ast.InternalSymbolNameDefault && symbol.Parent != nil { state.addReference(node, symbol, entryKindNone) - // !!! not implemented - // state.searchForImportsOfExport(node, symbol, &ExportInfo{exportingModuleSymbol: symbol.Parent, exportKind: ExportKindDefault}) + state.searchForImportsOfExport(node, symbol, &ExportInfo{exportingModuleSymbol: symbol.Parent, exportKind: ExportKindDefault}) } else { search := state.createSearch(node, symbol, ImpExpKindUnknown /*comingFrom*/, "", state.populateSearchSymbolSet(symbol, node, options.use == referenceUseRename, options.useAliasesForRename, options.implementations)) state.getReferencesInContainerOrFiles(symbol, search) @@ -1080,21 +1235,21 @@ type refSearch struct { includes func(symbol *ast.Symbol) bool } -// type inheritKey struct { -// symbol *ast.Symbol -// parent *ast.Symbol -// } +type inheritKey struct { + symbol *ast.Symbol + parent *ast.Symbol +} type refState struct { sourceFiles []*ast.SourceFile sourceFilesSet *collections.Set[string] - specialSearchKind string // !!! none, constructor, class + specialSearchKind string // "none", "constructor", or "class" checker *checker.Checker // cancellationToken CancellationToken - searchMeaning ast.SemanticMeaning - options refOptions - result []*SymbolAndEntries - // inheritsFromCache map[inheritKey]bool + searchMeaning ast.SemanticMeaning + options refOptions + result []*SymbolAndEntries + inheritsFromCache map[inheritKey]bool seenContainingTypeReferences collections.Set[*ast.Node] // node seen tracker // seenReExportRHS *collections.Set[*ast.Node] // node seen tracker importTracker ImportTracker @@ -1106,11 +1261,11 @@ func newState(sourceFiles []*ast.SourceFile, sourceFilesSet *collections.Set[str return &refState{ sourceFiles: sourceFiles, sourceFilesSet: sourceFilesSet, - specialSearchKind: "none", // !!! other search kinds not implemented + specialSearchKind: getSpecialSearchKind(node), checker: checker, searchMeaning: searchMeaning, options: options, - // inheritsFromCache: map[inheritKey]bool{}, + inheritsFromCache: map[inheritKey]bool{}, // seenReExportRHS: &collections.Set[*ast.Node]{}, symbolToReferences: map[*ast.Symbol]*SymbolAndEntries{}, sourceFileToSeenSymbols: map[*ast.SourceFile]*collections.Set[*ast.Symbol]{}, @@ -1162,7 +1317,6 @@ func (state *refState) createSearch(location *ast.Node, symbol *ast.Symbol, comi } func (state *refState) referenceAdder(searchSymbol *ast.Symbol) func(*ast.Node, entryKind) { - // !!! after find all references is fully implemented, rename this to something like 'getReferenceAdder' symbolAndEntries := state.symbolToReferences[searchSymbol] if symbolAndEntries == nil { symbolAndEntries = NewSymbolAndEntries(definitionKindSymbol, nil, searchSymbol, nil) @@ -1188,6 +1342,120 @@ func (state *refState) addReference(referenceLocation *ast.Node, symbol *ast.Sym } } +func getReferenceEntriesForShorthandPropertyAssignment(node *ast.Node, checker *checker.Checker, addReference func(*ast.Node)) { + refSymbol := checker.GetSymbolAtLocation(node) + if refSymbol == nil || refSymbol.ValueDeclaration == nil { + return + } + shorthandSymbol := checker.GetShorthandAssignmentValueSymbol(refSymbol.ValueDeclaration) + if shorthandSymbol != nil && len(shorthandSymbol.Declarations) > 0 { + for _, declaration := range shorthandSymbol.Declarations { + if getMeaningFromDeclaration(declaration)&ast.SemanticMeaningValue != 0 { + addReference(declaration) + } + } + } +} + +func climbPastPropertyAccess(node *ast.Node) *ast.Node { + if isRightSideOfPropertyAccess(node) { + return node.Parent + } + return node +} + +func isNewExpressionTarget(node *ast.Node) bool { + if node.Parent == nil { + return false + } + return node.Parent.Kind == ast.KindNewExpression && node.Parent.AsNewExpression().Expression == node +} + +func isCallExpressionTarget(node *ast.Node) bool { + if node.Parent == nil { + return false + } + return node.Parent.Kind == ast.KindCallExpression && node.Parent.AsCallExpression().Expression == node +} + +func isMethodOrAccessor(node *ast.Node) bool { + return node.Kind == ast.KindMethodDeclaration || node.Kind == ast.KindGetAccessor || node.Kind == ast.KindSetAccessor +} + +func tryGetClassByExtendingIdentifier(node *ast.Node) *ast.ClassLikeDeclaration { + return ast.TryGetClassExtendingExpressionWithTypeArguments(climbPastPropertyAccess(node).Parent) +} + +func getClassConstructorSymbol(classSymbol *ast.Symbol) *ast.Symbol { + if classSymbol.Members == nil { + return nil + } + return classSymbol.Members[ast.InternalSymbolNameConstructor] +} + +func hasOwnConstructor(classDeclaration *ast.ClassLikeDeclaration) bool { + return getClassConstructorSymbol(classDeclaration.Symbol()) != nil +} + +func findOwnConstructorReferences(classSymbol *ast.Symbol, sourceFile *ast.SourceFile, addNode func(*ast.Node)) { + constructorSymbol := getClassConstructorSymbol(classSymbol) + if constructorSymbol != nil && len(constructorSymbol.Declarations) > 0 { + for _, decl := range constructorSymbol.Declarations { + if decl.Kind == ast.KindConstructor { + if ctrKeyword := findChildOfKind(decl, ast.KindConstructorKeyword, sourceFile); ctrKeyword != nil { + addNode(ctrKeyword) + } + } + } + } + + if classSymbol.Exports != nil { + for _, member := range classSymbol.Exports { + decl := member.ValueDeclaration + if decl != nil && decl.Kind == ast.KindMethodDeclaration { + body := decl.Body() + if body != nil { + forEachDescendantOfKind(body, ast.KindThisKeyword, func(thisKeyword *ast.Node) { + if isNewExpressionTarget(thisKeyword) { + addNode(thisKeyword) + } + }) + } + } + } + } +} + +func findSuperConstructorAccesses(classDeclaration *ast.ClassLikeDeclaration, addNode func(*ast.Node)) { + constructorSymbol := getClassConstructorSymbol(classDeclaration.Symbol()) + if constructorSymbol == nil || len(constructorSymbol.Declarations) == 0 { + return + } + + for _, decl := range constructorSymbol.Declarations { + if decl.Kind == ast.KindConstructor { + body := decl.Body() + if body != nil { + forEachDescendantOfKind(body, ast.KindSuperKeyword, func(node *ast.Node) { + if isCallExpressionTarget(node) { + addNode(node) + } + }) + } + } + } +} + +func forEachDescendantOfKind(node *ast.Node, kind ast.Kind, action func(*ast.Node)) { + node.ForEachChild(func(child *ast.Node) bool { + if child.Kind == kind { + action(child) + } + forEachDescendantOfKind(child, kind, action) + return false + }) +} + func (state *refState) addImplementationReferences(refNode *ast.Node, addRef func(*ast.Node)) { // Check if we found a function/propertyAssignment/method with an implementation or initializer if ast.IsDeclarationName(refNode) && isImplementation(refNode.Parent) { @@ -1201,9 +1469,7 @@ func (state *refState) addImplementationReferences(refNode *ast.Node, addRef fun if refNode.Parent.Kind == ast.KindShorthandPropertyAssignment { // Go ahead and dereference the shorthand assignment by going to its definition - - // !!! not implemented - // getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addRef); + getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addRef) } // Check if the node is within an extends or implements clause @@ -1351,11 +1617,9 @@ func (state *refState) getReferencesAtLocation(sourceFile *ast.SourceFile, posit state.addReference(referenceLocation, relatedSymbol, relatedSymbolKind) } case "constructor": - // !!! not implemented - // state.addConstructorReferences(referenceLocation, sourceFile, search) + state.addConstructorReferences(referenceLocation, relatedSymbol, search, addReferencesHere) case "class": - // !!! not implemented - // state.addClassStaticThisReferences(referenceLocation, search) + state.addClassStaticThisReferences(referenceLocation, relatedSymbol, search, addReferencesHere) } // Use the parent symbol if the location is commonjs require syntax on javascript files only. @@ -1372,6 +1636,78 @@ func (state *refState) getReferencesAtLocation(sourceFile *ast.SourceFile, posit state.getImportOrExportReferences(referenceLocation, referenceSymbol, search) } +func (state *refState) addConstructorReferences(referenceLocation *ast.Node, symbol *ast.Symbol, search *refSearch, addReferencesHere bool) { + if isNewExpressionTarget(referenceLocation) && addReferencesHere { + state.addReference(referenceLocation, symbol, entryKindNone) + } + + pusher := func() func(*ast.Node, entryKind) { + return state.referenceAdder(search.symbol) + } + + if ast.IsClassLike(referenceLocation.Parent) { + // This is the class declaration containing the constructor. + sourceFile := ast.GetSourceFileOfNode(referenceLocation) + findOwnConstructorReferences(search.symbol, sourceFile, func(n *ast.Node) { + pusher()(n, entryKindNone) + }) + } else { + // If this class appears in `extends C`, then the extending class' "super" calls are references. + if classExtending := tryGetClassByExtendingIdentifier(referenceLocation); classExtending != nil { + findSuperConstructorAccesses(classExtending, func(n *ast.Node) { + pusher()(n, entryKindNone) + }) + state.findInheritedConstructorReferences(classExtending) + } + } +} + +func (state *refState) addClassStaticThisReferences(referenceLocation *ast.Node, symbol *ast.Symbol, search *refSearch, addReferencesHere bool) { + if addReferencesHere { + state.addReference(referenceLocation, symbol, entryKindNone) + } + + classLike := referenceLocation.Parent + if state.options.use == referenceUseRename || !ast.IsClassLike(classLike) { + return + } + + addRef := state.referenceAdder(search.symbol) + members := classLike.Members() + if members == nil { + return + } + for _, member := range members { + if !(isMethodOrAccessor(member) && ast.HasStaticModifier(member)) { + continue + } + body := member.Body() + if body != nil { + var cb func(*ast.Node) + cb = func(node *ast.Node) { + if node.Kind == ast.KindThisKeyword { + addRef(node, entryKindNone) + } else if !ast.IsFunctionLike(node) && !ast.IsClassLike(node) { + node.ForEachChild(func(child *ast.Node) bool { + cb(child) + return false + }) + } + } + cb(body) + } + } +} + +func (state *refState) findInheritedConstructorReferences(classDeclaration *ast.ClassLikeDeclaration) { + if hasOwnConstructor(classDeclaration) { + return + } + classSymbol := classDeclaration.Symbol() + search := state.createSearch(nil, classSymbol, ImpExpKindUnknown, "", nil) + state.getReferencesInContainerOrFiles(classSymbol, search) +} + func (state *refState) getImportOrExportReferences(referenceLocation *ast.Node, referenceSymbol *ast.Symbol, search *refSearch) { importOrExport := getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom == ImpExpKindExport) if importOrExport == nil { @@ -1521,9 +1857,7 @@ func (state *refState) getRelatedSymbol(search *refSearch, referenceSymbol *ast. }, func(rootSymbol *ast.Symbol) bool { return !(len(search.parents) != 0 && !core.Some(search.parents, func(parent *ast.Symbol) bool { - return false - // !!! not implemented - // return state.explicitlyInheritsFrom(rootSymbol.Parent, parent) + return state.explicitlyInheritsFrom(rootSymbol.Parent, parent) })) }, ) @@ -1675,3 +2009,34 @@ func (state *refState) searchForName(sourceFile *ast.SourceFile, search *refSear state.getReferencesInSourceFile(sourceFile, search, true /*addReferencesHere*/) } } + +func (state *refState) explicitlyInheritsFrom(symbol *ast.Symbol, parent *ast.Symbol) bool { + if symbol == parent { + return true + } + + // Check cache first + key := inheritKey{symbol: symbol, parent: parent} + if cached, ok := state.inheritsFromCache[key]; ok { + return cached + } + + // Set to false initially to prevent infinite recursion + state.inheritsFromCache[key] = false + + if symbol.Declarations == nil { + return false + } + + inherits := core.Some(symbol.Declarations, func(declaration *ast.Node) bool { + superTypeNodes := getAllSuperTypeNodes(declaration) + return core.Some(superTypeNodes, func(typeReference *ast.TypeNode) bool { + typ := state.checker.GetTypeAtLocation(typeReference.AsNode()) + return typ != nil && typ.Symbol() != nil && state.explicitlyInheritsFrom(typ.Symbol(), parent) + }) + }) + + // Update cache with the actual result + state.inheritsFromCache[key] = inherits + return inherits +} diff --git a/internal/ls/importTracker.go b/internal/ls/importTracker.go index ac434e638d..e4a70d62d7 100644 --- a/internal/ls/importTracker.go +++ b/internal/ls/importTracker.go @@ -6,6 +6,7 @@ import ( "github.com/microsoft/typescript-go/internal/ast" "github.com/microsoft/typescript-go/internal/checker" "github.com/microsoft/typescript-go/internal/collections" + "github.com/microsoft/typescript-go/internal/compiler" "github.com/microsoft/typescript-go/internal/core" "github.com/microsoft/typescript-go/internal/debug" ) @@ -42,6 +43,22 @@ type ImportsResult struct { type ImportTracker func(exportSymbol *ast.Symbol, exportInfo *ExportInfo, isForRename bool) *ImportsResult +type ModuleReferenceKind int32 + +const ( + ModuleReferenceKindImport ModuleReferenceKind = iota + ModuleReferenceKindReference + ModuleReferenceKindImplicit +) + +// ModuleReference represents a reference to a module, either via import, , or implicit reference +type ModuleReference struct { + kind ModuleReferenceKind + literal *ast.Node // for import and implicit kinds (StringLiteralLike) + referencingFile *ast.SourceFile + ref *ast.FileReference // for reference kind +} + // Creates the imports map and returns an ImportTracker that uses it. Call this lazily to avoid calling `getDirectImportsMap` unnecessarily. func createImportTracker(sourceFiles []*ast.SourceFile, sourceFilesSet *collections.Set[string], checker *checker.Checker) ImportTracker { allDirectImports := getDirectImportsMap(sourceFiles, checker) @@ -654,3 +671,58 @@ func symbolNameNoDefault(symbol *ast.Symbol) string { } return "" } + +// findModuleReferences finds all references to a module symbol across the given source files. +// This includes import statements, directives, and implicit references (e.g., JSX runtime imports). +func findModuleReferences(program *compiler.Program, sourceFiles []*ast.SourceFile, searchModuleSymbol *ast.Symbol, checker *checker.Checker) []ModuleReference { + refs := []ModuleReference{} + + for _, referencingFile := range sourceFiles { + searchSourceFile := searchModuleSymbol.ValueDeclaration + if searchSourceFile != nil && searchSourceFile.Kind == ast.KindSourceFile { + // Check directives + for _, ref := range referencingFile.ReferencedFiles { + if program.GetSourceFileFromReference(referencingFile, ref) == searchSourceFile.AsSourceFile() { + refs = append(refs, ModuleReference{ + kind: ModuleReferenceKindReference, + referencingFile: referencingFile, + ref: ref, + }) + } + } + + // Check directives + for _, ref := range referencingFile.TypeReferenceDirectives { + referenced := program.GetResolvedTypeReferenceDirectiveFromTypeReferenceDirective(ref, referencingFile) + if referenced != nil && referenced.ResolvedFileName == searchSourceFile.AsSourceFile().FileName() { + refs = append(refs, ModuleReference{ + kind: ModuleReferenceKindReference, + referencingFile: referencingFile, + ref: ref, + }) + } + } + } + + // Check all imports (including require() calls) + forEachImport(referencingFile, func(importDecl *ast.Node, moduleSpecifier *ast.Node) { + moduleSymbol := checker.GetSymbolAtLocation(moduleSpecifier) + if moduleSymbol == searchModuleSymbol { + if ast.NodeIsSynthesized(importDecl) { + refs = append(refs, ModuleReference{ + kind: ModuleReferenceKindImplicit, + literal: moduleSpecifier, + referencingFile: referencingFile, + }) + } else { + refs = append(refs, ModuleReference{ + kind: ModuleReferenceKindImport, + literal: moduleSpecifier, + }) + } + } + }) + } + + return refs +} diff --git a/testdata/baselines/reference/fourslash/documentHighlights/documentHighlightImportPath.baseline.jsonc b/testdata/baselines/reference/fourslash/documentHighlights/documentHighlightImportPath.baseline.jsonc new file mode 100644 index 0000000000..9990790b26 --- /dev/null +++ b/testdata/baselines/reference/fourslash/documentHighlights/documentHighlightImportPath.baseline.jsonc @@ -0,0 +1,3 @@ +// === documentHighlights === +// === /b.ts === +// import { x } from "/*HIGHLIGHTS*/[|./a|]"; \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesClassExpressionConstructor.baseline.jsonc b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesClassExpressionConstructor.baseline.jsonc index fd11e991f0..7b5c4730a1 100644 --- a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesClassExpressionConstructor.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesClassExpressionConstructor.baseline.jsonc @@ -1,46 +1,52 @@ // === documentHighlights === // === /getOccurrencesClassExpressionConstructor.ts === -// let A = class [|Foo|] { -// /*HIGHLIGHTS*/constructor(); -// constructor(x: number); -// constructor(y: string); -// constructor(a?: any) { -// // --- (line: 6) skipped --- +// let A = class Foo { +// /*HIGHLIGHTS*/[|constructor|](); +// [|constructor|](x: number); +// [|constructor|](y: string); +// [|constructor|](a?: any) { +// } +// } +// +// // --- (line: 9) skipped --- // === documentHighlights === // === /getOccurrencesClassExpressionConstructor.ts === -// let A = class [|Foo|] { -// constructor(); -// /*HIGHLIGHTS*/constructor(x: number); -// constructor(y: string); -// constructor(a?: any) { +// let A = class Foo { +// [|constructor|](); +// /*HIGHLIGHTS*/[|constructor|](x: number); +// [|constructor|](y: string); +// [|constructor|](a?: any) { // } -// // --- (line: 7) skipped --- +// } +// +// // --- (line: 9) skipped --- // === documentHighlights === // === /getOccurrencesClassExpressionConstructor.ts === -// let A = class [|Foo|] { -// constructor(); -// constructor(x: number); -// /*HIGHLIGHTS*/constructor(y: string); -// constructor(a?: any) { +// let A = class Foo { +// [|constructor|](); +// [|constructor|](x: number); +// /*HIGHLIGHTS*/[|constructor|](y: string); +// [|constructor|](a?: any) { // } // } -// // --- (line: 8) skipped --- +// +// // --- (line: 9) skipped --- // === documentHighlights === // === /getOccurrencesClassExpressionConstructor.ts === -// let A = class [|Foo|] { -// constructor(); -// constructor(x: number); -// constructor(y: string); -// /*HIGHLIGHTS*/constructor(a?: any) { +// let A = class Foo { +// [|constructor|](); +// [|constructor|](x: number); +// [|constructor|](y: string); +// /*HIGHLIGHTS*/[|constructor|](a?: any) { // } // } // diff --git a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor.baseline.jsonc b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor.baseline.jsonc index 9931401544..9a0d835004 100644 --- a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor.baseline.jsonc @@ -1,46 +1,52 @@ // === documentHighlights === // === /getOccurrencesConstructor.ts === -// class [|C|] { -// /*HIGHLIGHTS*/constructor(); -// constructor(x: number); -// constructor(y: string, x: number); -// constructor(a?: any, ...r: any[]) { -// // --- (line: 6) skipped --- +// class C { +// /*HIGHLIGHTS*/[|constructor|](); +// [|constructor|](x: number); +// [|constructor|](y: string, x: number); +// [|constructor|](a?: any, ...r: any[]) { +// if (a === undefined && r.length === 0) { +// return; +// } +// // --- (line: 9) skipped --- // === documentHighlights === // === /getOccurrencesConstructor.ts === -// class [|C|] { -// constructor(); -// /*HIGHLIGHTS*/constructor(x: number); -// constructor(y: string, x: number); -// constructor(a?: any, ...r: any[]) { +// class C { +// [|constructor|](); +// /*HIGHLIGHTS*/[|constructor|](x: number); +// [|constructor|](y: string, x: number); +// [|constructor|](a?: any, ...r: any[]) { // if (a === undefined && r.length === 0) { -// // --- (line: 7) skipped --- +// return; +// } +// // --- (line: 9) skipped --- // === documentHighlights === // === /getOccurrencesConstructor.ts === -// class [|C|] { -// constructor(); -// constructor(x: number); -// /*HIGHLIGHTS*/constructor(y: string, x: number); -// constructor(a?: any, ...r: any[]) { +// class C { +// [|constructor|](); +// [|constructor|](x: number); +// /*HIGHLIGHTS*/[|constructor|](y: string, x: number); +// [|constructor|](a?: any, ...r: any[]) { // if (a === undefined && r.length === 0) { // return; -// // --- (line: 8) skipped --- +// } +// // --- (line: 9) skipped --- // === documentHighlights === // === /getOccurrencesConstructor.ts === -// class [|C|] { -// constructor(); -// constructor(x: number); -// constructor(y: string, x: number); -// /*HIGHLIGHTS*/constructor(a?: any, ...r: any[]) { +// class C { +// [|constructor|](); +// [|constructor|](x: number); +// [|constructor|](y: string, x: number); +// /*HIGHLIGHTS*/[|constructor|](a?: any, ...r: any[]) { // if (a === undefined && r.length === 0) { // return; // } diff --git a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor2.baseline.jsonc b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor2.baseline.jsonc index 6f531d7015..786cff277a 100644 --- a/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor2.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/documentHighlights/getOccurrencesConstructor2.baseline.jsonc @@ -1,10 +1,9 @@ // === documentHighlights === // === /getOccurrencesConstructor2.ts === -// --- (line: 10) skipped --- -// } +// --- (line: 11) skipped --- // } // -// class [|D|] { -// /*HIGHLIGHTS*/constructor(public x: number, public y: number) { +// class D { +// /*HIGHLIGHTS*/[|constructor|](public x: number, public y: number) { // } // } \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/constructorFindAllReferences3.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/constructorFindAllReferences3.baseline.jsonc index 9876967d32..79b101605b 100644 --- a/testdata/baselines/reference/fourslash/findAllReferences/constructorFindAllReferences3.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/findAllReferences/constructorFindAllReferences3.baseline.jsonc @@ -1,7 +1,7 @@ // === findAllReferences === // === /constructorFindAllReferences3.ts === -// export class [|C|] { -// /*FIND ALL REFS*/constructor() { } +// export class C { +// /*FIND ALL REFS*/[|constructor|]() { } // public foo() { } // } // diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesDynamicImport1.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesDynamicImport1.baseline.jsonc new file mode 100644 index 0000000000..cf2a41e027 --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesDynamicImport1.baseline.jsonc @@ -0,0 +1,29 @@ +// === findAllReferences === +// === /foo.ts === +// export function foo() { return "foo"; } +// /*FIND ALL REFS*/import("./foo") +// var x = import("./foo") + + + +// === findAllReferences === +// === /foo.ts === +// export function foo() { return "foo"; } +// import("/*FIND ALL REFS*/[|./foo|]") +// var x = import("[|./foo|]") + + + +// === findAllReferences === +// === /foo.ts === +// export function foo() { return "foo"; } +// import("./foo") +// /*FIND ALL REFS*/var x = import("./foo") + + + +// === findAllReferences === +// === /foo.ts === +// export function foo() { return "foo"; } +// import("[|./foo|]") +// var x = import("/*FIND ALL REFS*/[|./foo|]") \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor.baseline.jsonc index 8b8c2b5574..fc41d645a1 100644 --- a/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor.baseline.jsonc @@ -1,114 +1,105 @@ // === findAllReferences === // === /a.ts === -// export class [|C|] { -// /*FIND ALL REFS*/constructor(n: number); -// constructor(); -// constructor(n?: number){} +// export class C { +// /*FIND ALL REFS*/[|constructor|](n: number); +// [|constructor|](); +// [|constructor|](n?: number){} // static f() { // this.f(); -// new this(); +// new [|this|](); // } // } // new [|C|](); -// const D = [|C|]; +// const D = C; // new D(); // === /b.ts === -// import { [|C|] } from "./a"; +// import { C } from "./a"; // new [|C|](); // === /c.ts === -// import { [|C|] } from "./a"; -// class D extends [|C|] { +// import { C } from "./a"; +// class D extends C { // constructor() { -// super(); +// [|super|](); // super.method(); // } // method() { super(); } -// } -// class E implements [|C|] { -// constructor() { super(); } -// } +// // --- (line: 8) skipped --- // === /d.ts === // import * as a from "./a"; -// new a.[|C|](); -// class d extends a.[|C|] { constructor() { super(); } +// new a.C(); +// class d extends a.C { constructor() { [|super|](); } // === findAllReferences === // === /a.ts === -// export class [|C|] { -// constructor(n: number); -// /*FIND ALL REFS*/constructor(); -// constructor(n?: number){} +// export class C { +// [|constructor|](n: number); +// /*FIND ALL REFS*/[|constructor|](); +// [|constructor|](n?: number){} // static f() { // this.f(); -// new this(); +// new [|this|](); // } // } // new [|C|](); -// const D = [|C|]; +// const D = C; // new D(); // === /b.ts === -// import { [|C|] } from "./a"; +// import { C } from "./a"; // new [|C|](); // === /c.ts === -// import { [|C|] } from "./a"; -// class D extends [|C|] { +// import { C } from "./a"; +// class D extends C { // constructor() { -// super(); +// [|super|](); // super.method(); // } // method() { super(); } -// } -// class E implements [|C|] { -// constructor() { super(); } -// } +// // --- (line: 8) skipped --- // === /d.ts === // import * as a from "./a"; -// new a.[|C|](); -// class d extends a.[|C|] { constructor() { super(); } +// new a.C(); +// class d extends a.C { constructor() { [|super|](); } // === findAllReferences === // === /a.ts === -// export class [|C|] { -// constructor(n: number); -// constructor(); -// /*FIND ALL REFS*/constructor(n?: number){} +// export class C { +// [|constructor|](n: number); +// [|constructor|](); +// /*FIND ALL REFS*/[|constructor|](n?: number){} // static f() { // this.f(); -// new this(); +// new [|this|](); // } // } // new [|C|](); -// const D = [|C|]; +// const D = C; // new D(); // === /b.ts === -// import { [|C|] } from "./a"; +// import { C } from "./a"; // new [|C|](); // === /c.ts === -// import { [|C|] } from "./a"; -// class D extends [|C|] { +// import { C } from "./a"; +// class D extends C { // constructor() { -// super(); +// [|super|](); // super.method(); // } // method() { super(); } -// } -// class E implements [|C|] { -// constructor() { super(); } -// } +// // --- (line: 8) skipped --- // === /d.ts === // import * as a from "./a"; -// new a.[|C|](); -// class d extends a.[|C|] { constructor() { super(); } \ No newline at end of file +// new a.C(); +// class d extends a.C { constructor() { [|super|](); } \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor_badOverload.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor_badOverload.baseline.jsonc index 4c9e2f0c7e..9947e3cb5d 100644 --- a/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor_badOverload.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesOfConstructor_badOverload.baseline.jsonc @@ -1,15 +1,15 @@ // === findAllReferences === // === /findAllReferencesOfConstructor_badOverload.ts === -// class [|C|] { -// /*FIND ALL REFS*/constructor(n: number); -// constructor(){} +// class C { +// /*FIND ALL REFS*/[|constructor|](n: number); +// [|constructor|](){} // } // === findAllReferences === // === /findAllReferencesOfConstructor_badOverload.ts === -// class [|C|] { -// constructor(n: number); -// /*FIND ALL REFS*/constructor(){} +// class C { +// [|constructor|](n: number); +// /*FIND ALL REFS*/[|constructor|](){} // } \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesUmdModuleAsGlobalConst.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesUmdModuleAsGlobalConst.baseline.jsonc new file mode 100644 index 0000000000..63169a81fa --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllReferencesUmdModuleAsGlobalConst.baseline.jsonc @@ -0,0 +1,39 @@ +// === findAllReferences === +// === /node_modules/@types/three/index.d.ts === +// export * from "./three-core"; +// export as namespace /*FIND ALL REFS*/[|THREE|]; + + + +// === findAllReferences === +// === /typings/global.d.ts === +// import * as _THREE from '/*FIND ALL REFS*/[|three|]'; +// declare global { +// const THREE: typeof _THREE; +// } + + + +// === findAllReferences === +// === /src/index.ts === +// export const a = {}; +// let v = new [|THREE|].Vector2(); + +// === /typings/global.d.ts === +// import * as _THREE from 'three'; +// declare global { +// const /*FIND ALL REFS*/[|THREE|]: typeof _THREE; +// } + + + +// === findAllReferences === +// === /src/index.ts === +// export const a = {}; +// let v = new /*FIND ALL REFS*/[|THREE|].Vector2(); + +// === /typings/global.d.ts === +// import * as _THREE from 'three'; +// declare global { +// const [|THREE|]: typeof _THREE; +// } \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsClassWithStaticThisAccess.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsClassWithStaticThisAccess.baseline.jsonc index 6a8b752253..62eab0f718 100644 --- a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsClassWithStaticThisAccess.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsClassWithStaticThisAccess.baseline.jsonc @@ -2,9 +2,15 @@ // === /findAllRefsClassWithStaticThisAccess.ts === // class /*FIND ALL REFS*/[|C|] { // static s() { -// this; +// [|this|]; +// } +// static get f() { +// return [|this|]; +// +// function inner() { this; } +// class Inner { x = this; } // } -// // --- (line: 5) skipped --- +// } diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsExportEquals.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsExportEquals.baseline.jsonc new file mode 100644 index 0000000000..3734653d91 --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsExportEquals.baseline.jsonc @@ -0,0 +1,44 @@ +// === findAllReferences === +// === /a.ts === +// type /*FIND ALL REFS*/[|T|] = number; +// export = T; + + + +// === findAllReferences === +// === /a.ts === +// type T = number; +// /*FIND ALL REFS*/[|export|] = T; + +// === /b.ts === +// import T = require("[|./a|]"); + + + +// === findAllReferences === +// === /a.ts === +// type T = number; +// export = /*FIND ALL REFS*/[|T|]; + +// === /b.ts === +// import [|T|] = require("./a"); + + + +// === findAllReferences === +// === /a.ts === +// type [|T|] = number; +// export = [|T|]; + +// === /b.ts === +// import /*FIND ALL REFS*/[|T|] = require("./a"); + + + +// === findAllReferences === +// === /a.ts === +// type [|T|] = number; +// [|export|] = [|T|]; + +// === /b.ts === +// import [|T|] = require("/*FIND ALL REFS*/[|./a|]"); \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsIsDefinition.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsIsDefinition.baseline.jsonc index 40a30963df..b1d0fc3619 100644 --- a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsIsDefinition.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsIsDefinition.baseline.jsonc @@ -73,16 +73,15 @@ // === findAllReferences === // === /findAllRefsIsDefinition.ts === -// --- (line: 15) skipped --- -// interface IFoo { +// --- (line: 16) skipped --- // foo(): void; // } -// class [|Foo|] implements IFoo { -// constructor(n: number) -// constructor() -// /*FIND ALL REFS*/constructor(n: number?) { } +// class Foo implements IFoo { +// [|constructor|](n: number) +// [|constructor|]() +// /*FIND ALL REFS*/[|constructor|](n: number?) { } // foo(): void { } -// static init() { return new this() } +// static init() { return new [|this|]() } // } diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsOfConstructor_withModifier.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsOfConstructor_withModifier.baseline.jsonc index 109ee85c9a..1843c960f8 100644 --- a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsOfConstructor_withModifier.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefsOfConstructor_withModifier.baseline.jsonc @@ -1,6 +1,6 @@ // === findAllReferences === // === /findAllRefsOfConstructor_withModifier.ts === -// class [|X|] { -// public /*FIND ALL REFS*/constructor() {} +// class X { +// public /*FIND ALL REFS*/[|constructor|]() {} // } // var x = new [|X|](); \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/findAllRefs_importType_typeofImport.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefs_importType_typeofImport.baseline.jsonc new file mode 100644 index 0000000000..33e67cb257 --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/findAllRefs_importType_typeofImport.baseline.jsonc @@ -0,0 +1,25 @@ +// === findAllReferences === +// === /b.ts === +// /*FIND ALL REFS*/const x: typeof import("./a") = { x: 0 }; +// const y: typeof import("./a") = { x: 0 }; + + + +// === findAllReferences === +// === /b.ts === +// const x: typeof import("/*FIND ALL REFS*/[|./a|]") = { x: 0 }; +// const y: typeof import("[|./a|]") = { x: 0 }; + + + +// === findAllReferences === +// === /b.ts === +// const x: typeof import("./a") = { x: 0 }; +// /*FIND ALL REFS*/const y: typeof import("./a") = { x: 0 }; + + + +// === findAllReferences === +// === /b.ts === +// const x: typeof import("[|./a|]") = { x: 0 }; +// const y: typeof import("/*FIND ALL REFS*/[|./a|]") = { x: 0 }; \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/jsxFindAllReferencesOnRuntimeImportWithPaths1.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/jsxFindAllReferencesOnRuntimeImportWithPaths1.baseline.jsonc new file mode 100644 index 0000000000..392e16b4b2 --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/jsxFindAllReferencesOnRuntimeImportWithPaths1.baseline.jsonc @@ -0,0 +1,3 @@ +// === findAllReferences === +// === /project/src/foo.ts === +// import * as x from /*FIND ALL REFS*/"[|@foo/dir/jsx-runtime|]"; \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/referencesIsAvailableThroughGlobalNoCrash.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/referencesIsAvailableThroughGlobalNoCrash.baseline.jsonc new file mode 100644 index 0000000000..9ae5412973 --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/referencesIsAvailableThroughGlobalNoCrash.baseline.jsonc @@ -0,0 +1,13 @@ +// === findAllReferences === +// === /packages/playwright-core/bundles/utils/node_modules/@types/debug/index.d.ts === +// declare var [|debug|]: [|debug|].Debug & { debug: [|debug|].Debug; default: [|debug|].Debug }; +// [|export|] = [|debug|]; +// export as namespace debug; +// declare namespace [|debug|] { +// interface Debug { +// coerce: (val: any) => any; +// } +// } + +// === /packages/playwright-core/src/index.ts === +// export const debug: typeof import('[|../bundles/utils/node_modules//*FIND ALL REFS*/@types/debug|]') = require('./utilsBundleImpl').debug; \ No newline at end of file diff --git a/testdata/baselines/reference/fourslash/findAllReferences/renameJsExports03.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/renameJsExports03.baseline.jsonc index e7589d64b6..e6aca1fc85 100644 --- a/testdata/baselines/reference/fourslash/findAllReferences/renameJsExports03.baseline.jsonc +++ b/testdata/baselines/reference/fourslash/findAllReferences/renameJsExports03.baseline.jsonc @@ -9,10 +9,10 @@ // === findAllReferences === // === /a.js === -// class [|A|] { -// /*FIND ALL REFS*/constructor() { } +// class A { +// /*FIND ALL REFS*/[|constructor|]() { } // } -// module.exports = [|A|]; +// module.exports = A; diff --git a/testdata/baselines/reference/fourslash/findAllReferences/tslibFindAllReferencesOnRuntimeImportWithPaths1.baseline.jsonc b/testdata/baselines/reference/fourslash/findAllReferences/tslibFindAllReferencesOnRuntimeImportWithPaths1.baseline.jsonc new file mode 100644 index 0000000000..5276f7a8d4 --- /dev/null +++ b/testdata/baselines/reference/fourslash/findAllReferences/tslibFindAllReferencesOnRuntimeImportWithPaths1.baseline.jsonc @@ -0,0 +1,3 @@ +// === findAllReferences === +// === /project/src/foo.ts === +// import * as x from /*FIND ALL REFS*/"[|tslib|]"; \ No newline at end of file