-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Enable go via workspace detection
- Loading branch information
Showing
22 changed files
with
2,033 additions
and
1,011 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,5 +4,6 @@ | |
"cSpell.words": [ | ||
"esbuild", | ||
"socketsecurity" | ||
] | ||
], | ||
"typescript.tsdk": "node_modules/typescript/lib" | ||
} |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
const goBuiltins = [ | ||
'archive/tar', | ||
'archive/zip', | ||
'bufio', | ||
'bytes', | ||
'compress/bzip2', | ||
'compress/flate', | ||
'compress/gzip', | ||
'compress/lzw', | ||
'compress/zlib', | ||
'container/heap', | ||
'container/list', | ||
'container/ring', | ||
'context', | ||
'crypto', | ||
'database/sql', | ||
'debug/buildinfo', | ||
'debug/dwarf', | ||
'debug/elf', | ||
'debug/gosym', | ||
'debug/macho', | ||
'debug/pe', | ||
'debug/plan9obj', | ||
'embed', | ||
'encoding', | ||
'errors', | ||
'expvar', | ||
'flag', | ||
'fmt', | ||
'go/ast', | ||
'go/build', | ||
'go/constant', | ||
'go/doc', | ||
'go/format', | ||
'go/importer', | ||
'go/internal/gccgoimporter', | ||
'go/internal/gcimporter', | ||
'go/internal/srcimporter', | ||
'go/internal/typeparams', | ||
'go/parser', | ||
'go/printer', | ||
'go/scanner', | ||
'go/token', | ||
'go/types', | ||
'hash', | ||
'html', | ||
'image', | ||
'index/suffixarray', | ||
'internal', | ||
'io', | ||
'log', | ||
'math', | ||
'mime', | ||
'net', | ||
'os', | ||
'path', | ||
'plugin', | ||
'reflect', | ||
'regexp', | ||
'runtime', | ||
'sort', | ||
'strconv', | ||
'strings', | ||
'sync', | ||
'syscall', | ||
'testing', | ||
'text/scanner', | ||
'text/tabwriter', | ||
'text/template', | ||
'time', | ||
'unicode', | ||
'unsafe' | ||
] | ||
|
||
export function isGoBuiltin (pkg: string) { | ||
return goBuiltins.some(builtin => pkg === builtin || pkg.startsWith(builtin + '/')) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
import * as vscode from 'vscode' | ||
import { EXTENSION_PREFIX } from '../../util'; | ||
|
||
async function getGoExtension() { | ||
const go = vscode.extensions.getExtension('golang.go'); | ||
if (go && !go.isActive) await go.activate(); | ||
return go?.exports; | ||
} | ||
|
||
export async function initGo(): Promise<vscode.Disposable> { | ||
// in the future, do any needed init work with the golang.go extension instance here | ||
return new vscode.Disposable(() => {}); | ||
} | ||
|
||
const warned = new Set<string>(); | ||
|
||
export async function getGoExecutable(fileName?: string): Promise<string | void> { | ||
// no executable in virtual workspace | ||
if (vscode.workspace.workspaceFolders?.every(f => f.uri.scheme !== 'file')) return | ||
const workspaceConfig = vscode.workspace.getConfiguration(EXTENSION_PREFIX); | ||
const pathOverride = workspaceConfig.get<string>('goExecutable'); | ||
if (pathOverride) { | ||
return Promise.resolve(vscode.workspace.fs.stat(vscode.Uri.file(pathOverride))).then( | ||
st => { | ||
if (st.type & vscode.FileType.File) return pathOverride; | ||
throw new Error('not a file') | ||
} | ||
).catch(err => { | ||
vscode.window.showErrorMessage(`Failed to find Go binary at '${pathOverride}'. Please update ${EXTENSION_PREFIX}.goExecutable.`) | ||
}) | ||
} | ||
const ext = await getGoExtension(); | ||
const cmd = await ext?.settings.getExecutionCommand( | ||
'go', | ||
fileName && vscode.Uri.file(fileName) | ||
) | ||
if (cmd) return cmd.binPath | ||
const workspaceID = vscode.workspace.name || | ||
vscode.workspace.workspaceFolders?.map(f => f.uri.fsPath).join(',') || | ||
vscode.window.activeTextEditor?.document.uri.fsPath; | ||
if (workspaceID) { | ||
if (warned.has(workspaceID)) return; | ||
warned.add(workspaceID); | ||
} | ||
const installGo = 'Install Go extension'; | ||
const configGo = 'Configure Go extension'; | ||
const setPath = `Configure Socket`; | ||
vscode.window.showErrorMessage( | ||
`Socket failed to find a Go installation; please ${ext ? 'install the Go toolchain with' : 'install'} the Go extension or set ${EXTENSION_PREFIX}.goExecutable.`, | ||
ext ? configGo : installGo, | ||
setPath | ||
).then(async res => { | ||
if (res === installGo) { | ||
vscode.env.openExternal(vscode.Uri.parse('vscode:extension/golang.go')); | ||
} else if (res === configGo) { | ||
vscode.commands.executeCommand('go.tools.install'); | ||
} else if (res === setPath) { | ||
await workspaceConfig.update('goExecutable', '', vscode.ConfigurationTarget.Global) | ||
vscode.commands.executeCommand('workbench.action.openSettingsJson'); | ||
} | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"bufio" | ||
"os" | ||
"go/parser" | ||
"go/token" | ||
"strconv" | ||
) | ||
|
||
// Eventually maybe migrate to WASI with tinygo | ||
|
||
|
||
type VSPosition struct { | ||
Line int `json:"line"` | ||
Character int `json:"character"` | ||
} | ||
|
||
type VSRange struct { | ||
Start VSPosition `json:"start"` | ||
End VSPosition `json:"end"` | ||
} | ||
|
||
type GoImport struct { | ||
Name string `json:"name"` | ||
Range VSRange `json:"range"` | ||
} | ||
|
||
func toVSPos(src token.Position) VSPosition { | ||
// TODO: breaks on unicode but probably rare enough to not matter | ||
return VSPosition { src.Line - 1, src.Column - 1, } | ||
} | ||
|
||
func main() { | ||
reader := bufio.NewReader(os.Stdin) | ||
fset := token.NewFileSet() | ||
file, err := parser.ParseFile(fset, "src.go", reader, parser.ImportsOnly) | ||
|
||
if err != nil { | ||
os.Stderr.Write([]byte(err.Error())) | ||
os.Exit(1) | ||
} | ||
|
||
results := make([]GoImport, 0) | ||
|
||
for _, imp := range file.Imports { | ||
start := fset.Position(imp.Pos()) | ||
end := fset.Position(imp.End()) | ||
name, nameErr := strconv.Unquote(imp.Path.Value) | ||
|
||
if nameErr != nil { | ||
os.Stderr.Write([]byte(nameErr.Error())) | ||
os.Exit(1) | ||
} | ||
|
||
results = append(results, GoImport { | ||
name, | ||
VSRange { toVSPos(start), toVSPos(end), }, | ||
}) | ||
} | ||
|
||
result, encErr := json.Marshal(results) | ||
if encErr != nil { | ||
os.Stderr.Write([]byte(err.Error())) | ||
os.Exit(1) | ||
} | ||
|
||
os.Stdout.Write(result) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
import importFinder from './find-imports.go' | ||
|
||
let cachedBin: Promise<string> | null = null | ||
let lastBinPath: string | null = null | ||
|
||
export async function generateNativeGoImportBinary (goBin: string) { | ||
const [ | ||
childProcess, | ||
path, | ||
fs, | ||
os | ||
] = await Promise.all([ | ||
import('node:child_process'), | ||
import('node:path'), | ||
import('node:fs/promises'), | ||
import('node:os') | ||
]) | ||
if (cachedBin && lastBinPath === goBin) { | ||
const bin = await cachedBin.catch(() => null) | ||
if (bin) { | ||
const valid = await fs.lstat(bin).then(f => { | ||
return f.isFile() | ||
}, err => { | ||
if (err && (typeof err as { code?: unknown }).code === 'ENOENT') { | ||
return false | ||
} | ||
throw err | ||
}) | ||
if (valid) return bin | ||
} | ||
} | ||
lastBinPath = goBin | ||
cachedBin = (async () => { | ||
const outBin = path.join(await fs.mkdtemp(path.join(os.tmpdir(), 'socket-')), 'go-import-parser') | ||
const build = childProcess.spawn(goBin, ['build', '-o', outBin, importFinder], { | ||
cwd: __dirname | ||
}) | ||
|
||
const exitCode = await new Promise<number | null>((resolve, reject) => { | ||
build.once('exit', resolve) | ||
build.once('error', reject) | ||
setTimeout(() => reject(new Error('timeout')), 3000) | ||
}) | ||
|
||
if (exitCode) { | ||
throw new Error(`failed to build with code ${exitCode}`) | ||
} | ||
|
||
return outBin | ||
})() | ||
|
||
return cachedBin | ||
|
||
} | ||
|
Oops, something went wrong.