mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-25 02:58:56 +01:00
Autofill for JSDocs (#20625)
* Add autofill for JSDocs
Adds prototype of autofill for jsdoc comments. For code like:
```js
/**|
function mul(x, y) {
return x * y;
}
```
When you press return, we will complete it to:
```js
/**
*
* @param x
* @param y
*/
function mul(x, y) {
return x * y;
}
```
In Typescript and to:
```js
/**
*
* @param {any} x
* @param {any} y
*/
function mul(x, y) {
return x + y;
}
```
In JavaScript
* Handle revert case better
* Disable on enter when suggestion is visible
This commit is contained in:
@@ -40,6 +40,7 @@ import WorkspaceSymbolProvider from './features/workspaceSymbolProvider';
|
||||
import CodeActionProvider from './features/codeActionProvider';
|
||||
import ReferenceCodeLensProvider from './features/referencesCodeLensProvider';
|
||||
|
||||
import JsDocCompletionHelper from './utils/JsDocCompletionHelper';
|
||||
import * as BuildStatus from './utils/buildStatus';
|
||||
import * as ProjectStatus from './utils/projectStatus';
|
||||
import TypingsStatus, { AtaProgressReporter } from './utils/typingsStatus';
|
||||
@@ -101,6 +102,20 @@ export function activate(context: ExtensionContext): void {
|
||||
client.onVersionStatusClicked();
|
||||
}));
|
||||
|
||||
const jsDocCompletionHelper = new JsDocCompletionHelper(client);
|
||||
context.subscriptions.push(commands.registerCommand('_typescript.tryCompleteJsDoc', () => {
|
||||
const editor = window.activeTextEditor;
|
||||
if (!editor || !editor.selection.isEmpty) {
|
||||
return commands.executeCommand('type', { text: '\n' });
|
||||
}
|
||||
return jsDocCompletionHelper.tryCompleteJsDoc(editor, editor.selection.active).then(didCompleteComment => {
|
||||
if (didCompleteComment) {
|
||||
return;
|
||||
}
|
||||
return commands.executeCommand('type', { text: '\n' });
|
||||
});
|
||||
}));
|
||||
|
||||
const goToProjectConfig = (isTypeScript: boolean) => {
|
||||
const editor = window.activeTextEditor;
|
||||
if (editor) {
|
||||
|
||||
@@ -103,6 +103,7 @@ export interface ITypescriptServiceClient {
|
||||
execute(command: 'navtree', args: Proto.FileRequestArgs, token?: CancellationToken): Promise<Proto.NavTreeResponse>;
|
||||
execute(command: 'getCodeFixes', args: Proto.CodeFixRequestArgs, token?: CancellationToken): Promise<Proto.GetCodeFixesResponse>;
|
||||
execute(command: 'getSupportedCodeFixes', args: null, token?: CancellationToken): Promise<Proto.GetSupportedCodeFixesResponse>;
|
||||
execute(command: 'docCommentTemplate', args: Proto.FileLocationRequestArgs, token?: CancellationToken): Promise<Proto.DocCommandTemplateResponse>;
|
||||
// execute(command: 'compileOnSaveAffectedFileList', args: Proto.CompileOnSaveEmitFileRequestArgs, token?: CancellationToken): Promise<Proto.CompileOnSaveAffectedFileListResponse>;
|
||||
// execute(command: 'compileOnSaveEmitFile', args: Proto.CompileOnSaveEmitFileRequestArgs, token?: CancellationToken): Promise<any>;
|
||||
execute(command: string, args: any, expectedResult: boolean | CancellationToken, token?: CancellationToken): Promise<any>;
|
||||
|
||||
101
extensions/typescript/src/utils/JsDocCompletionHelper.ts
Normal file
101
extensions/typescript/src/utils/JsDocCompletionHelper.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { TextEditor, Position, Range, Selection } from 'vscode';
|
||||
|
||||
import { ITypescriptServiceClient } from '../typescriptService';
|
||||
|
||||
import { FileLocationRequestArgs } from '../protocol';
|
||||
|
||||
export default class JsDocCompletionHelper {
|
||||
|
||||
constructor(
|
||||
private client: ITypescriptServiceClient,
|
||||
) { }
|
||||
|
||||
public tryCompleteJsDoc(editor: TextEditor, position: Position): Thenable<boolean> {
|
||||
const file = this.client.normalizePath(editor.document.uri);
|
||||
if (!file) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
const line = editor.document.lineAt(position.line).text;
|
||||
|
||||
// Ensure line starts with '/**' then cursor
|
||||
const prefix = line.slice(0, position.character).match(/^\s*(\/\*\*+)$/);
|
||||
if (!prefix) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
// Ensure there is no content after the cursor besides possibly the end of the comment
|
||||
const suffix = line.slice(position.character).match(/^\s*\**\/?$/);
|
||||
if (!suffix) {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
const start = position.translate(0, -prefix[1].length);
|
||||
return editor.edit(
|
||||
edits => {
|
||||
edits.delete(new Range(start, new Position(start.line, line.length)));
|
||||
}, {
|
||||
undoStopBefore: true,
|
||||
undoStopAfter: false
|
||||
}
|
||||
).then(removedComment => {
|
||||
if (!removedComment) {
|
||||
// Edit failed, nothing to revert.
|
||||
return false;
|
||||
}
|
||||
|
||||
let cancelled = false;
|
||||
const timer = setTimeout(() => {
|
||||
cancelled = true;
|
||||
}, 250);
|
||||
|
||||
const args: FileLocationRequestArgs = {
|
||||
file: file,
|
||||
line: start.line + 1,
|
||||
offset: start.character + 1
|
||||
};
|
||||
|
||||
return this.client.execute('docCommentTemplate', args)
|
||||
.then(res => {
|
||||
clearTimeout(timer);
|
||||
if (cancelled || !res || !res.body) {
|
||||
return false;
|
||||
}
|
||||
const commentText = res.body.newText;
|
||||
return editor.edit(
|
||||
edits => edits.insert(start, commentText),
|
||||
{ undoStopBefore: false, undoStopAfter: true });
|
||||
}, () => {
|
||||
clearTimeout(timer);
|
||||
return false;
|
||||
})
|
||||
.then(didInsertComment => {
|
||||
if (didInsertComment) {
|
||||
const newCursorPosition = new Position(start.line + 1, editor.document.lineAt(start.line + 1).text.length);
|
||||
editor.selection = new Selection(newCursorPosition, newCursorPosition);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Revert to the original line content and restore position
|
||||
return editor.edit(
|
||||
edits => {
|
||||
edits.insert(start, prefix[1] + suffix[0]);
|
||||
}, {
|
||||
undoStopBefore: false,
|
||||
undoStopAfter: true
|
||||
}
|
||||
).then(() => {
|
||||
editor.selection = new Selection(position, position);
|
||||
return false;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user