diff --git a/src/goSuggest.ts b/src/goSuggest.ts index 465018cdc..f7d04efa5 100644 --- a/src/goSuggest.ts +++ b/src/goSuggest.ts @@ -7,12 +7,12 @@ import vscode = require('vscode'); import cp = require('child_process'); -import { dirname, basename } from 'path'; -import { getBinPath, parameters, parseFilePrelude, isPositionInString, goKeywords, getToolsEnvVars, timeout } from './util'; +import { getBinPath, parameters, parseFilePrelude, isPositionInString, goKeywords, getToolsEnvVars, timeout, guessPackageNameFromFile } from './util'; import { promptForMissingTool } from './goInstallTools'; import { getTextEditForAddImport } from './goImport'; import { getImportablePackages } from './goPackages'; + function vscodeKindFromGoCodeClass(kind: string): vscode.CompletionItemKind { switch (kind) { case 'const': @@ -148,21 +148,6 @@ export class GoCompletionItemProvider implements vscode.CompletionItemProvider { let suggestions = []; let suggestionSet = new Set(); - // 'Smart Snippet' for package clause - // TODO: Factor this out into a general mechanism - if (!inputText.match(/package\s+(\w+)/)) { - let defaultPackageName = - basename(filename) === 'main.go' - ? 'main' - : basename(dirname(filename)); - if (defaultPackageName.match(/[a-zA-Z_]\w*/)) { - let packageItem = new vscode.CompletionItem('package ' + defaultPackageName); - packageItem.kind = vscode.CompletionItemKind.Snippet; - packageItem.insertText = 'package ' + defaultPackageName + '\r\n\r\n'; - suggestions.push(packageItem); - } - - } if (results[1]) { for (let suggest of results[1]) { if (inString && suggest.class !== 'import') continue; @@ -204,6 +189,18 @@ export class GoCompletionItemProvider implements vscode.CompletionItemProvider { let importablePkgs = includeUnimportedPkgs ? this.getMatchingPackages(currentWord, suggestionSet) : []; suggestions = suggestions.concat(importablePkgs); + // 'Smart Snippet' for package clause + // TODO: Factor this out into a general mechanism + if (!inputText.match(/package\s+(\w+)/)) { + return guessPackageNameFromFile(filename).then(pkgName => { + let packageItem = new vscode.CompletionItem('package ' + pkgName); + packageItem.kind = vscode.CompletionItemKind.Snippet; + packageItem.insertText = 'package ' + pkgName + '\r\n\r\n'; + suggestions.push(packageItem); + resolve(suggestions); + }, () => resolve(suggestions)); + } + resolve(suggestions); } catch (e) { reject(e); diff --git a/src/util.ts b/src/util.ts index 65bd39c7a..27fd2fecb 100644 --- a/src/util.ts +++ b/src/util.ts @@ -428,3 +428,55 @@ export function getImportPath(text: string): string { return ''; } + +// TODO: Add unit tests for the below + +/** + * Guess the package name based on parent directory name of the given file + * + * Cases: + * - dir 'go-i18n' -> 'i18n' + * - dir 'go-spew' -> 'spew' + * - dir 'kingpin' -> 'kingpin' + * - dir 'go-expand-tilde' -> 'tilde' + * - dir 'gax-go' -> 'gax' + * - dir 'go-difflib' -> 'difflib' + * - dir 'jwt-go' -> 'jwt' + * - dir 'go-radix' -> 'radix' + * + * @param {string} filePath. + */ +export function guessPackageNameFromFile(filePath): Promise { + return new Promise((resolve, reject) => { + + const goFilename = path.basename(filePath); + if (goFilename === 'main.go') { + return resolve('main'); + } + + const directoryPath = path.dirname(filePath); + let segments = directoryPath.split(/[\.-]/); + segments = segments.filter(val => val !== 'go'); + + if (segments.length === 0 || !/[a-zA-Z_]\w*/.test(segments[segments.length - 1])) { + return reject(); + } + + const proposedPkgName = segments[segments.length - 1]; + + if (goFilename.endsWith('internal_test.go')) { + return resolve(proposedPkgName); + } + + if (goFilename.endsWith('_test.go')) { + return resolve(proposedPkgName + '_test'); + } + + fs.stat(path.join(directoryPath, 'main.go'), (err, stats) => { + if (stats && stats.isFile()) { + return resolve('main'); + } + return resolve(proposedPkgName); + }); + }); +} \ No newline at end of file