From 997c7b921196b5f515fb43e00baccaedac281bfc Mon Sep 17 00:00:00 2001 From: Derek Keeler Date: Thu, 28 Jun 2018 15:59:10 -0700 Subject: [PATCH] Discovered root cause & fixed issue with popups in comments - issue #2057 - struggling with test framework & signature provider! --- src/client/providers/completionSource.ts | 15 +++------ src/client/providers/providerUtilities.ts | 8 ++--- src/client/providers/signatureProvider.ts | 12 +++++-- .../providers/completionSource.unit.test.ts | 32 +++++++++++++++++-- 4 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/client/providers/completionSource.ts b/src/client/providers/completionSource.ts index 764f9e570cfd..c287d4fa858c 100644 --- a/src/client/providers/completionSource.ts +++ b/src/client/providers/completionSource.ts @@ -65,25 +65,18 @@ export class CompletionSource { private async getCompletionResult(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken) : Promise { - if (position.character <= 0) { - return undefined; - } - const filename = document.fileName; - const lineText = document.lineAt(position.line).text; - if (lineText.match(/^\s*\/\//)) { - return undefined; - } - // Suppress completion inside string and comments. - if (isPositionInsideStringOrComment(document, position)) { + if (position.character <= 0 || + isPositionInsideStringOrComment(document, position)) { return undefined; } + const type = proxy.CommandType.Completions; const columnIndex = position.character; const source = document.getText(); const cmd: proxy.ICommand = { command: type, - fileName: filename, + fileName: document.fileName, columnIndex: columnIndex, lineIndex: position.line, source: source diff --git a/src/client/providers/providerUtilities.ts b/src/client/providers/providerUtilities.ts index 0a4f8274144d..ecc6f371cdad 100644 --- a/src/client/providers/providerUtilities.ts +++ b/src/client/providers/providerUtilities.ts @@ -1,16 +1,16 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import * as vscode from 'vscode'; +import { Position, Range, TextDocument } from 'vscode'; import { Tokenizer } from '../language/tokenizer'; import { ITextRangeCollection, IToken, TokenizerMode, TokenType } from '../language/types'; -export function getDocumentTokens(document: vscode.TextDocument, tokenizeTo: vscode.Position, mode: TokenizerMode): ITextRangeCollection { - const text = document.getText(new vscode.Range(new vscode.Position(0, 0), tokenizeTo)); +export function getDocumentTokens(document: TextDocument, tokenizeTo: Position, mode: TokenizerMode): ITextRangeCollection { + const text = document.getText(new Range(new Position(0, 0), tokenizeTo)); return new Tokenizer().tokenize(text, 0, text.length, mode); } -export function isPositionInsideStringOrComment(document: vscode.TextDocument, position: vscode.Position): boolean { +export function isPositionInsideStringOrComment(document: TextDocument, position: Position): boolean { const tokenizeTo = position.translate(1, 0); const tokens = getDocumentTokens(document, tokenizeTo, TokenizerMode.CommentsAndStrings); const offset = document.offsetAt(position); diff --git a/src/client/providers/signatureProvider.ts b/src/client/providers/signatureProvider.ts index cf1014296519..c68bf70ca3bd 100644 --- a/src/client/providers/signatureProvider.ts +++ b/src/client/providers/signatureProvider.ts @@ -14,6 +14,7 @@ import { JediFactory } from '../languageServices/jediProxyFactory'; import { captureTelemetry } from '../telemetry'; import { SIGNATURE } from '../telemetry/constants'; import * as proxy from './jediProxy'; +import { isPositionInsideStringOrComment } from './providerUtilities'; const DOCSTRING_PARAM_PATTERNS = [ '\\s*:type\\s*PARAMNAME:\\s*([^\\n, ]+)', // Sphinx @@ -71,7 +72,7 @@ export class PythonSignatureProvider implements SignatureHelpProvider { if (validParamInfo) { const docLines = def.docstring.splitLines(); - label = docLines.shift().trim(); + label = docLines.shift()!.trim(); documentation = docLines.join(EOL).trim(); } else { if (def.params && def.params.length > 0) { @@ -110,7 +111,14 @@ export class PythonSignatureProvider implements SignatureHelpProvider { return new SignatureHelp(); } @captureTelemetry(SIGNATURE) - public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Thenable { + public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Thenable { + // early exit if we're in a string or comment (or in an undefined position) + if (position.character <= 0 || + isPositionInsideStringOrComment(document, position)) + { + return Promise.resolve(undefined); + } + const cmd: proxy.ICommand = { command: proxy.CommandType.Arguments, fileName: document.fileName, diff --git a/src/test/providers/completionSource.unit.test.ts b/src/test/providers/completionSource.unit.test.ts index a6ddf77bf934..8a2182c4bbaf 100644 --- a/src/test/providers/completionSource.unit.test.ts +++ b/src/test/providers/completionSource.unit.test.ts @@ -5,17 +5,25 @@ // tslint:disable:max-func-body-length no-any +// import { expect, use } from 'chai'; +// import * as chaipromise from 'chai-as-promised'; import * as TypeMoq from 'typemoq'; -import { CancellationTokenSource, CompletionItemKind, Position, SymbolKind, TextDocument, TextLine } from 'vscode'; +import { CancellationTokenSource, CompletionItemKind, // CancellationToken + Position, SymbolKind, TextDocument, TextLine } from 'vscode'; // SignatureHelp import { IAutoCompleteSettings, IConfigurationService, IPythonSettings } from '../../client/common/types'; import { IServiceContainer } from '../../client/ioc/types'; import { JediFactory } from '../../client/languageServices/jediProxyFactory'; import { CompletionSource } from '../../client/providers/completionSource'; import { IItemInfoSource } from '../../client/providers/itemInfoSource'; -import { IAutoCompleteItem, ICompletionResult, JediProxyHandler } from '../../client/providers/jediProxy'; +import { IAutoCompleteItem, // IArgumentsResult + ICompletionResult, JediProxyHandler } from '../../client/providers/jediProxy'; +//import { PythonSignatureProvider } from '../../client/providers/signatureProvider'; + +//use(chaipromise); suite('Completion Provider', () => { let completionSource: CompletionSource; + //let pySignatureProvider: PythonSignatureProvider; let jediHandler: TypeMoq.IMock>; let autoCompleteSettings: TypeMoq.IMock; let itemInfoSource: TypeMoq.IMock; @@ -36,6 +44,7 @@ suite('Completion Provider', () => { pythonSettings.setup(p => p.autoComplete).returns(() => autoCompleteSettings.object); itemInfoSource = TypeMoq.Mock.ofType(); completionSource = new CompletionSource(jediFactory.object, serviceContainer.object, itemInfoSource.object); + //pySignatureProvider = new PythonSignatureProvider(jediFactory.object); }); async function testDocumentation(source: string, addBrackets: boolean) { @@ -85,5 +94,24 @@ suite('Completion Provider', () => { const source = 'if True:\n print("Hello")\n'; await testDocumentation(source, true); }); + // test('Signature provides docs for commands', async () => { + // const source = ' print(\'Python is awesome\',)'; + // const position = new Position(1, 27); + + // const lineText = TypeMoq.Mock.ofType(); + // lineText.setup(l => l.text).returns(() => source); + + // const doc = TypeMoq.Mock.ofType(); + // doc.setup(d => d.fileName).returns(() => ''); + // doc.setup(d => d.getText(TypeMoq.It.isAny())).returns(() => source); + // doc.setup(d => d.lineAt(TypeMoq.It.isAny())).returns(() => lineText.object); + // doc.setup(d => d.offsetAt(TypeMoq.It.isAny())).returns(() => 0); + // const cancelToken = TypeMoq.Mock.ofType(); + // jediHandler.setup(j => j.sendCommand(TypeMoq.It.isAny(), TypeMoq.It.isAny())) + // .returns(() => new Promise.resolve(IArgumentsResult)); + + // const items: SignatureHelp = await pySignatureProvider.provideSignatureHelp(doc.object, position, cancelToken.object); + // expect(items).to.not.equal(null, 'Expected to have a signature generated for this line of code.'); + // }); });