'use strict' ; import vscode = require ( 'vscode' ) ; import { getImportablePackages } from './gopPackages' ; import { promptForMissingTool } from './gopInstallTools' ; import { documentSymbols , GoOutlineImportsOptions } from './goOutline' ; import { parseFilePrelude } from './util' ; export function getTextEditForAddImport ( inputText , arg ) { if ( arg === undefined ) { return null ; } const { imports , pkg } = parseFilePrelude ( inputText ) ; if ( imports . some ( ( block ) => block . pkgs . some ( ( pkgpath ) => pkgpath === arg ) ) ) { return [ ] ; } const multis = imports . filter ( ( x ) => x . kind === 'multi' ) ; const minusCgo = imports . filter ( ( x ) => x . kind !== 'pseudo' ) ; if ( multis . length > 0 ) { const lastImportSection = multis [ multis . length - 1 ] ; if ( lastImportSection . end === - 1 ) { return [ vscode . TextEdit . insert ( new vscode . Position ( lastImportSection . start + 1 , 0 ) , `import "${ arg }"\n` ) ] ; } return [ vscode . TextEdit . insert ( new vscode . Position ( lastImportSection . start + 1 , 0 ) , '\t"' + arg + '"\n' ) ] ; } else if ( minusCgo . length > 0 ) { const edits = [ ] ; edits . push ( vscode . TextEdit . insert ( new vscode . Position ( minusCgo [ 0 ] . start - 1 , 0 ) , 'import (\n\t"' + arg + '"\n' ) ) ; minusCgo . forEach ( ( element ) => { const currentLine = vscode . window . activeTextEditor . document . lineAt ( element . start - 1 ) . text ; const updatedLine = currentLine . replace ( /^\s*import\s*/ , '\t' ) ; edits . push ( vscode . TextEdit . replace ( new vscode . Range ( element . start - 1 , 0 , element . start - 1 , currentLine . length ) , updatedLine ) ) ; } ) ; edits . push ( vscode . TextEdit . insert ( new vscode . Position ( minusCgo [ minusCgo . length - 1 ] . end - 1 , 0 ) , ')\n' ) ) ; return edits ; } else if ( pkg && pkg . start >= 0 ) { return [ vscode . TextEdit . insert ( new vscode . Position ( 0 , 0 ) , '\nimport (\n\t"' + arg + '"\n)\n' ) ] ; } else { return [ ] ; } } const missingToolMsg = 'Missing tool: ' ; export async function listPackages ( excludeImportedPkgs = false ) { const importedPkgs = excludeImportedPkgs && vscode . window . activeTextEditor ? await getImports ( vscode . window . activeTextEditor . document ) : [ ] ; const pkgMap = await getImportablePackages ( vscode . window . activeTextEditor . document . fileName , true ) ; const stdLibs = [ ] ; const nonStdLibs = [ ] ; pkgMap . forEach ( ( value , key ) => { if ( importedPkgs . some ( ( imported ) => imported === key ) ) { return ; } if ( value . isStd ) { stdLibs . push ( key ) ; } else { nonStdLibs . push ( key ) ; } } ) ; return [ ... stdLibs . sort ( ) , ... nonStdLibs . sort ( ) ] ; } param document returns async function getImports ( document ) { const options = { fileName : document . fileName , importsOption : GoOutlineImportsOptions . Only , document } ; const symbols = await documentSymbols ( options , null ) ; if ( ! symbols || ! symbols . length ) { return [ ] ; } const imports = symbols [ 0 ] . children . filter ( ( x ) => x . kind === vscode . SymbolKind . Namespace ) . map ( ( x ) => x . name . substr ( 1 , x . name . length - 2 ) ) ; return imports ; } async function askUserForImport ( ) { try { const packages = await listPackages ( true ) ; return vscode . window . showQuickPick ( packages ) ; } catch ( err ) { if ( typeof err === 'string' && err . startsWith ( missingToolMsg ) ) { promptForMissingTool ( err . substr ( missingToolMsg . length ) ) ; } } } export function addImport ( arg ) { const editor = vscode . window . activeTextEditor ; if ( ! editor ) { vscode . window . showErrorMessage ( 'No active editor found to add imports.' ) ; return ; } const p = arg && arg . importPath ? Promise . resolve ( arg . importPath ) : askUserForImport ( ) ; p . then ( ( imp ) => { if ( ! imp ) { return ; } const edits = getTextEditForAddImport ( vscode . window . activeTextEditor . document . getText ( ) , imp ) ; if ( edits && edits . length > 0 ) { const edit = new vscode . WorkspaceEdit ( ) ; edit . set ( editor . document . uri , edits ) ; vscode . workspace . applyEdit ( edit ) ; } } ) ; }