-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added DefinitionAndBoundSpan command #19175
Added DefinitionAndBoundSpan command #19175
Conversation
src/services/services.ts
Outdated
|
||
const sourceFile = getValidSourceFile(fileName); | ||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocCcomment*/ false); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what if this position is within a comment? do you want to verify that it is at least a token? identifier? can you elaborate on the scenario here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added JsDoc for comments, based on our discussion I had changed the design of the command. This is no longer valid.
src/services/services.ts
Outdated
|
||
const sourceFile = getValidSourceFile(fileName); | ||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocCcomment*/ false); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also SpanForPosition
seems a bit vauge to me.. is this TokenSpanAtPosition
or NodeSpanAtPosition
or IdentiiferTokenSpanAtPosition
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer valid as the method has been removed.
@@ -490,6 +490,9 @@ namespace Harness.LanguageService { | |||
getSpanOfEnclosingComment(fileName: string, position: number, onlyMultiLine: boolean): ts.TextSpan { | |||
return unwrapJSONCallResult(this.shim.getSpanOfEnclosingComment(fileName, position, onlyMultiLine)); | |||
} | |||
getSpanForPosition(): ts.TextSpan { | |||
throw new Error("Not supportred on the shim."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typo: "supported" #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
@@ -175,6 +175,7 @@ namespace ts.server { | |||
CommandNames.Configure, | |||
CommandNames.Definition, | |||
CommandNames.DefinitionFull, | |||
CommandNames.DefinitionAndBoundSpan, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I notice that the regular Definition
command has a separate Full version. Does the new command need one as well? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Offline, I think we established that VS Code will probably not consume the new API. If this API is just for VS, should it have "Full" in the name? I think that's how we usually distinguish.
In reply to: 144675978 [](ancestors = 144675978)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Based on a discussion with @mhegazy, I have added the method for the simplified, hence, the "full" has been updated.
src/services/services.ts
Outdated
@@ -1807,6 +1807,15 @@ namespace ts { | |||
return range && createTextSpanFromRange(range); | |||
} | |||
|
|||
function getSpanForPosition(fileName: string, position: number): TextSpan { | |||
synchronizeHostData(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
synchronizeHostData(); [](start = 12, length = 22)
Why synchronize? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No longer valid as the method has been removed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still find the synchronization surprising, but I see that the existing GTD code path does it. #Closed
src/services/services.ts
Outdated
synchronizeHostData(); | ||
|
||
const sourceFile = getValidSourceFile(fileName); | ||
const node = getTouchingPropertyName(sourceFile, position, /*includeJsDocCcomment*/ false); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
false [](start = 96, length = 5)
Do we support GTD in doc comments? (I don't know, but I believe C# does.) #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We do support it, fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🕐
src/server/session.ts
Outdated
}; | ||
} | ||
|
||
private getSimplifiedTextSpan(scriptInfo: ScriptInfo, textSpan: TextSpan): protocol.TextSpan { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getSimplifiedTextSpan [](start = 16, length = 21)
Should this be called in more places? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, there must be some other places where a "simplified textSpan" might be required and this method could be reused. I didn't check for that thou.
In any case, this was refactored to reuse in two different places. line 628 and line 641.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactored for reusability. Also based on a conversation with @mhegazy, changed a couple of method names.
src/services/goToDefinition.ts
Outdated
const comment = findReferenceInPosition(sourceFile.referencedFiles, position); | ||
if (comment && tryResolveScriptReference(program, sourceFile, comment) || findReferenceInPosition(sourceFile.typeReferenceDirectives, position)) { | ||
return { definitions, textSpan: undefined }; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does this block do? Is it for ctrl-click on the file path in a triple-slash reference? Is the TODO still relevant? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This block checks if the position we're searching is within a comment and if that comment is a script reference (triple slash). If true we don't search for a textSpan as the method for that involves a comment parser and complicates a little bit more the process, so undefined is returned instead for now.
The TODO is relevant because of this. Ctrl + Click is going to be enabled with definitions but no textSpan for underlining it is implemented yet.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added bug #19447 for tracking this.
src/harness/fourslash.ts
Outdated
const defs = getDefs(); | ||
let definitions: ts.DefinitionInfo[] | ReadonlyArray<ts.DefinitionInfo>; | ||
let testName: string; | ||
if (this.isDefinitionInfoAndBoundSpan(defs)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be easier to just check isArray
? #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be the same IMO, if anything maybe a little bit harder to read.
First, we need to compare against undefined as well making the comparison a little bit bigger. Second, we'll need to use a type assertion instead of a type guard.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isArray
has the advantage of already existing. And I believe (but don't know) that code flow type inference will make type assertions unnecessary (essentially, any[] & (foo[] | bar) => foo[]). #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, isArray
will narrow the type, but due to the undefined
check it will not be able to do it. In any case, I have added the modification as it's no big deal on readability and like you mentioned already exists and no custom guards are necessary.
private verifyGoToXWorker(endMarkers: string[], getDefs: () => ts.DefinitionInfo[] | ts.DefinitionInfoAndBoundSpan | undefined, startMarkerName?: string) { | ||
const defs = getDefs(); | ||
let definitions: ts.DefinitionInfo[] | ReadonlyArray<ts.DefinitionInfo>; | ||
let testName: string; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testName [](start = 16, length = 8)
It seems like this is actually the name of the API under test. #Closed
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which one is reported when the argument is undefined
? Does it matter?
In reply to: 146340127 [](ancestors = 146340127)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The argument is not going to be undefined only the response from the argument function. It happens when the token doesn't contain a definition.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still have questions.
src/harness/fourslash.ts
Outdated
@@ -584,18 +584,23 @@ namespace FourSlash { | |||
|
|||
public verifyGoToDefinition(arg0: any, endMarkerNames?: string | string[]) { | |||
this.verifyGoToX(arg0, endMarkerNames, () => this.getGoToDefinition()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure why we need two calls here. getGoToDefinitionAndBoundSpan
subsumes the other one, so would be sufficient to do here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would say always use getGoToDefinitionAndBoundSpan
and check the span only if the marker name was provided.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed as suggested.
src/server/session.ts
Outdated
return definitionAndBoundSpan; | ||
} | ||
|
||
private mapFileSpan(definitions: ReadonlyArray<DefinitionInfo>, project: Project): ReadonlyArray<protocol.FileSpan> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider renaming to mapDefinitionInfo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
src/server/session.ts
Outdated
|
||
return { | ||
file: fileName, | ||
...this.toLocationTextSpan(textSpan, scriptInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get the location first, then add the fileName. this way you avoid the extra object allocation per entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed to add the textspan inline
src/server/session.ts
Outdated
return definitions.map(def => this.getFileSpan(def.fileName, def.textSpan, project)); | ||
} | ||
|
||
private getFileSpan(fileName: string, textSpan: TextSpan, project: Project): protocol.FileSpan { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
consider renaming it to toFileSpan
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed.
src/server/session.ts
Outdated
file: fileName, | ||
isWriteAccess, | ||
...this.toLocationTextSpan(textSpan, scriptInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will cause an extra object allocation for every occurrence. we use this on every hover, and do not want to increase the amount of garbage we create.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rollback to be inline.
src/server/session.ts
Outdated
end: scriptInfo.positionToLineOffset(textSpanEnd(edit.span)), | ||
newText: edit.newText ? edit.newText : "" | ||
newText: edit.newText ? edit.newText : "", | ||
...this.toLocationTextSpan(edit.span, scriptInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this one too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rollback to be inline.
src/server/session.ts
Outdated
const bakedItem: protocol.NavtoItem = { | ||
name: navItem.name, | ||
kind: navItem.kind, | ||
file: navItem.fileName, | ||
start, | ||
end, | ||
...this.toLocationTextSpan(navItem.textSpan, scriptInfo) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rollback to be inline.
src/services/goToDefinition.ts
Outdated
// TODO: Add textSpan for triple slash references (file and type). | ||
const comment = findReferenceInPosition(sourceFile.referencedFiles, position); | ||
if (comment && tryResolveScriptReference(program, sourceFile, comment) || findReferenceInPosition(sourceFile.typeReferenceDirectives, position)) { | ||
return { definitions, textSpan: undefined }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would make the textSpan the full line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code has changed so this is no longer valid. The new one has it full line.
src/services/goToDefinition.ts
Outdated
} | ||
|
||
// TODO: Add textSpan for triple slash references (file and type). | ||
const comment = findReferenceInPosition(sourceFile.referencedFiles, position); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i think this should be:
const comment = findReferenceInPosition(sourceFile.referencedFiles, position) || findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Changed.
src/services/goToDefinition.ts
Outdated
|
||
// TODO: Add textSpan for triple slash references (file and type). | ||
const comment = findReferenceInPosition(sourceFile.referencedFiles, position); | ||
if (comment && tryResolveScriptReference(program, sourceFile, comment) || findReferenceInPosition(sourceFile.typeReferenceDirectives, position)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do not think you need to call tryResolveScriptReference here. just make sure definitions is not empty, which you already checked earlier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
…o123/TypeScript into AddDefinitionAndBoundSpan
src/services/goToDefinition.ts
Outdated
} | ||
|
||
let comment = findReferenceInPosition(sourceFile.referencedFiles, position); | ||
if (!comment || !tryResolveScriptReference(program, sourceFile, comment)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do you need the resolve call?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need. Removed the resolve call.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
//cc @mjbvz |
Adds a new command DefinitionAndBoundSpan that will return all definitions for a given position plus the TextSpan.
The purpose of this is for allowing editors to highlight the token being defined.