diff --git a/src/goImport.ts b/src/goImport.ts index c6bb26642..ecbeba1b9 100644 --- a/src/goImport.ts +++ b/src/goImport.ts @@ -10,9 +10,11 @@ import cp = require('child_process'); import { getBinPath } from './goPath'; import { parseFilePrelude } from './util'; import { promptForMissingTool } from './goInstallTools'; +import { documentSymbols } from './goOutline'; -export function listPackages(): Thenable { - return new Promise((resolve, reject) => { +export function listPackages(excludeImportedPkgs: boolean = false): Thenable { + let importsPromise = excludeImportedPkgs && vscode.window.activeTextEditor ? getImports(vscode.window.activeTextEditor.document.fileName) : Promise.resolve([]); + let pkgsPromise = new Promise((resolve, reject) => { cp.execFile(getBinPath('gopkgs'), [], (err, stdout, stderr) => { if (err && (err).code === 'ENOENT') { promptForMissingTool('gopkgs'); @@ -23,10 +25,38 @@ export function listPackages(): Thenable { return resolve(sortedlines); }); }); + + return Promise.all([importsPromise, pkgsPromise]).then(values => { + let imports = values[0]; + let pkgs = values[1]; + if (imports.length === 0) { + return pkgs; + } + return pkgs.filter(element => { + return imports.indexOf(element) === -1; + }); + }); +} + +/** + * Returns the imported packages in the given file + * + * @param fileName File system path of the file whose imports need to be returned + * @returns Array of imported package paths wrapped in a promise + */ +export function getImports(fileName: string): Promise { + return documentSymbols(fileName).then(symbols => { + if (!symbols || !symbols[0] || !symbols[0].children) { + return []; + } + // imports will be of the form { type: 'import', label: '"math"'} + let imports = symbols[0].children.filter(x => x.type === 'import').map(x => x.label.substr(1, x.label.length - 2)); + return imports; + }); } function askUserForImport(): Thenable { - return listPackages().then(packages => { + return listPackages(true).then(packages => { return vscode.window.showQuickPick(packages); }); } diff --git a/test/go.test.ts b/test/go.test.ts index 72a814b2c..e6ff06297 100644 --- a/test/go.test.ts +++ b/test/go.test.ts @@ -16,6 +16,8 @@ import { getEditsFromUnifiedDiffStr, getEdits } from '../src/diffUtils'; import jsDiff = require('diff'); import { testCurrentFile } from '../src/goTest'; import { getGoVersion } from '../src/goInstallTools'; +import { documentSymbols } from '../src/goOutline'; +import { listPackages } from '../src/goImport'; suite('Go Extension Tests', () => { let gopath = process.env['GOPATH']; @@ -278,4 +280,37 @@ encountered. }).then(() => done(), done); }); + test('Test Outline', (done) => { + let filePath = path.join(fixturePath, 'test.go'); + documentSymbols(filePath).then(outlines => { + let packageOutline = outlines[0]; + let symbols = packageOutline.children; + let imports = symbols.filter(x => x.type === 'import'); + let functions = symbols.filter(x => x.type === 'function'); + + assert.equal(packageOutline.type, 'package'); + assert.equal(packageOutline.label, 'main'); + assert.equal(imports[0].label, '"fmt"'); + assert.equal(functions[0].label, 'print'); + assert.equal(functions[1].label, 'main'); + done(); + }, done); + }); + + test('Test listPackages', (done) => { + let uri = vscode.Uri.file(path.join(fixturePath, 'test.go')); + vscode.workspace.openTextDocument(uri).then(document => { + return vscode.window.showTextDocument(document).then(editor => { + let includeImportedPkgs = listPackages(false); + let excludeImportedPkgs = listPackages(true); + includeImportedPkgs.then(pkgs => { + assert.equal(pkgs.indexOf('fmt') > -1, true); + }); + excludeImportedPkgs.then(pkgs => { + assert.equal(pkgs.indexOf('fmt') > -1, false); + }); + return Promise.all([includeImportedPkgs, excludeImportedPkgs]); + }); + }).then(() => done(), done); + }); });