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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package fourslash_test

import (
"testing"

"github.com/microsoft/typescript-go/internal/fourslash"
"github.com/microsoft/typescript-go/internal/testutil"
)

func TestGoToDefinitionGetterReturnsCallableInterface(t *testing.T) {
t.Parallel()

defer testutil.RecoverAndFail(t, "Panic on fourslash test")
const content = `// @Filename: type.d.ts
export interface Disposable {
dispose(): void;
}

export interface [|Event|]<T> {
[|(|]
listener: (e: T) => any,
thisArgs?: any,
disposables?: Disposable[]
[|)|]: Disposable;
}

export interface TextDocumentChangeEvent<T> {
document: T;
}

export declare class TextDocuments<
T extends {
uri: string;
}
> {
[|get onDidChangeContent()|]: Event<TextDocumentChangeEvent<T>>;
}

export interface TextDocument {
uri: string;
}

// @Filename: index.ts
import { TextDocument, TextDocuments } from "./type";

var documents: TextDocuments<TextDocument>;

documents!.[|onDid/*1*/ChangeContent|]()
`
f, done := fourslash.NewFourslash(t, nil /*capabilities*/, content)
defer done()
f.VerifyBaselineGoToDefinition(t, true, "1")
}
9 changes: 6 additions & 3 deletions internal/ls/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,12 @@ func (l *LanguageService) ProvideDefinition(
declarations := getDeclarationsFromLocation(c, node)
calledDeclaration := tryGetSignatureDeclaration(c, node)
if calledDeclaration != nil {
// If we can resolve a call signature, remove all function-like declarations and add that signature.
nonFunctionDeclarations := core.Filter(slices.Clip(declarations), func(node *ast.Node) bool { return !ast.IsFunctionLike(node) })
declarations = append(nonFunctionDeclarations, calledDeclaration)
// If we can resolve a call signature, remove all function-like declarations (except accessors) and add that signature.
// Accessors are kept because they show where the callable value comes from.
nonFunctionOrAccessorDeclarations := core.Filter(slices.Clip(declarations), func(node *ast.Node) bool {
return !ast.IsFunctionLike(node) || ast.IsAccessor(node)
})
declarations = append(nonFunctionOrAccessorDeclarations, calledDeclaration)
}
return l.createLocationsFromDeclarations(originSelectionRange, clientSupportsLink, declarations), nil
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// === goToDefinition ===
// === /type.d.ts ===
// export interface Disposable {
// dispose(): void;
// }
//
// export interface Event<T> {
// [|(
// listener: (e: T) => any,
// thisArgs?: any,
// disposables?: Disposable[]
// ): Disposable;|]
// }
//
// export interface TextDocumentChangeEvent<T> {
// --- (line: 14) skipped ---

// --- (line: 18) skipped ---
// uri: string;
// }
// > {
// <|get [|onDidChangeContent|](): Event<TextDocumentChangeEvent<T>>;|>
// }
//
// export interface TextDocument {
// --- (line: 26) skipped ---

// === /index.ts ===
// import { TextDocument, TextDocuments } from "./type";
//
// var documents: TextDocuments<TextDocument>;
//
// documents!.[|onDid/*GOTO DEF*/ChangeContent|]()
//