Fix Go to Definition for getters returning callable interfaces
Go to Definition on a getter that returns a callable interface (e.g., documents.onDidChangeContent()) was only showing the call signature, not the getter itself.
interface Event<T> {
(listener: (e: T) => any): Disposable;
}
class TextDocuments {
get onDidChangeContent(): Event<TextDocumentChangeEvent>;
}
// F12 on onDidChangeContent here should show both the Event call signature
// AND the getter declaration
documents.onDidChangeContent();
Changes
- Modified
internal/ls/definition.goto preserve accessor declarations when resolving call signatures - Previously filtered out all function-like declarations; now keeps getters/setters as they indicate the value's origin
- Added fourslash test verifying both definitions appear
Technical Detail
When a call signature is resolved, the existing logic removed all function-like declarations via !ast.IsFunctionLike(node). Since KindGetAccessor is function-like, getters were incorrectly filtered. The fix adds || ast.IsAccessor(node) to the predicate.
Original prompt
This section details on the original issue you should resolve
<issue_title>[lsp] Go to Definition missing getter when property returns callable interface</issue_title> <issue_description>## VS Code Editor Issue
Extension Version: 0.20251203.1
VS Code Version: 1.106.3
Operating System: Windows 11 Pro 24H2 (Build 26100.7171)Steps to Reproduce
- Create two files as shown below (or clone the minimal reproduction repository)
- Open VS Code with TypeScript Go Native enabled
- Open
index.ts- Place cursor on
onDidChangeContentin line 5:documents!.onDidChangeContent()- Execute "Go to Definition" (F12)
index.ts
import { TextDocuments } from "./type"; var documents: TextDocuments; documents!.onDidChangeContent() // ^ Go to Definition heretype.d.ts
export interface Event { (): any; } export declare class TextDocuments { get onDidChangeContent(): Event; }Minimal reproduction repository: https://github.com/imbant/ts-go-definition-bug
Issue
Expected Behavior (Strada / JS Language Server)
![]()
Returns 2 definition locations:
interface Eventcallable signature (line 2 intype.d.ts)get onDidChangeContent()getter definition (line 6 intype.d.ts)Actual Behavior (TypeScript Go Native)
Returns only 1 definition location:
interface Eventcallable signature❌ Missing: The getter
get onDidChangeContent(): EventdefinitionAnalysis
The property
onDidChangeContentis a getter that returns a callable interface (Event). When the code isdocuments!.onDidChangeContent():
onDidChangeContentaccesses the getter()invokes the callable interface returned by the getter"Go to Definition" should return both:
- The callable interface signature being invoked
- The getter property that provides this value</issue_description>
<agent_instructions>index.ts contains:
import { TextDocument, TextDocuments } from "./type"; var documents: TextDocuments<TextDocument>; documents!.onDidChangeContent()types.d.ts contains
export interface Disposable { /** * Dispose this object. */ dispose(): void; } export interface Event<T> { /** * * @param listener The listener function will be called when the event happens. * @param thisArgs The 'this' which will be used when calling the event listener. * @param disposables An array to which a {{IDisposable}} will be added. * @return */ ( listener: (e: T) => any, thisArgs?: any, disposables?: Disposable[] ): Disposable; } export interface TextDocumentChangeEvent<T> { /** * The document that has changed. */ document: T; } export declare class TextDocuments< T extends { uri: string; } > { get onDidChangeContent(): Event<TextDocumentChangeEvent<T>>; } export interface TextDocument { uri: string; }Create a fourslash test for this first, then work on the issue</agent_instructions>
Comments on the Issue (you are @copilot in this section)
- Fixes microsoft/typescript-go#2209
💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.