15
15
*/
16
16
package com .google .idea .blaze .base .run .confighandler ;
17
17
18
- import static com .google .common .base .Verify .verify ;
19
-
20
18
import com .google .common .base .Preconditions ;
21
19
import com .google .common .collect .ImmutableList ;
22
- import com .google .common .util .concurrent .FutureCallback ;
23
- import com .google .common .util .concurrent .Futures ;
24
- import com .google .common .util .concurrent .ListenableFuture ;
25
- import com .google .idea .blaze .base .async .executor .BlazeExecutor ;
26
20
import com .google .idea .blaze .base .async .process .LineProcessingOutputStream ;
27
21
import com .google .idea .blaze .base .bazel .BuildSystem .BuildInvoker ;
28
22
import com .google .idea .blaze .base .command .BlazeCommand ;
29
23
import com .google .idea .blaze .base .command .BlazeCommandName ;
30
24
import com .google .idea .blaze .base .command .BlazeFlags ;
31
25
import com .google .idea .blaze .base .command .BlazeInvocationContext ;
32
- import com .google .idea .blaze .base .command .buildresult .BuildResultParser ;
33
- import com .google .idea .blaze .base .command .buildresult .bepparser .BuildEventStreamProvider ;
26
+ import com .google .idea .blaze .base .command .buildresult .BuildResultHelperBep ;
34
27
import com .google .idea .blaze .base .console .BlazeConsoleLineProcessorProvider ;
35
28
import com .google .idea .blaze .base .issueparser .ToolWindowTaskIssueOutputFilter ;
36
29
import com .google .idea .blaze .base .model .primitives .WorkspaceRoot ;
44
37
import com .google .idea .blaze .base .run .smrunner .BlazeTestUiSession ;
45
38
import com .google .idea .blaze .base .run .smrunner .SmRunnerUtils ;
46
39
import com .google .idea .blaze .base .run .state .BlazeCommandRunConfigurationCommonState ;
47
- import com .google .idea .blaze .base .run .testlogs .BlazeTestResultFinderStrategy ;
48
- import com .google .idea .blaze .base .run .testlogs .BlazeTestResultHolder ;
49
- import com .google .idea .blaze .base .run .testlogs .BlazeTestResults ;
40
+ import com .google .idea .blaze .base .run .testlogs .LocalBuildEventProtocolTestFinderStrategy ;
50
41
import com .google .idea .blaze .base .scope .BlazeContext ;
51
42
import com .google .idea .blaze .base .scope .OutputSink ;
52
43
import com .google .idea .blaze .base .scope .scopes .IdeaLogScope ;
55
46
import com .google .idea .blaze .base .settings .BlazeImportSettings ;
56
47
import com .google .idea .blaze .base .settings .BlazeImportSettingsManager ;
57
48
import com .google .idea .blaze .base .settings .BlazeUserSettings ;
58
- import com .google .idea .blaze .base .sync .aspects .BlazeBuildOutputs ;
59
- import com .google .idea .blaze .common .Interners ;
60
49
import com .google .idea .blaze .common .PrintOutput ;
61
50
import com .google .idea .blaze .common .PrintOutput .OutputType ;
62
51
import com .intellij .execution .DefaultExecutionResult ;
70
59
import com .intellij .execution .filters .Filter ;
71
60
import com .intellij .execution .filters .TextConsoleBuilderImpl ;
72
61
import com .intellij .execution .filters .UrlFilter ;
73
- import com .intellij .execution .process .ProcessAdapter ;
74
- import com .intellij .execution .process .ProcessEvent ;
75
62
import com .intellij .execution .process .ProcessHandler ;
76
63
import com .intellij .execution .process .ProcessListener ;
77
64
import com .intellij .execution .runners .ExecutionEnvironment ;
78
65
import com .intellij .execution .runners .ProgramRunner ;
79
66
import com .intellij .execution .ui .ConsoleView ;
80
67
import com .intellij .execution .ui .ConsoleViewContentType ;
81
- import com .intellij .openapi .application .ApplicationManager ;
82
68
import com .intellij .openapi .project .Project ;
83
- import java .io .OutputStream ;
84
69
import java .util .ArrayList ;
85
70
import java .util .List ;
86
71
import java .util .Map ;
87
- import org .jetbrains .annotations .NotNull ;
88
- import org .jetbrains .annotations .Nullable ;
89
72
90
73
/**
91
74
* Generic runner for {@link BlazeCommandRunConfiguration}s, used as a fallback in the case where no
@@ -107,6 +90,7 @@ public boolean executeBeforeRunTask(ExecutionEnvironment environment) {
107
90
108
91
/** {@link RunProfileState} for generic blaze commands. */
109
92
public static class BlazeCommandRunProfileState extends CommandLineState {
93
+
110
94
private static final int BLAZE_BUILD_INTERRUPTED = 8 ;
111
95
private final BlazeCommandRunConfiguration configuration ;
112
96
private final BlazeCommandRunConfigurationCommonState handlerState ;
@@ -148,8 +132,8 @@ protected ProcessHandler startProcess() throws ExecutionException {
148
132
ProjectViewSet projectViewSet = ProjectViewManager .getInstance (project ).getProjectViewSet ();
149
133
assert projectViewSet != null ;
150
134
BlazeContext context = BlazeContext .create ();
151
- BuildInvoker invoker =
152
- Blaze . getBuildSystemProvider ( project ). getBuildSystem (). getBuildInvoker ( project );
135
+ BuildInvoker invoker = Blaze . getBuildSystemProvider ( project ). getBuildSystem (). getBuildInvoker ( project );
136
+ WorkspaceRoot workspaceRoot = WorkspaceRoot . fromImportSettings ( importSettings );
153
137
BlazeCommand .Builder blazeCommand =
154
138
getBlazeCommand (
155
139
project ,
@@ -158,109 +142,67 @@ protected ProcessHandler startProcess() throws ExecutionException {
158
142
ImmutableList .of (),
159
143
context );
160
144
return isTest ()
161
- ? getProcessHandlerForTests (project , invoker , blazeCommand , context )
162
- : getProcessHandlerForNonTests (project , invoker , blazeCommand , context );
163
- }
164
-
165
- private ProcessHandler getGenericProcessHandler () {
166
- return new ProcessHandler () {
167
- @ Override
168
- protected void destroyProcessImpl () {
169
- notifyProcessTerminated (BLAZE_BUILD_INTERRUPTED );
170
- }
171
-
172
- @ Override
173
- protected void detachProcessImpl () {
174
- ApplicationManager .getApplication ().executeOnPooledThread (this ::notifyProcessDetached );
175
- }
176
-
177
- @ Override
178
- public boolean detachIsDefault () {
179
- return false ;
180
- }
181
-
182
- @ Nullable
183
- @ Override
184
- public OutputStream getProcessInput () {
185
- return null ;
186
- }
187
- };
145
+ ? getProcessHandlerForTests (project , blazeCommand , workspaceRoot , context )
146
+ : getScopedProcessHandler (project , blazeCommand .build (), workspaceRoot );
188
147
}
189
148
190
- private ProcessHandler getProcessHandlerForNonTests (
149
+ private ProcessHandler getScopedProcessHandler (
191
150
Project project ,
192
- BuildInvoker invoker ,
193
- BlazeCommand . Builder blazeCommandBuilder ,
194
- BlazeContext context )
151
+ BlazeCommand blazeCommand ,
152
+ WorkspaceRoot workspaceRoot
153
+ )
195
154
throws ExecutionException {
196
- ProcessHandler processHandler = getGenericProcessHandler ();
197
- ConsoleView consoleView = getConsoleBuilder ().getConsole ();
198
- context .addOutputSink (PrintOutput .class , new WritingOutputSink (consoleView ));
199
- setConsoleBuilder (
200
- new TextConsoleBuilderImpl (project ) {
201
- @ Override
202
- protected ConsoleView createConsole () {
203
- return consoleView ;
204
- }
205
- });
206
- addConsoleFilters (consoleFilters .toArray (new Filter [0 ]));
207
-
208
- @ NotNull Map <String , String > envVars = handlerState .getUserEnvVarsState ().getData ().getEnvs ();
209
- ListenableFuture <BlazeBuildOutputs > blazeBuildOutputsListenableFuture =
210
- BlazeExecutor .getInstance ()
211
- .submit (
212
- () -> {
213
- try (BuildEventStreamProvider streamProvider =
214
- invoker .invoke (blazeCommandBuilder , context )) {
215
- return BlazeBuildOutputs .fromParsedBepOutput (
216
- BuildResultParser .getBuildOutput (streamProvider , Interners .STRING ));
217
- }
218
- });
219
- Futures .addCallback (
220
- blazeBuildOutputsListenableFuture ,
221
- new FutureCallback <BlazeBuildOutputs >() {
222
- @ Override
223
- public void onSuccess (BlazeBuildOutputs blazeBuildOutputs ) {
224
- processHandler .detachProcess ();
225
- }
226
-
155
+ GeneralCommandLine commandLine = new GeneralCommandLine (blazeCommand .toList ());
156
+ EnvironmentVariablesData envVarState = handlerState .getUserEnvVarsState ().getData ();
157
+ commandLine .withEnvironment (envVarState .getEnvs ());
158
+ commandLine .withParentEnvironmentType (
159
+ envVarState .isPassParentEnvs ()
160
+ ? GeneralCommandLine .ParentEnvironmentType .CONSOLE
161
+ : GeneralCommandLine .ParentEnvironmentType .NONE );
162
+ return new ScopedBlazeProcessHandler (
163
+ project ,
164
+ commandLine ,
165
+ workspaceRoot ,
166
+ new ScopedBlazeProcessHandler .ScopedProcessHandlerDelegate () {
227
167
@ Override
228
- public void onFailure (Throwable throwable ) {
229
- context .handleException (throwable .getMessage (), throwable );
230
- processHandler .detachProcess ();
168
+ public void onBlazeContextStart (BlazeContext context ) {
169
+ context
170
+ .push (
171
+ new ProblemsViewScope (
172
+ project , BlazeUserSettings .getInstance ().getShowProblemsViewOnRun ()))
173
+ .push (new IdeaLogScope ());
231
174
}
232
- },
233
- BlazeExecutor .getInstance ().getExecutor ());
234
175
235
- processHandler .addProcessListener (
236
- new ProcessAdapter () {
237
176
@ Override
238
- public void processWillTerminate (@ NotNull ProcessEvent event , boolean willBeDestroyed ) {
239
- if (willBeDestroyed ) {
240
- context .setCancelled ();
241
- }
177
+ public ImmutableList <ProcessListener > createProcessListeners (BlazeContext context ) {
178
+ LineProcessingOutputStream outputStream =
179
+ LineProcessingOutputStream .of (
180
+ BlazeConsoleLineProcessorProvider .getAllStderrLineProcessors (context ));
181
+ return ImmutableList .of (new LineProcessingProcessAdapter (outputStream ));
242
182
}
243
183
});
244
- return processHandler ;
245
184
}
246
185
247
186
private ProcessHandler getProcessHandlerForTests (
248
187
Project project ,
249
- BuildInvoker invoker ,
250
188
BlazeCommand .Builder blazeCommandBuilder ,
251
- BlazeContext context ) {
252
- BlazeTestResultFinderStrategy testResultFinderStrategy = new BlazeTestResultHolder ();
253
- BlazeTestUiSession testUiSession = null ;
189
+ WorkspaceRoot workspaceRoot ,
190
+ BlazeContext context
191
+ ) throws ExecutionException {
192
+ // TODO: find proper place to close the result helper (same for BlazeCidrLauncher)
193
+ final var buildResultHelper = new BuildResultHelperBep ();
194
+ final var testResultFinderStrategy = new LocalBuildEventProtocolTestFinderStrategy (buildResultHelper .getOutputFile ());
195
+
254
196
if (BlazeTestEventsHandler .targetsSupported (project , configuration .getTargets ())) {
255
- testUiSession =
197
+ final var testUiSession =
256
198
BlazeTestUiSession .create (
257
199
ImmutableList .<String >builder ()
258
200
.add ("--runs_per_test=1" )
259
201
.add ("--flaky_test_attempts=1" )
202
+ .addAll (buildResultHelper .getBuildFlags ())
260
203
.build (),
261
204
testResultFinderStrategy );
262
- }
263
- if (testUiSession != null ) {
205
+
264
206
ConsoleView consoleView =
265
207
SmRunnerUtils .getConsoleView (
266
208
project , configuration , getEnvironment ().getExecutor (), testUiSession );
@@ -272,76 +214,19 @@ protected ConsoleView createConsole() {
272
214
}
273
215
});
274
216
context .addOutputSink (PrintOutput .class , new WritingOutputSink (consoleView ));
275
- }
276
- addConsoleFilters (consoleFilters .toArray (new Filter [0 ]));
277
- @ NotNull Map <String , String > envVars = handlerState .getUserEnvVarsState ().getData ().getEnvs ();
278
217
279
- if (invoker .getCommandRunner ().canUseCli ()) {
280
- // If we can use the CLI, that means we will run through Bazel (as opposed to a raw process handler)
281
- // When running `bazel test`, bazel will not forward the environment to the tests themselves -- we need to use
282
- // the --test_env flag for that. Therefore, we convert all the env vars to --test_env flags here.
283
- for (Map .Entry <String , String > env : envVars .entrySet ()) {
284
- blazeCommandBuilder .addBlazeFlags (BlazeFlags .TEST_ENV , String .format ("%s=%s" , env .getKey (), env .getValue ()));
285
- }
218
+ blazeCommandBuilder .addBlazeFlags (testUiSession .getBlazeFlags ());
286
219
}
287
- return getCommandRunnerProcessHandlerForTests (
288
- invoker , blazeCommandBuilder , testResultFinderStrategy , context );
289
- }
290
220
291
- private ProcessHandler getCommandRunnerProcessHandlerForTests (
292
- BuildInvoker invoker ,
293
- BlazeCommand .Builder blazeCommandBuilder ,
294
- BlazeTestResultFinderStrategy testResultFinderStrategy ,
295
- BlazeContext context ) {
296
- ProcessHandler processHandler = getGenericProcessHandler ();
297
- @ NotNull Map <String , String > envVars = handlerState .getUserEnvVarsState ().getData ().getEnvs ();
298
- ListenableFuture <BlazeTestResults > blazeTestResultsFuture =
299
- BlazeExecutor .getInstance ()
300
- .submit (
301
- () -> {
302
- try (BuildEventStreamProvider streamProvider =
303
- invoker .invoke (blazeCommandBuilder , context )) {
304
- return BuildResultParser .getTestResults (streamProvider );
305
- }
306
- });
307
- Futures .addCallback (
308
- blazeTestResultsFuture ,
309
- new FutureCallback <BlazeTestResults >() {
310
- @ Override
311
- public void onSuccess (BlazeTestResults blazeTestResults ) {
312
- // The command-runners allow using a remote BES for parsing the test results, so we
313
- // use a BlazeTestResultHolder to store the test results for the IDE to find/read
314
- // later. The LocalTestResultFinderStrategy won't work here since it writes/reads the
315
- // test results to a local file.
316
- verify (testResultFinderStrategy instanceof BlazeTestResultHolder );
317
- ((BlazeTestResultHolder ) testResultFinderStrategy ).setTestResults (blazeTestResults );
318
- processHandler .detachProcess ();
319
- }
221
+ addConsoleFilters (consoleFilters .toArray (new Filter [0 ]));
320
222
321
- @ Override
322
- public void onFailure (Throwable throwable ) {
323
- context .handleException (throwable .getMessage (), throwable );
324
- verify (testResultFinderStrategy instanceof BlazeTestResultHolder );
325
- ((BlazeTestResultHolder ) testResultFinderStrategy )
326
- .setTestResults (BlazeTestResults .NO_RESULTS );
327
- processHandler .detachProcess ();
328
- }
329
- },
330
- BlazeExecutor .getInstance ().getExecutor ());
223
+ // When running `bazel test`, bazel will not forward the environment to the tests themselves -- we need to use
224
+ // the --test_env flag for that. Therefore, we convert all the env vars to --test_env flags here.
225
+ for (Map .Entry <String , String > env : handlerState .getUserEnvVarsState ().getData ().getEnvs ().entrySet ()) {
226
+ blazeCommandBuilder .addBlazeFlags (BlazeFlags .TEST_ENV , String .format ("%s=%s" , env .getKey (), env .getValue ()));
227
+ }
331
228
332
- processHandler .addProcessListener (
333
- new ProcessAdapter () {
334
- @ Override
335
- public void processWillTerminate (@ NotNull ProcessEvent event , boolean willBeDestroyed ) {
336
- if (willBeDestroyed ) {
337
- context .setCancelled ();
338
- verify (testResultFinderStrategy instanceof BlazeTestResultHolder );
339
- ((BlazeTestResultHolder ) testResultFinderStrategy )
340
- .setTestResults (BlazeTestResults .NO_RESULTS );
341
- }
342
- }
343
- });
344
- return processHandler ;
229
+ return getScopedProcessHandler (project , blazeCommandBuilder .build (), workspaceRoot );
345
230
}
346
231
347
232
private BlazeCommand .Builder getBlazeCommand (
0 commit comments