Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 21 additions & 18 deletions internal/fourslash/_scripts/manualTests.txt
Comment thread
jakebailey marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,7 +1,23 @@
autoImportPackageRootPathTypeModule
completionListInClosedFunction05
completionListWithLabel
completionsAtIncompleteObjectLiteralProperty
completionsImport_defaultAndNamedConflict
completionsImport_filteredByPackageJson_ambient
completionsImport_reExportDefault
completionsImport_reexportTransient
completionsSelfDeclaring1
completionsWithDeprecatedTag4
completionsWithStringReplacementMode1
formatOnEnterInComment
getOutliningSpans
importNameCodeFix_uriStyleNodeCoreModules1
importNameCodeFixDefaultExport7
importNameCodeFixOptionalImport0
incrementalParsingWithJsDoc
jsDocFunctionSignatures12
jsDocFunctionSignatures2
jsdocParameterNameCompletion
navigationBarFunctionPrototype
navigationBarFunctionPrototype2
navigationBarFunctionPrototype3
Expand All @@ -16,26 +32,13 @@ navto_excludeLib1
navto_excludeLib2
navto_excludeLib4
navto_serverExcludeLib
outliningForNonCompleteInterfaceDeclaration
outliningHintSpansForFunction
parserCorruptionAfterMapInClass
quickInfoForOverloadOnConst1
renameDefaultKeyword
renameForDefaultExport01
tsxCompletion12
completionsImport_reExportDefault
completionsImport_reexportTransient
jsDocFunctionSignatures2
jsDocFunctionSignatures12
outliningHintSpansForFunction
getOutliningSpans
outliningForNonCompleteInterfaceDeclaration
incrementalParsingWithJsDoc
autoImportPackageRootPathTypeModule
completionListWithLabel
completionsImport_defaultAndNamedConflict
completionsWithStringReplacementMode1
jsdocParameterNameCompletion
semicolonFormattingInsideAComment
semicolonFormattingInsideAStringLiteral
stringLiteralCompletionsInPositionTypedUsingRest
importNameCodeFix_uriStyleNodeCoreModules1
completionsImport_filteredByPackageJson_ambient
importNameCodeFixDefaultExport7
importNameCodeFixOptionalImport0
tsxCompletion12
18 changes: 18 additions & 0 deletions internal/fourslash/test_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ const (

func parseFileContent(fileName string, content string, fileOptions map[string]string) (*testFileWithMarkers, error) {
fileName = tspath.GetNormalizedAbsolutePath(fileName, "/")
content = chompLeadingSpace(content)

// The file content (minus metacharacters) so far
var output strings.Builder
Expand Down Expand Up @@ -466,6 +467,23 @@ func reportError(fileName string, line int, col int, message string) error {
return &fourslashError{fmt.Sprintf("%v (%v,%v): %v", fileName, line, col, message)}
}

func chompLeadingSpace(content string) string {
lines := strings.Split(content, "\n")
for _, line := range lines {
if len(line) > 0 && line[0] != ' ' {
return content
}
}

result := make([]string, len(lines))
for i, line := range lines {
if len(line) > 0 {
result[i] = line[1:]
}
}
return strings.Join(result, "\n")
}

type fourslashError struct {
err string
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ func TestFormatOnEnterInComment(t *testing.T) {
fourslash.SkipIfFailing(t)
t.Parallel()
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = ` /**
* /*1*/
*/`
const content = ` /**
* /*1*/
*/`
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
defer done()
f.GoToMarker(t, "1")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestSemicolonFormattingInsideAComment(t *testing.T) {
fourslash.SkipIfFailing(t)
t.Parallel()
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = ` ///**/`
const content = ` ///**/`
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
defer done()
f.GoToMarker(t, "")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ func TestSemicolonFormattingInsideAStringLiteral(t *testing.T) {
fourslash.SkipIfFailing(t)
Comment thread
jakebailey marked this conversation as resolved.
Outdated
t.Parallel()
defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = ` var x = "string/**/`
const content = ` var x = "string/**/`
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
defer done()
f.GoToMarker(t, "")
Expand Down
54 changes: 42 additions & 12 deletions internal/ls/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/microsoft/typescript-go/internal/checker"
"github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/ls/lsconv"
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
"github.com/microsoft/typescript-go/internal/scanner"
)
Expand All @@ -22,24 +23,31 @@ func (l *LanguageService) ProvideDefinition(
clientSupportsLink := caps.TextDocument.Definition.LinkSupport

program, file := l.getProgramAndFile(documentURI)
node := astnav.GetTouchingPropertyName(file, int(l.converters.LineAndCharacterToPosition(file, position)))
pos := int(l.converters.LineAndCharacterToPosition(file, position))
node := astnav.GetTouchingPropertyName(file, pos)
reference := getReferenceAtPosition(file, pos, program)

if node.Kind == ast.KindSourceFile {
return lsproto.LocationOrLocationsOrDefinitionLinksOrNull{}, nil
}

originSelectionRange := l.createLspRangeFromNode(node, file)
if reference != nil && reference.file != nil {
return l.createDefinitionLocations(originSelectionRange, clientSupportsLink, []*ast.Node{}, reference), nil
}

c, done := program.GetTypeCheckerForFile(ctx, file)
defer done()

if node.Kind == ast.KindOverrideKeyword {
if sym := getSymbolForOverriddenMember(c, node); sym != nil {
return l.createLocationsFromDeclarations(originSelectionRange, clientSupportsLink, sym.Declarations), nil
return l.createDefinitionLocations(originSelectionRange, clientSupportsLink, sym.Declarations, nil /*reference*/), nil
}
}

if ast.IsJumpStatementTarget(node) {
if label := getTargetLabel(node.Parent, node.Text()); label != nil {
return l.createLocationsFromDeclarations(originSelectionRange, clientSupportsLink, []*ast.Node{label}), nil
return l.createDefinitionLocations(originSelectionRange, clientSupportsLink, []*ast.Node{label}, nil /*reference*/), nil
}
}

Expand All @@ -52,7 +60,7 @@ func (l *LanguageService) ProvideDefinition(

if node.Kind == ast.KindReturnKeyword || node.Kind == ast.KindYieldKeyword || node.Kind == ast.KindAwaitKeyword {
if fn := ast.FindAncestor(node, ast.IsFunctionLikeDeclaration); fn != nil {
return l.createLocationsFromDeclarations(originSelectionRange, clientSupportsLink, []*ast.Node{fn}), nil
return l.createDefinitionLocations(originSelectionRange, clientSupportsLink, []*ast.Node{fn}, nil /*reference*/), nil
}
}

Expand All @@ -63,7 +71,7 @@ func (l *LanguageService) ProvideDefinition(
nonFunctionDeclarations := core.Filter(slices.Clip(declarations), func(node *ast.Node) bool { return !ast.IsFunctionLike(node) })
declarations = append(nonFunctionDeclarations, calledDeclaration)
}
return l.createLocationsFromDeclarations(originSelectionRange, clientSupportsLink, declarations), nil
return l.createDefinitionLocations(originSelectionRange, clientSupportsLink, declarations, reference), nil
}

func (l *LanguageService) ProvideTypeDefinition(
Expand Down Expand Up @@ -93,10 +101,10 @@ func (l *LanguageService) ProvideTypeDefinition(
declarations = core.Concatenate(getDeclarationsFromType(typeArgument), declarations)
}
if len(declarations) != 0 {
return l.createLocationsFromDeclarations(originSelectionRange, clientSupportsLink, declarations), nil
return l.createDefinitionLocations(originSelectionRange, clientSupportsLink, declarations, nil /*reference*/), nil
}
if symbol.Flags&ast.SymbolFlagsValue == 0 && symbol.Flags&ast.SymbolFlagsType != 0 {
return l.createLocationsFromDeclarations(originSelectionRange, clientSupportsLink, symbol.Declarations), nil
return l.createDefinitionLocations(originSelectionRange, clientSupportsLink, symbol.Declarations, nil /*reference*/), nil
}
}

Expand All @@ -121,13 +129,34 @@ type fileRange struct {
fileRange core.TextRange
}

func (l *LanguageService) createLocationsFromDeclarations(
func (l *LanguageService) createDefinitionLocations(
originSelectionRange *lsproto.Range,
clientSupportsLink bool,
declarations []*ast.Node,
reference *refInfo,
) lsproto.DefinitionResponse {
locations := make([]*lsproto.LocationLink, 0, len(declarations))
locations := make([]*lsproto.LocationLink, 0)
locationRanges := collections.Set[fileRange]{}

if reference != nil {
targetRange := lsproto.Range{
Start: lsproto.Position{
Line: 0,
Character: 0,
},
End: lsproto.Position{
Line: 0,
Character: 0,
},
}
Comment thread
a-tarasyuk marked this conversation as resolved.
locations = append(locations, &lsproto.LocationLink{
OriginSelectionRange: originSelectionRange,
TargetUri: lsconv.FileNameToDocumentURI(reference.fileName),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could this ever need to go through the source mapper?

TargetRange: targetRange,
TargetSelectionRange: targetRange,
})
}

for _, decl := range declarations {
file := ast.GetSourceFileOfNode(decl)
fileName := file.FileName()
Expand All @@ -146,10 +175,11 @@ func (l *LanguageService) createLocationsFromDeclarations(
})
}
}
if !clientSupportsLink {
return createLocationsFromLinks(locations)

if clientSupportsLink {
return lsproto.LocationOrLocationsOrDefinitionLinksOrNull{DefinitionLinks: &locations}
}
return lsproto.LocationOrLocationsOrDefinitionLinksOrNull{DefinitionLinks: &locations}
return createLocationsFromLinks(locations)
}

func createLocationsFromLinks(links []*lsproto.LocationLink) lsproto.DefinitionResponse {
Expand Down
49 changes: 0 additions & 49 deletions internal/ls/findallreferences.go
Original file line number Diff line number Diff line change
Expand Up @@ -1451,55 +1451,6 @@ func (l *LanguageService) getReferencedSymbolsForModule(ctx context.Context, pro
return []*SymbolAndEntries{}
}

func getReferenceAtPosition(sourceFile *ast.SourceFile, position int, program *compiler.Program) *refInfo {
if referencePath := findReferenceInPosition(sourceFile.ReferencedFiles, position); referencePath != nil {
if file := program.GetSourceFileFromReference(sourceFile, referencePath); file != nil {
return &refInfo{reference: referencePath, fileName: file.FileName(), file: file, unverified: false}
}
return nil
}

if typeReferenceDirective := findReferenceInPosition(sourceFile.TypeReferenceDirectives, position); typeReferenceDirective != nil {
if reference := program.GetResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective, sourceFile); reference != nil {
if file := program.GetSourceFile(reference.ResolvedFileName); file != nil {
return &refInfo{reference: typeReferenceDirective, fileName: file.FileName(), file: file, unverified: false}
}
}
return nil
}

if libReferenceDirective := findReferenceInPosition(sourceFile.LibReferenceDirectives, position); libReferenceDirective != nil {
if file := program.GetLibFileFromReference(libReferenceDirective); file != nil {
return &refInfo{reference: libReferenceDirective, fileName: file.FileName(), file: file, unverified: false}
}
return nil
}

if len(sourceFile.Imports()) == 0 && len(sourceFile.ModuleAugmentations) == 0 {
return nil
}

node := astnav.GetTouchingToken(sourceFile, position)
if !isModuleSpecifierLike(node) || !tspath.IsExternalModuleNameRelative(node.Text()) {
return nil
}
if resolution := program.GetResolvedModuleFromModuleSpecifier(sourceFile, node); resolution != nil {
verifiedFileName := resolution.ResolvedFileName
fileName := resolution.ResolvedFileName
if fileName == "" {
fileName = tspath.ResolvePath(tspath.GetDirectoryPath(sourceFile.FileName()), node.Text())
}
return &refInfo{
file: program.GetSourceFile(fileName),
fileName: fileName,
reference: nil,
unverified: verifiedFileName != "",
}
}

return nil
}

// -- Core algorithm for find all references --
func getSpecialSearchKind(node *ast.Node) string {
if node == nil {
Expand Down
52 changes: 52 additions & 0 deletions internal/ls/utilities.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/microsoft/typescript-go/internal/astnav"
"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"
"github.com/microsoft/typescript-go/internal/jsnum"
Expand All @@ -18,6 +19,7 @@ import (
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
"github.com/microsoft/typescript-go/internal/scanner"
"github.com/microsoft/typescript-go/internal/stringutil"
"github.com/microsoft/typescript-go/internal/tspath"
)

var quoteReplacer = strings.NewReplacer("'", `\'`, `\"`, `"`)
Expand Down Expand Up @@ -1484,6 +1486,56 @@ func toContextRange(textRange *core.TextRange, contextFile *ast.SourceFile, cont
return nil
}

func getReferenceAtPosition(sourceFile *ast.SourceFile, position int, program *compiler.Program) *refInfo {
if referencePath := findReferenceInPosition(sourceFile.ReferencedFiles, position); referencePath != nil {
if file := program.GetSourceFileFromReference(sourceFile, referencePath); file != nil {
return &refInfo{reference: referencePath, fileName: file.FileName(), file: file, unverified: false}
}
return nil
}

if typeReferenceDirective := findReferenceInPosition(sourceFile.TypeReferenceDirectives, position); typeReferenceDirective != nil {
if reference := program.GetResolvedTypeReferenceDirectiveFromTypeReferenceDirective(typeReferenceDirective, sourceFile); reference != nil {
if file := program.GetSourceFile(reference.ResolvedFileName); file != nil {
return &refInfo{reference: typeReferenceDirective, fileName: file.FileName(), file: file, unverified: false}
}
}
return nil
}

if libReferenceDirective := findReferenceInPosition(sourceFile.LibReferenceDirectives, position); libReferenceDirective != nil {
if file := program.GetLibFileFromReference(libReferenceDirective); file != nil {
return &refInfo{reference: libReferenceDirective, fileName: file.FileName(), file: file, unverified: false}
}
return nil
}

if len(sourceFile.Imports()) == 0 && len(sourceFile.ModuleAugmentations) == 0 {
return nil
}

node := astnav.GetTouchingToken(sourceFile, position)
if !isModuleSpecifierLike(node) || !tspath.IsExternalModuleNameRelative(node.Text()) {
return nil
}

if resolution := program.GetResolvedModuleFromModuleSpecifier(sourceFile, node); resolution != nil {
verifiedFileName := resolution.ResolvedFileName
fileName := resolution.ResolvedFileName
if fileName == "" {
fileName = tspath.ResolvePath(tspath.GetDirectoryPath(sourceFile.FileName()), node.Text())
}
return &refInfo{
file: program.GetSourceFile(fileName),
fileName: fileName,
reference: nil,
unverified: verifiedFileName != "",
}
}

return nil
}

func ptrTo[T any](v T) *T {
return &v
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@

// === documentHighlights ===
// === /d.ts ===
// /// <reference path="/*HIGHLIGHTS*/[|./a.ts|]" />
// /// <reference path="/*HIGHLIGHTS*/[|./a.ts|]" />
Loading
Loading