From 48a66ea963bf1c71fa9955444dd7ec68c57e81c1 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Fri, 12 May 2017 17:40:06 -0700 Subject: [PATCH 01/12] Add initial skeleton for providing comment help --- src/features/HelpCompletion.ts | 32 ++++++++++++++++++++++++++++++++ src/main.ts | 4 +++- 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/features/HelpCompletion.ts diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts new file mode 100644 index 0000000000..f6e0c7cd14 --- /dev/null +++ b/src/features/HelpCompletion.ts @@ -0,0 +1,32 @@ +/*--------------------------------------------------------- + * Copyright (C) Microsoft Corporation. All rights reserved. + *--------------------------------------------------------*/ + +import vscode = require("vscode"); +import { IFeature } from "../feature"; +import { TextDocumentChangeEvent, workspace, Disposable } from "vscode"; +import { LanguageClient } from "vscode-languageclient/lib/main"; + +export class HelpCompletionFeature implements IFeature { + private languageClient: LanguageClient; + private triggerCharacters: string; + private disposable: Disposable; + constructor() { + this.triggerCharacters = "#<"; + let subscriptions = []; + workspace.onDidChangeTextDocument(this.onEvent, this, subscriptions); + this.disposable = Disposable.from(...subscriptions); + } + + setLanguageClient(languageclient: LanguageClient) { + this.languageClient = languageclient; + } + + dispose() { + + } + + onEvent(changeEvent: TextDocumentChangeEvent): void { + console.log(`event triggered. change content: ${changeEvent.contentChanges[0].text}`); + } +} diff --git a/src/main.ts b/src/main.ts index 925d98991b..379b9be4e4 100644 --- a/src/main.ts +++ b/src/main.ts @@ -27,6 +27,7 @@ import { FindModuleFeature } from './features/PowerShellFindModule'; import { NewFileOrProjectFeature } from './features/NewFileOrProject'; import { ExtensionCommandsFeature } from './features/ExtensionCommands'; import { DocumentFormatterFeature } from './features/DocumentFormatter'; +import { HelpCompletionFeature } from "./features/HelpCompletion"; // NOTE: We will need to find a better way to deal with the required // PS Editor Services version... @@ -117,7 +118,8 @@ export function activate(context: vscode.ExtensionContext): void { new RemoteFilesFeature(), new DebugSessionFeature(sessionManager), new PickPSHostProcessFeature(), - new SpecifyScriptArgsFeature(context) + new SpecifyScriptArgsFeature(context), + new HelpCompletionFeature() ]; sessionManager.setExtensionFeatures(extensionFeatures); From ceb0b2fec8def9f2c8ef08665e35ccb92b08d542 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Fri, 12 May 2017 21:13:24 -0700 Subject: [PATCH 02/12] Implement a very basic comment help provider --- src/features/HelpCompletion.ts | 69 ++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index f6e0c7cd14..b9ad292ec3 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -4,17 +4,34 @@ import vscode = require("vscode"); import { IFeature } from "../feature"; -import { TextDocumentChangeEvent, workspace, Disposable } from "vscode"; -import { LanguageClient } from "vscode-languageclient/lib/main"; +import { TextDocumentChangeEvent, workspace, Disposable, Position } from "vscode"; +import { LanguageClient, RequestType } from "vscode-languageclient"; + +export namespace CommentHelpRequest { + export const type = new RequestType("powerShell/getCommentHelp"); +} + +interface CommentHelpRequestParams { + documentUri: string; + triggerPosition: Position; +} + +interface CommentHelpRequestResult { + content: string[]; +} + +enum SearchState { Searching, Locked, Found }; export class HelpCompletionFeature implements IFeature { private languageClient: LanguageClient; private triggerCharacters: string; private disposable: Disposable; + private searchState: SearchState; constructor() { this.triggerCharacters = "#<"; let subscriptions = []; workspace.onDidChangeTextDocument(this.onEvent, this, subscriptions); + this.searchState = SearchState.Searching; this.disposable = Disposable.from(...subscriptions); } @@ -23,10 +40,54 @@ export class HelpCompletionFeature implements IFeature { } dispose() { - + this.disposable.dispose(); } onEvent(changeEvent: TextDocumentChangeEvent): void { - console.log(`event triggered. change content: ${changeEvent.contentChanges[0].text}`); + let text = changeEvent.contentChanges[0].text; + switch (this.searchState) { + case SearchState.Searching: + if (text.length === 1 && text[0] === this.triggerCharacters[0]) { + this.searchState = SearchState.Locked; + } + break; + + case SearchState.Locked: + if (text.length === 1 && text[0] === this.triggerCharacters[1]) { + this.searchState = SearchState.Found; + } + break; + } + + let r = changeEvent.contentChanges[0].range; + console.log(`Search State: ${this.searchState.toString()}; Range: (${r.start.line}, ${r.start.character}), (${r.end.line}, ${r.end.character})`); + if (this.searchState === SearchState.Found) { + this.searchState = SearchState.Searching; + if (this.languageClient) { + let change = changeEvent.contentChanges[0]; + let triggerStartPos = change.range.start; + let triggerEndPos = change.range.end; + let doc = changeEvent.document; + this.languageClient.sendRequest( + CommentHelpRequest.type, + { + documentUri: changeEvent.document.uri.toString(), + triggerPosition: triggerStartPos + }).then(result => { + let content = result.content; + if (content === undefined) { + return; + } + + // todo allow "##" as trigger characters + // todo remove the new line after help block + // todo get the eol character programmatically or let the server return one whole string + let editor = vscode.window.activeTextEditor; + let replaceRange = new vscode.Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); + let text = content.join("\r\n"); + editor.edit(editbuilder => editbuilder.replace(replaceRange, text)); + }); + } + } } } From 734a55da0c29c5c7a3e923eed052e948b00817de Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Sun, 14 May 2017 10:59:36 -0700 Subject: [PATCH 03/12] Add option for comment style in comment help --- src/features/HelpCompletion.ts | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index b9ad292ec3..c960ccb58b 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -14,6 +14,7 @@ export namespace CommentHelpRequest { interface CommentHelpRequestParams { documentUri: string; triggerPosition: Position; + blockComment: boolean; } interface CommentHelpRequestResult { @@ -23,12 +24,20 @@ interface CommentHelpRequestResult { enum SearchState { Searching, Locked, Found }; export class HelpCompletionFeature implements IFeature { + private readonly triggerCharactersBlockComment: string; + private readonly triggerCharactersLineComment: string; + private triggerCharactersFound: string; private languageClient: LanguageClient; - private triggerCharacters: string; private disposable: Disposable; private searchState: SearchState; + private get isBlockComment(): boolean { + return this.triggerCharactersFound !== undefined && + this.triggerCharactersFound === this.triggerCharactersBlockComment; + } + constructor() { - this.triggerCharacters = "#<"; + this.triggerCharactersBlockComment = "#<"; + this.triggerCharactersLineComment = "##"; let subscriptions = []; workspace.onDidChangeTextDocument(this.onEvent, this, subscriptions); this.searchState = SearchState.Searching; @@ -47,15 +56,20 @@ export class HelpCompletionFeature implements IFeature { let text = changeEvent.contentChanges[0].text; switch (this.searchState) { case SearchState.Searching: - if (text.length === 1 && text[0] === this.triggerCharacters[0]) { + if (text.length === 1 && text[0] === this.triggerCharactersBlockComment[0]) { this.searchState = SearchState.Locked; } break; case SearchState.Locked: - if (text.length === 1 && text[0] === this.triggerCharacters[1]) { + if (text.length === 1 && + (text[0] === (this.triggerCharactersFound = this.triggerCharactersBlockComment)[1] || + text[0] === (this.triggerCharactersFound = this.triggerCharactersLineComment)[1])) { this.searchState = SearchState.Found; } + else { + this.searchState = SearchState.Searching; + } break; } @@ -72,7 +86,8 @@ export class HelpCompletionFeature implements IFeature { CommentHelpRequest.type, { documentUri: changeEvent.document.uri.toString(), - triggerPosition: triggerStartPos + triggerPosition: triggerStartPos, + blockComment: this.isBlockComment }).then(result => { let content = result.content; if (content === undefined) { From 07501ae3d4b5ba086e7651f054b66f3201406b4d Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Mon, 15 May 2017 13:52:51 -0700 Subject: [PATCH 04/12] Change trigger characters from "#<" to "<#" --- src/features/HelpCompletion.ts | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index c960ccb58b..07078b09c6 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -36,7 +36,7 @@ export class HelpCompletionFeature implements IFeature { } constructor() { - this.triggerCharactersBlockComment = "#<"; + this.triggerCharactersBlockComment = "<#"; this.triggerCharactersLineComment = "##"; let subscriptions = []; workspace.onDidChangeTextDocument(this.onEvent, this, subscriptions); @@ -44,8 +44,8 @@ export class HelpCompletionFeature implements IFeature { this.disposable = Disposable.from(...subscriptions); } - setLanguageClient(languageclient: LanguageClient) { - this.languageClient = languageclient; + setLanguageClient(languageClient: LanguageClient) { + this.languageClient = languageClient; } dispose() { @@ -56,15 +56,20 @@ export class HelpCompletionFeature implements IFeature { let text = changeEvent.contentChanges[0].text; switch (this.searchState) { case SearchState.Searching: - if (text.length === 1 && text[0] === this.triggerCharactersBlockComment[0]) { - this.searchState = SearchState.Locked; + if (text.length === 1) { + if (text[0] === this.triggerCharactersBlockComment[0]) { + this.searchState = SearchState.Locked; + this.triggerCharactersFound = this.triggerCharactersBlockComment; + } + else if (text[0] === this.triggerCharactersLineComment[0]) { + this.searchState = SearchState.Locked; + this.triggerCharactersFound = this.triggerCharactersLineComment; + } } break; case SearchState.Locked: - if (text.length === 1 && - (text[0] === (this.triggerCharactersFound = this.triggerCharactersBlockComment)[1] || - text[0] === (this.triggerCharactersFound = this.triggerCharactersLineComment)[1])) { + if (text.length === 1 && text[0] === this.triggerCharactersFound[1]) { this.searchState = SearchState.Found; } else { @@ -89,18 +94,22 @@ export class HelpCompletionFeature implements IFeature { triggerPosition: triggerStartPos, blockComment: this.isBlockComment }).then(result => { + if (result === undefined) { + return; + } + let content = result.content; if (content === undefined) { return; } - // todo allow "##" as trigger characters // todo remove the new line after help block // todo get the eol character programmatically or let the server return one whole string + // todo add indentation level to the help content let editor = vscode.window.activeTextEditor; let replaceRange = new vscode.Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); let text = content.join("\r\n"); - editor.edit(editbuilder => editbuilder.replace(replaceRange, text)); + editor.edit(editBuilder => editBuilder.replace(replaceRange, text)); }); } } From 3852f6a6279d4d0b289a528db52257900a87a158 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Mon, 15 May 2017 14:01:56 -0700 Subject: [PATCH 05/12] Trim the last empty line from comment help block --- src/features/HelpCompletion.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index 07078b09c6..a5dca77b5c 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -103,12 +103,13 @@ export class HelpCompletionFeature implements IFeature { return; } - // todo remove the new line after help block // todo get the eol character programmatically or let the server return one whole string // todo add indentation level to the help content let editor = vscode.window.activeTextEditor; let replaceRange = new vscode.Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); - let text = content.join("\r\n"); + + // Trim the last empty line and join the strings. + let text = content.slice(0, -1).join("\r\n"); editor.edit(editBuilder => editBuilder.replace(replaceRange, text)); }); } From c64bff11991cf3d97b28a4632f8708420b3c407b Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Mon, 15 May 2017 15:05:41 -0700 Subject: [PATCH 06/12] Bump vscode engine's version to 1.12.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 37f7fac39f..604daabc17 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "publisher": "ms-vscode", "description": "Develop PowerShell scripts in Visual Studio Code!", "engines": { - "vscode": "^1.10.0" + "vscode": "^1.12.0" }, "license": "SEE LICENSE IN LICENSE.txt", "homepage": "https://github.com/PowerShell/vscode-powershell/blob/master/README.md", From 22eb1c70abc264d122aea0a1b114b39f4d4b933f Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Mon, 15 May 2017 15:09:51 -0700 Subject: [PATCH 07/12] Bump vscode npm package version to 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 604daabc17..d9e52351fe 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@types/node": "^6.0.40", "typescript": "^2.0.3", "vsce": "^1.18.0", - "vscode": "^1.0.0" + "vscode": "^1.1.0" }, "extensionDependencies": [ "vscode.powershell" From a0d619a234f91657198d5133bfc1f630765053e5 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Mon, 15 May 2017 15:10:26 -0700 Subject: [PATCH 08/12] Get end of line character from the document --- src/features/HelpCompletion.ts | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index a5dca77b5c..a8499efa28 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -2,9 +2,8 @@ * Copyright (C) Microsoft Corporation. All rights reserved. *--------------------------------------------------------*/ -import vscode = require("vscode"); import { IFeature } from "../feature"; -import { TextDocumentChangeEvent, workspace, Disposable, Position } from "vscode"; +import { TextDocumentChangeEvent, workspace, Disposable, Position, window, Range, EndOfLine } from "vscode"; import { LanguageClient, RequestType } from "vscode-languageclient"; export namespace CommentHelpRequest { @@ -53,6 +52,7 @@ export class HelpCompletionFeature implements IFeature { } onEvent(changeEvent: TextDocumentChangeEvent): void { + // todo split this method into logical components let text = changeEvent.contentChanges[0].text; switch (this.searchState) { case SearchState.Searching: @@ -103,16 +103,24 @@ export class HelpCompletionFeature implements IFeature { return; } - // todo get the eol character programmatically or let the server return one whole string // todo add indentation level to the help content - let editor = vscode.window.activeTextEditor; - let replaceRange = new vscode.Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); + let editor = window.activeTextEditor; + let replaceRange = new Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); // Trim the last empty line and join the strings. - let text = content.slice(0, -1).join("\r\n"); + let text = content.slice(0, -1).join(this.getEOL(doc.eol)); editor.edit(editBuilder => editBuilder.replace(replaceRange, text)); }); } } } + + private getEOL(eol: EndOfLine): string { + // there are only two type of EndOfLine types. + if (eol === EndOfLine.CRLF) { + return "\r\n"; + } + + return "\n"; + } } From 4b4213e23c21c78d7e34c928987064db2b2f8047 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Tue, 16 May 2017 18:36:11 -0700 Subject: [PATCH 09/12] Insert a snippet instead of a string --- src/features/HelpCompletion.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index a8499efa28..5812e96038 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -3,7 +3,7 @@ *--------------------------------------------------------*/ import { IFeature } from "../feature"; -import { TextDocumentChangeEvent, workspace, Disposable, Position, window, Range, EndOfLine } from "vscode"; +import { TextDocumentChangeEvent, workspace, Disposable, Position, window, Range, EndOfLine, SnippetString } from "vscode"; import { LanguageClient, RequestType } from "vscode-languageclient"; export namespace CommentHelpRequest { @@ -53,6 +53,8 @@ export class HelpCompletionFeature implements IFeature { onEvent(changeEvent: TextDocumentChangeEvent): void { // todo split this method into logical components + // todo create a helpcompletion provider class + // todo associate state with a given document let text = changeEvent.contentChanges[0].text; switch (this.searchState) { case SearchState.Searching: @@ -109,7 +111,7 @@ export class HelpCompletionFeature implements IFeature { // Trim the last empty line and join the strings. let text = content.slice(0, -1).join(this.getEOL(doc.eol)); - editor.edit(editBuilder => editBuilder.replace(replaceRange, text)); + editor.insertSnippet(new SnippetString(text), replaceRange); }); } } From 8ba1e21b3442feccc2d94de0f6fa0db874dc5dea Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Tue, 16 May 2017 20:35:05 -0700 Subject: [PATCH 10/12] Componentize HelpCompletion feature --- src/features/HelpCompletion.ts | 183 +++++++++++++++++++++------------ 1 file changed, 120 insertions(+), 63 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index 5812e96038..b36e7183cf 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -3,7 +3,7 @@ *--------------------------------------------------------*/ import { IFeature } from "../feature"; -import { TextDocumentChangeEvent, workspace, Disposable, Position, window, Range, EndOfLine, SnippetString } from "vscode"; +import { TextDocumentChangeEvent, workspace, Disposable, Position, window, Range, EndOfLine, SnippetString, TextDocument } from "vscode"; import { LanguageClient, RequestType } from "vscode-languageclient"; export namespace CommentHelpRequest { @@ -23,28 +23,20 @@ interface CommentHelpRequestResult { enum SearchState { Searching, Locked, Found }; export class HelpCompletionFeature implements IFeature { - private readonly triggerCharactersBlockComment: string; - private readonly triggerCharactersLineComment: string; - private triggerCharactersFound: string; + private helpCompletionProvider: HelpCompletionProvider; private languageClient: LanguageClient; private disposable: Disposable; - private searchState: SearchState; - private get isBlockComment(): boolean { - return this.triggerCharactersFound !== undefined && - this.triggerCharactersFound === this.triggerCharactersBlockComment; - } constructor() { - this.triggerCharactersBlockComment = "<#"; - this.triggerCharactersLineComment = "##"; + this.helpCompletionProvider = new HelpCompletionProvider(); let subscriptions = []; workspace.onDidChangeTextDocument(this.onEvent, this, subscriptions); - this.searchState = SearchState.Searching; this.disposable = Disposable.from(...subscriptions); } setLanguageClient(languageClient: LanguageClient) { this.languageClient = languageClient; + this.helpCompletionProvider.languageClient = languageClient; } dispose() { @@ -52,69 +44,134 @@ export class HelpCompletionFeature implements IFeature { } onEvent(changeEvent: TextDocumentChangeEvent): void { - // todo split this method into logical components - // todo create a helpcompletion provider class - // todo associate state with a given document - let text = changeEvent.contentChanges[0].text; - switch (this.searchState) { + this.helpCompletionProvider.updateState( + changeEvent.document, + changeEvent.contentChanges[0].text, + changeEvent.contentChanges[0].range); + + // todo raise an event when trigger is found, and attach complete() to the event. + if (this.helpCompletionProvider.triggerFound) { + this.helpCompletionProvider.reset(); + this.helpCompletionProvider.complete(); + } + + } +} + +class TriggerFinder { + private state: SearchState; + private document: TextDocument; + private count: number; + constructor(private triggerCharacters: string) { + this.state = SearchState.Searching; + this.count = 0; + } + + public get found(): boolean { + return this.state === SearchState.Found; + } + + public updateState(document: TextDocument, changeText: string): void { + switch (this.state) { case SearchState.Searching: - if (text.length === 1) { - if (text[0] === this.triggerCharactersBlockComment[0]) { - this.searchState = SearchState.Locked; - this.triggerCharactersFound = this.triggerCharactersBlockComment; - } - else if (text[0] === this.triggerCharactersLineComment[0]) { - this.searchState = SearchState.Locked; - this.triggerCharactersFound = this.triggerCharactersLineComment; - } + if (changeText.length === 1 && changeText[0] === this.triggerCharacters[this.count]) { + this.state = SearchState.Locked; + this.document = document; + this.count++; } break; case SearchState.Locked: - if (text.length === 1 && text[0] === this.triggerCharactersFound[1]) { - this.searchState = SearchState.Found; + if (changeText.length === 1 && changeText[0] === this.triggerCharacters[this.count] && document === this.document) { + this.count++; + if (this.count === this.triggerCharacters.length) { + this.state = SearchState.Found; + } } else { - this.searchState = SearchState.Searching; + this.reset(); } break; + + default: + this.reset(); + break; } + } + + public reset(): void { + this.state = SearchState.Searching; + this.count = 0; + } +} - let r = changeEvent.contentChanges[0].range; - console.log(`Search State: ${this.searchState.toString()}; Range: (${r.start.line}, ${r.start.character}), (${r.end.line}, ${r.end.character})`); - if (this.searchState === SearchState.Found) { - this.searchState = SearchState.Searching; - if (this.languageClient) { - let change = changeEvent.contentChanges[0]; - let triggerStartPos = change.range.start; - let triggerEndPos = change.range.end; - let doc = changeEvent.document; - this.languageClient.sendRequest( - CommentHelpRequest.type, - { - documentUri: changeEvent.document.uri.toString(), - triggerPosition: triggerStartPos, - blockComment: this.isBlockComment - }).then(result => { - if (result === undefined) { - return; - } - - let content = result.content; - if (content === undefined) { - return; - } - - // todo add indentation level to the help content - let editor = window.activeTextEditor; - let replaceRange = new Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); - - // Trim the last empty line and join the strings. - let text = content.slice(0, -1).join(this.getEOL(doc.eol)); - editor.insertSnippet(new SnippetString(text), replaceRange); - }); - } +class HelpCompletionProvider { + private triggerFinderBlockComment: TriggerFinder; + private triggerFinderLineComment: TriggerFinder; + private lastChangeText: string; + private lastChangeRange: Range; + private lastDocument: TextDocument; + private langClient: LanguageClient; + + constructor() { + this.triggerFinderBlockComment = new TriggerFinder("<#"); + this.triggerFinderLineComment = new TriggerFinder("##"); + } + + public get triggerFound(): boolean { + return this.triggerFinderBlockComment.found || this.triggerFinderLineComment.found; + } + + public set languageClient(value: LanguageClient) { + this.langClient = value; + } + + public updateState(document: TextDocument, changeText: string, changeRange: Range): void { + this.lastDocument = document; + this.lastChangeText = changeText; + this.lastChangeRange = changeRange; + this.triggerFinderBlockComment.updateState(document, changeText); + this.triggerFinderLineComment.updateState(document, changeText); + } + + public reset(): void { + this.triggerFinderBlockComment.reset(); + this.triggerFinderLineComment.reset(); + } + + public complete(): Thenable { + if (this.langClient === undefined) { + return; } + + let change = this.lastChangeText; + let triggerStartPos = this.lastChangeRange.start; + let triggerEndPos = this.lastChangeRange.end; + let doc = this.lastDocument; + this.langClient.sendRequest( + CommentHelpRequest.type, + { + documentUri: doc.uri.toString(), + triggerPosition: triggerStartPos, + blockComment: this.triggerFinderBlockComment.found + }).then(result => { + if (result === undefined) { + return; + } + + let content = result.content; + if (content === undefined) { + return; + } + + // todo add indentation level to the help content + let editor = window.activeTextEditor; + let replaceRange = new Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); + + // Trim the last empty line and join the strings. + let text = content.slice(0, -1).join(this.getEOL(doc.eol)); + editor.insertSnippet(new SnippetString(text), replaceRange); + }); } private getEOL(eol: EndOfLine): string { From 1b35c07a6f2ed4c0bf80003552d203f4b87270c6 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Tue, 16 May 2017 20:57:01 -0700 Subject: [PATCH 11/12] Fix returning promise from complete() method --- src/features/HelpCompletion.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index b36e7183cf..f39c4ccc59 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -51,8 +51,7 @@ export class HelpCompletionFeature implements IFeature { // todo raise an event when trigger is found, and attach complete() to the event. if (this.helpCompletionProvider.triggerFound) { - this.helpCompletionProvider.reset(); - this.helpCompletionProvider.complete(); + this.helpCompletionProvider.complete().then(() => this.helpCompletionProvider.reset()); } } @@ -148,7 +147,7 @@ class HelpCompletionProvider { let triggerStartPos = this.lastChangeRange.start; let triggerEndPos = this.lastChangeRange.end; let doc = this.lastDocument; - this.langClient.sendRequest( + return this.langClient.sendRequest( CommentHelpRequest.type, { documentUri: doc.uri.toString(), From 09d49387c81bdf9cc83af3e3996948845eb982e1 Mon Sep 17 00:00:00 2001 From: Kapil Borle Date: Wed, 17 May 2017 18:40:40 -0700 Subject: [PATCH 12/12] Remove indentation from comment help --- src/features/HelpCompletion.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/features/HelpCompletion.ts b/src/features/HelpCompletion.ts index f39c4ccc59..d4bc5f0736 100644 --- a/src/features/HelpCompletion.ts +++ b/src/features/HelpCompletion.ts @@ -167,8 +167,9 @@ class HelpCompletionProvider { let editor = window.activeTextEditor; let replaceRange = new Range(triggerStartPos.translate(0, -1), triggerStartPos.translate(0, 1)); + // Trim the leading whitespace (used by the rule for indentation) as VSCode takes care of the indentation. // Trim the last empty line and join the strings. - let text = content.slice(0, -1).join(this.getEOL(doc.eol)); + let text = content.map(x => x.trimLeft()).slice(0, -1).join(this.getEOL(doc.eol)); editor.insertSnippet(new SnippetString(text), replaceRange); }); }