public async provideCompletionItemsInternal()

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);
			});
		});
	}