Merge pull request #1738 from lggomez/signature_fix

Don't count signature position changes inside string literals
This commit is contained in:
Vlad Barosan 2019-02-20 15:37:09 -08:00 коммит произвёл GitHub
Родитель e638ad71a9 490bb91af0
Коммит 5b6ca87e3a
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
1 изменённых файлов: 38 добавлений и 40 удалений

Просмотреть файл

@ -8,31 +8,27 @@
import vscode = require('vscode');
import { SignatureHelpProvider, SignatureHelp, SignatureInformation, ParameterInformation, TextDocument, Position, CancellationToken, WorkspaceConfiguration } from 'vscode';
import { definitionLocation } from './goDeclaration';
import { getParametersAndReturnType } from './util';
import { getParametersAndReturnType, isPositionInString } from './util';
export class GoSignatureHelpProvider implements SignatureHelpProvider {
private goConfig: WorkspaceConfiguration = null;
constructor(goConfig?: WorkspaceConfiguration) {
this.goConfig = goConfig;
constructor(private goConfig?: WorkspaceConfiguration) {
}
public provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise<SignatureHelp> {
if (!this.goConfig) {
this.goConfig = vscode.workspace.getConfiguration('go', document.uri);
}
public async provideSignatureHelp(document: TextDocument, position: Position, token: CancellationToken): Promise<SignatureHelp> {
let goConfig = this.goConfig || vscode.workspace.getConfiguration('go', document.uri);
let theCall = this.walkBackwardsToBeginningOfCall(document, position);
const theCall = this.walkBackwardsToBeginningOfCall(document, position);
if (theCall == null) {
return Promise.resolve(null);
}
let callerPos = this.previousTokenPosition(document, theCall.openParen);
const callerPos = this.previousTokenPosition(document, theCall.openParen);
// Temporary fix to fall back to godoc if guru is the set docsTool
let goConfig = this.goConfig;
if (goConfig['docsTool'] === 'guru') {
goConfig = Object.assign({}, goConfig, { 'docsTool': 'godoc' });
}
return definitionLocation(document, callerPos, goConfig, true, token).then(res => {
try {
const res = await definitionLocation(document, callerPos, goConfig, true, token);
if (!res) {
// The definition was not found
return null;
@ -45,37 +41,36 @@ export class GoSignatureHelpProvider implements SignatureHelpProvider {
if (!declarationText) {
return null;
}
let result = new SignatureHelp();
const result = new SignatureHelp();
let sig: string;
let si: SignatureInformation;
if (res.toolUsed === 'godef') {
// declaration is of the form "Add func(a int, b int) int"
let nameEnd = declarationText.indexOf(' ');
let sigStart = nameEnd + 5; // ' func'
let funcName = declarationText.substring(0, nameEnd);
const nameEnd = declarationText.indexOf(' ');
const sigStart = nameEnd + 5; // ' func'
const funcName = declarationText.substring(0, nameEnd);
sig = declarationText.substring(sigStart);
si = new SignatureInformation(funcName + sig, res.doc);
} else if (res.toolUsed === 'gogetdoc') {
}
else if (res.toolUsed === 'gogetdoc') {
// declaration is of the form "func Add(a int, b int) int"
declarationText = declarationText.substring(5);
let funcNameStart = declarationText.indexOf(res.name + '('); // Find 'functionname(' to remove anything before it
const funcNameStart = declarationText.indexOf(res.name + '('); // Find 'functionname(' to remove anything before it
if (funcNameStart > 0) {
declarationText = declarationText.substring(funcNameStart);
}
si = new SignatureInformation(declarationText, res.doc);
sig = declarationText.substring(res.name.length);
}
si.parameters = getParametersAndReturnType(sig).params.map(paramText =>
new ParameterInformation(paramText)
);
si.parameters = getParametersAndReturnType(sig).params.map(paramText => new ParameterInformation(paramText));
result.signatures = [si];
result.activeSignature = 0;
result.activeParameter = Math.min(theCall.commas.length, si.parameters.length - 1);
return result;
}, () => {
}
catch (e) {
return null;
});
}
}
private previousTokenPosition(document: TextDocument, position: Position): Position {
@ -89,28 +84,30 @@ export class GoSignatureHelpProvider implements SignatureHelpProvider {
return null;
}
private walkBackwardsToBeginningOfCall(document: TextDocument, position: Position): { openParen: Position, commas: Position[] } {
/**
* Goes through the function params' lines and gets the number of commas and the start position of the call.
*/
private walkBackwardsToBeginningOfCall(document: TextDocument, position: Position): { openParen: Position, commas: Position[] } | null {
let parenBalance = 0;
let commas = [];
let maxLookupLines = 30;
const commas = [];
for (let line = position.line; line >= 0 && maxLookupLines >= 0; line--, maxLookupLines--) {
let currentLine = document.lineAt(line).text;
let characterPosition = document.lineAt(line).text.length - 1;
for (let lineNr = position.line; lineNr >= 0 && maxLookupLines >= 0; lineNr-- , maxLookupLines--) {
if (line === position.line) {
characterPosition = position.character;
currentLine = currentLine.substring(0, position.character);
}
const line = document.lineAt(lineNr);
// if its current line, get the text until the position given, otherwise get the full line.
const [currentLine, characterPosition] = lineNr === position.line
? [line.text.substring(0, position.character), position.character]
: [line.text, line.text.length - 1];
for (let char = characterPosition; char >= 0; char--) {
for (let char = characterPosition - 1; char >= 0; char--) {
switch (currentLine[char]) {
case '(':
parenBalance--;
if (parenBalance < 0) {
return {
openParen: new Position(line, char),
commas: commas
openParen: new Position(lineNr, char),
commas
};
}
break;
@ -118,13 +115,14 @@ export class GoSignatureHelpProvider implements SignatureHelpProvider {
parenBalance++;
break;
case ',':
if (parenBalance === 0) {
commas.push(new Position(line, char));
const commaPos = new Position(lineNr, char);
if ((parenBalance === 0) && !isPositionInString(document, commaPos)) {
commas.push(commaPos);
}
break;
}
}
}
return null;
}
}
}