forked from golang/vscode-go
-
Notifications
You must be signed in to change notification settings - Fork 0
/
goBuild.ts
180 lines (165 loc) · 5.26 KB
/
goBuild.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
/*---------------------------------------------------------
* Copyright (C) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See LICENSE in the project root for license information.
*--------------------------------------------------------*/
import path = require('path');
import vscode = require('vscode');
import { getGoConfig } from './config';
import { toolExecutionEnvironment } from './goEnv';
import { buildDiagnosticCollection } from './goMain';
import { isModSupported } from './goModules';
import { getNonVendorPackages } from './goPackages';
import { diagnosticsStatusBarItem, outputChannel } from './goStatus';
import { getTestFlags } from './testUtils';
import {
getCurrentGoPath,
getModuleCache,
getTempFilePath,
getWorkspaceFolderPath,
handleDiagnosticErrors,
ICheckResult,
runTool
} from './util';
import { getCurrentGoWorkspaceFromGOPATH } from './utils/pathUtils';
/**
* Builds current package or workspace.
*/
export function buildCode(buildWorkspace?: boolean) {
const editor = vscode.window.activeTextEditor;
if (!buildWorkspace) {
if (!editor) {
vscode.window.showInformationMessage('No editor is active, cannot find current package to build');
return;
}
if (editor.document.languageId !== 'go') {
vscode.window.showInformationMessage(
'File in the active editor is not a Go file, cannot find current package to build'
);
return;
}
}
const documentUri = editor ? editor.document.uri : null;
const goConfig = getGoConfig(documentUri);
outputChannel.clear(); // Ensures stale output from build on save is cleared
diagnosticsStatusBarItem.show();
diagnosticsStatusBarItem.text = 'Building...';
isModSupported(documentUri).then((isMod) => {
goBuild(documentUri, isMod, goConfig, buildWorkspace)
.then((errors) => {
handleDiagnosticErrors(editor ? editor.document : null, errors, buildDiagnosticCollection);
diagnosticsStatusBarItem.hide();
})
.catch((err) => {
vscode.window.showInformationMessage('Error: ' + err);
diagnosticsStatusBarItem.text = 'Build Failed';
});
});
}
/**
* Runs go build -i or go test -i and presents the output in the 'Go' channel and in the diagnostic collections.
*
* @param fileUri Document uri.
* @param isMod Boolean denoting if modules are being used.
* @param goConfig Configuration for the Go extension.
* @param buildWorkspace If true builds code in all workspace.
*/
export async function goBuild(
fileUri: vscode.Uri,
isMod: boolean,
goConfig: vscode.WorkspaceConfiguration,
buildWorkspace?: boolean
): Promise<ICheckResult[]> {
epoch++;
const closureEpoch = epoch;
if (tokenSource) {
if (running) {
tokenSource.cancel();
}
tokenSource.dispose();
}
tokenSource = new vscode.CancellationTokenSource();
const updateRunning = () => {
if (closureEpoch === epoch) {
running = false;
}
};
const currentWorkspace = getWorkspaceFolderPath(fileUri);
const cwd = buildWorkspace && currentWorkspace ? currentWorkspace : path.dirname(fileUri.fsPath);
if (!path.isAbsolute(cwd)) {
return Promise.resolve([]);
}
// Skip building if cwd is in the module cache
if (isMod && cwd.startsWith(getModuleCache())) {
return [];
}
const buildEnv = toolExecutionEnvironment();
const tmpPath = getTempFilePath('go-code-check');
const isTestFile = fileUri && fileUri.fsPath.endsWith('_test.go');
const buildFlags: string[] = isTestFile
? getTestFlags(goConfig)
: Array.isArray(goConfig['buildFlags'])
? [...goConfig['buildFlags']]
: [];
const buildArgs: string[] = isTestFile ? ['test', '-c'] : ['build'];
if (goConfig['installDependenciesWhenBuilding'] === true && !isMod) {
buildArgs.push('-i');
// Remove the -i flag from user as we add it anyway
if (buildFlags.indexOf('-i') > -1) {
buildFlags.splice(buildFlags.indexOf('-i'), 1);
}
}
buildArgs.push(...buildFlags);
if (goConfig['buildTags'] && buildFlags.indexOf('-tags') === -1) {
buildArgs.push('-tags');
buildArgs.push(goConfig['buildTags']);
}
if (buildWorkspace && currentWorkspace && !isTestFile) {
outputChannel.appendLine(`Starting building the current workspace at ${currentWorkspace}`);
return getNonVendorPackages(currentWorkspace).then((pkgs) => {
running = true;
return runTool(
buildArgs.concat(Array.from(pkgs.keys())),
currentWorkspace,
'error',
true,
null,
buildEnv,
true,
tokenSource.token
).then((v) => {
updateRunning();
return v;
});
});
}
outputChannel.appendLine(`Starting building the current package at ${cwd}`);
const currentGoWorkspace = getCurrentGoWorkspaceFromGOPATH(getCurrentGoPath(), cwd);
let importPath = '.';
if (!isMod) {
// Find the right importPath instead of directly using `.`. Fixes https://github.com/Microsoft/vscode-go/issues/846
if (currentGoWorkspace && !isMod) {
importPath = cwd.substr(currentGoWorkspace.length + 1);
} else {
outputChannel.appendLine(
`Not able to determine import path of current package by using cwd: ${cwd} and Go workspace: ${currentGoWorkspace}`
);
}
}
running = true;
return runTool(
buildArgs.concat('-o', tmpPath, importPath),
cwd,
'error',
true,
null,
buildEnv,
true,
tokenSource.token
).then((v) => {
updateRunning();
return v;
});
}
let epoch = 0;
let tokenSource: vscode.CancellationTokenSource;
let running = false;