in src/goSuggest.ts [145:269]
public async provideCompletionItemsInternal(
document: vscode.TextDocument,
position: vscode.Position,
token: vscode.CancellationToken,
config: vscode.WorkspaceConfiguration
): Promise<vscode.CompletionItem[] | vscode.CompletionList> {
// Completions for the package statement based on the file name
const pkgStatementCompletions = await getPackageStatementCompletions(document);
if (pkgStatementCompletions && pkgStatementCompletions.length) {
return pkgStatementCompletions;
}
this.excludeDocs = false;
this.gocodeFlags = ['-f=json'];
if (Array.isArray(config['gocodeFlags'])) {
this.gocodeFlags.push(...config['gocodeFlags']);
}
return this.ensureGoCodeConfigured(document.uri, config).then(() => {
return new Promise<vscode.CompletionItem[] | vscode.CompletionList>((resolve, reject) => {
const filename = document.fileName;
const lineText = document.lineAt(position.line).text;
const lineTillCurrentPosition = lineText.substr(0, position.character);
const autocompleteUnimportedPackages =
config['autocompleteUnimportedPackages'] === true && !lineText.match(/^(\s)*(import|package)(\s)+/);
// triggering completions in comments on exported members
const commentCompletion = getCommentCompletion(document, position);
if (commentCompletion) {
return resolve([commentCompletion]);
}
// prevent completion when typing in a line comment that doesnt start from the beginning of the line
if (isPositionInComment(document, position)) {
return resolve([]);
}
const inString = isPositionInString(document, position);
if (!inString && lineTillCurrentPosition.endsWith('"')) {
return resolve([]);
}
const currentWord = getCurrentWord(document, position);
if (currentWord.match(/^\d+$/)) {
return resolve([]);
}
let offset = byteOffsetAt(document, position);
let inputText = document.getText();
const includeUnimportedPkgs = autocompleteUnimportedPackages && !inString && currentWord.length > 0;
return this.runGoCode(
document,
filename,
inputText,
offset,
inString,
position,
lineText,
currentWord,
includeUnimportedPkgs,
config
).then((suggestions) => {
// gocode does not suggest keywords, so we have to do it
suggestions.push(...getKeywordCompletions(currentWord));
// If no suggestions and cursor is at a dot, then check if preceeding word is a package name
// If yes, then import the package in the inputText and run gocode again to get suggestions
if ((!suggestions || suggestions.length === 0) && lineTillCurrentPosition.endsWith('.')) {
const pkgPath = this.getPackagePathFromLine(lineTillCurrentPosition);
if (pkgPath.length === 1) {
// Now that we have the package path, import it right after the "package" statement
const v = parseFilePrelude(vscode.window.activeTextEditor.document.getText());
const pkg = v.pkg;
const posToAddImport = document.offsetAt(new vscode.Position(pkg.start + 1, 0));
const textToAdd = `import "${pkgPath[0]}"\n`;
inputText =
inputText.substr(0, posToAddImport) + textToAdd + inputText.substr(posToAddImport);
offset += textToAdd.length;
// Now that we have the package imported in the inputText, run gocode again
return this.runGoCode(
document,
filename,
inputText,
offset,
inString,
position,
lineText,
currentWord,
false,
config
).then((newsuggestions) => {
// Since the new suggestions are due to the package that we imported,
// add additionalTextEdits to do the same in the actual document in the editor
// We use additionalTextEdits instead of command so that 'useCodeSnippetsOnFunctionSuggest'
// feature continues to work
newsuggestions.forEach((item) => {
item.additionalTextEdits = getTextEditForAddImport(pkgPath[0]);
});
resolve(newsuggestions);
}, reject);
}
if (pkgPath.length > 1) {
pkgPath.forEach((pkg) => {
const item = new vscode.CompletionItem(
`${lineTillCurrentPosition.replace('.', '').trim()} (${pkg})`,
vscode.CompletionItemKind.Module
);
item.additionalTextEdits = getTextEditForAddImport(pkg);
item.insertText = '';
item.detail = pkg;
item.command = {
title: 'Trigger Suggest',
command: 'editor.action.triggerSuggest'
};
suggestions.push(item);
});
resolve(new vscode.CompletionList(suggestions, true));
}
}
resolve(suggestions);
}, reject);
});
});
}