mirror of
https://github.com/microsoft/vscode.git
synced 2026-05-03 23:06:49 +01:00
Clean Up JSDoc Completion Provider Implementation (#25981)
* Fix JSDoc Completion Provider
**Bug**
89da6ab81f fixed #11944 by changing how enter works in completion providers. Now if the completion exactly matches the current text, pressing `enter` is not captured by the the suggestion widget. Instead it inserts a new line into the editor. This broke the jsdoc completion provider which uses `''` as a placeholder insertion before calculating the actual insertion upon being accepted. This weird behavior is because of a of the current tsserver api
**Fix**
Change the insert text to a single space instead. This seems to fix this issue in my testing.
* Slightly more elegant fix
This commit is contained in:
@@ -26,7 +26,7 @@ namespace Configuration {
|
||||
|
||||
class JsDocCompletionItem extends CompletionItem {
|
||||
constructor(
|
||||
file: Uri,
|
||||
document: TextDocument,
|
||||
position: Position,
|
||||
shouldGetJSDocFromTSServer: boolean,
|
||||
) {
|
||||
@@ -34,10 +34,19 @@ class JsDocCompletionItem extends CompletionItem {
|
||||
this.detail = localize('typescript.jsDocCompletionItem.documentation', 'JSDoc comment');
|
||||
this.insertText = '';
|
||||
this.sortText = '\0';
|
||||
|
||||
const line = document.lineAt(position.line).text;
|
||||
const prefix = line.slice(0, position.character).match(/\/\**\s*$/);
|
||||
const suffix = line.slice(position.character).match(/^\s*\**\//);
|
||||
const start = position.translate(0, prefix ? -prefix[0].length : 0);
|
||||
this.range = new Range(
|
||||
start,
|
||||
position.translate(0, suffix ? suffix[0].length : 0));
|
||||
|
||||
this.command = {
|
||||
title: 'Try Complete JSDoc',
|
||||
command: TryCompleteJsDocCommand.COMMAND_NAME,
|
||||
arguments: [file, position, shouldGetJSDocFromTSServer]
|
||||
arguments: [document.uri, start, shouldGetJSDocFromTSServer]
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -67,7 +76,7 @@ export class JsDocCompletionProvider implements CompletionItemProvider {
|
||||
const line = document.lineAt(position.line).text;
|
||||
const prefix = line.slice(0, position.character);
|
||||
if (prefix.match(/^\s*$|\/\*\*\s*$|^\s*\/\*\*+\s*$/)) {
|
||||
return [new JsDocCompletionItem(document.uri, position, this.config.enabled)];
|
||||
return [new JsDocCompletionItem(document, position, this.config.enabled)];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
@@ -80,15 +89,15 @@ export class JsDocCompletionProvider implements CompletionItemProvider {
|
||||
export class TryCompleteJsDocCommand {
|
||||
static COMMAND_NAME = '_typeScript.tryCompleteJsDoc';
|
||||
|
||||
constructor(private client: ITypescriptServiceClient) {
|
||||
|
||||
}
|
||||
constructor(
|
||||
private client: ITypescriptServiceClient
|
||||
) { }
|
||||
|
||||
/**
|
||||
* Try to insert a jsdoc comment, using a template provide by typescript
|
||||
* if possible, otherwise falling back to a default comment format.
|
||||
*/
|
||||
public tryCompleteJsDoc(resource: Uri, position: Position, shouldGetJSDocFromTSServer: boolean): Thenable<boolean> {
|
||||
public tryCompleteJsDoc(resource: Uri, start: Position, shouldGetJSDocFromTSServer: boolean): Thenable<boolean> {
|
||||
const file = this.client.normalizePath(resource);
|
||||
if (!file) {
|
||||
return Promise.resolve(false);
|
||||
@@ -99,44 +108,17 @@ export class TryCompleteJsDocCommand {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
return this.prepForDocCompletion(editor, position)
|
||||
.then((start: Position) => {
|
||||
if (!shouldGetJSDocFromTSServer) {
|
||||
return this.tryInsertDefaultDoc(editor, start);
|
||||
}
|
||||
|
||||
return this.tryInsertJsDocFromTemplate(editor, file, start)
|
||||
.then((didInsertFromTemplate: boolean) => {
|
||||
if (didInsertFromTemplate) {
|
||||
return true;
|
||||
}
|
||||
return this.tryInsertDefaultDoc(editor, start);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the area around the position for insertion of the jsdoc.
|
||||
*
|
||||
* Removes any the prefix and suffix of a possible jsdoc
|
||||
*/
|
||||
private prepForDocCompletion(editor: TextEditor, position: Position): Thenable<Position> {
|
||||
const line = editor.document.lineAt(position.line).text;
|
||||
const prefix = line.slice(0, position.character).match(/\/\**\s*$/);
|
||||
const suffix = line.slice(position.character).match(/^\s*\**\//);
|
||||
if (!prefix && !suffix) {
|
||||
// Nothing to remove
|
||||
return Promise.resolve(position);
|
||||
if (!shouldGetJSDocFromTSServer) {
|
||||
return this.tryInsertDefaultDoc(editor, start);
|
||||
}
|
||||
|
||||
const start = position.translate(0, prefix ? -prefix[0].length : 0);
|
||||
return editor.edit(
|
||||
edits => {
|
||||
edits.delete(new Range(start, position.translate(0, suffix ? suffix[0].length : 0)));
|
||||
}, {
|
||||
undoStopBefore: true,
|
||||
undoStopAfter: false
|
||||
}).then(() => start);
|
||||
return this.tryInsertJsDocFromTemplate(editor, file, start)
|
||||
.then((didInsertFromTemplate: boolean) => {
|
||||
if (didInsertFromTemplate) {
|
||||
return true;
|
||||
}
|
||||
return this.tryInsertDefaultDoc(editor, start);
|
||||
});
|
||||
}
|
||||
|
||||
private tryInsertJsDocFromTemplate(editor: TextEditor, file: string, position: Position): Promise<boolean> {
|
||||
|
||||
Reference in New Issue
Block a user