|
204 | 204 | { |
205 | 205 | <FluentMessageBar Title="Compiler worker failed." Intent="MessageIntent.Error" AllowDismiss="false"> |
206 | 206 | <div style="white-space-collapse: preserve">@workerError</div> |
207 | | - <FluentButton Appearance="Appearance.Accent" Style="width: 100%; margin-top: 0.5em" OnClick="ReloadWorker" |
| 207 | + <FluentButton Appearance="Appearance.Accent" Style="width: 100%; margin-top: 0.5em" OnClick="ReloadWorkerAsync" |
208 | 208 | IconStart="@(new Icons.Regular.Size16.ArrowClockwise())">Re-create the worker</FluentButton> |
209 | 209 | </FluentMessageBar> |
210 | 210 | } |
|
243 | 243 | </FluentTabs> |
244 | 244 |
|
245 | 245 | @* Output toolbar *@ |
246 | | - @if (OutputHasToolbar) |
| 246 | + @if (OutputHasToolbar && GetOutput(DisplayOutputType) != null) |
247 | 247 | { |
248 | 248 | <FluentToolbar> |
249 | 249 | @switch (DisplayOutputType) |
|
252 | 252 | { |
253 | 253 | <FluentCheckbox @bind-Value:get="savedState.ShowSymbols" |
254 | 254 | @bind-Value:set="(v) => ChangePreferencesAsync((s) => s with { ShowSymbols = v })" |
255 | | - Label="Symbols" /> |
| 255 | + Label="Symbols" |
| 256 | + title="Displays symbol nodes in the tree - look for `.GetSymbolInfo()` and `.GetDeclaredSymbol()` under syntax nodes" /> |
256 | 257 | <FluentCheckbox @bind-Value:get="savedState.ShowOperations" |
257 | 258 | @bind-Value:set="(v) => ChangePreferencesAsync((s) => s with { ShowOperations = v })" |
258 | | - Label="Operations" /> |
| 259 | + Label="Operations" |
| 260 | + title="Displays IOperation nodes in the tree - look for `.GetOperation()` under syntax nodes" /> |
259 | 261 | <FluentCheckbox @bind-Value:get="savedState.ShowBoundNodes" |
260 | 262 | @bind-Value:set="(v) => ChangePreferencesAsync((s) => s with { ShowBoundNodes = v })" |
261 | | - Label="Bound nodes" /> |
| 263 | + Label="Bound nodes" |
| 264 | + title="Displays bound nodes in the tree - look for `.GetBoundRoot()` under syntax nodes" /> |
262 | 265 | <FluentButton OnClick="FoldAllOutputAsync" Title="Collapse all">@* |
263 | 266 | *@<FluentIcon Value="@(new Icons.Regular.Size20.ArrowCollapseAll())" Color="Color.Neutral" /></FluentButton> |
264 | 267 | } |
|
357 | 360 | public required DateTimeOffset Start { get; init; } |
358 | 361 | public required DateTimeOffset End { get; init; } |
359 | 362 |
|
| 363 | + public required bool AutoLoadLazyOutputs { get; init; } |
| 364 | + |
360 | 365 | /// <summary> |
361 | 366 | /// Only set if this <see cref="CompiledState"/> instance represents compiled (not cached) state |
362 | 367 | /// but we also have cached output loaded for it. |
|
1019 | 1024 | CacheInfo = cacheInfo, |
1020 | 1025 | Start = startTime, |
1021 | 1026 | End = DateTimeOffset.Now, |
| 1027 | + AutoLoadLazyOutputs = true, |
1022 | 1028 | }; |
1023 | 1029 |
|
1024 | 1030 | await DisplaySquigglesAsync(); |
|
1187 | 1193 |
|
1188 | 1194 | var text = CompilerOutputPlugin.GetText(outputInfo, result, out outputDisclaimer, ref language); |
1189 | 1195 |
|
| 1196 | + string? previousLanguage; |
| 1197 | + |
1190 | 1198 | if (!outputStates.TryGetValue(outputType, out var state)) |
1191 | 1199 | { |
1192 | 1200 | state = new(await BlazorMonaco.Editor.Global.CreateModel( |
|
1195 | 1203 | language: language, |
1196 | 1204 | uri: CompiledAssembly.GetOutputModelUri(outputInfo?.File, outputType))); |
1197 | 1205 | outputStates[outputType] = state; |
| 1206 | + previousLanguage = null; |
1198 | 1207 | } |
1199 | 1208 | else |
1200 | 1209 | { |
1201 | 1210 | await state.Model.SetValue(text); |
| 1211 | + previousLanguage = await state.Model.GetLanguageId(); |
1202 | 1212 | await BlazorMonaco.Editor.Global.SetModelLanguage(JSRuntime, state.Model, language); |
1203 | 1213 | } |
1204 | 1214 |
|
|
1216 | 1226 |
|
1217 | 1227 | await outputEditor.SetModel(state.Model); |
1218 | 1228 |
|
1219 | | - if (saveViewState && !state.ViewState.IsEmpty) |
| 1229 | + if (saveViewState && !state.ViewState.IsEmpty && |
| 1230 | + // Avoid restoring state (and instead perform folding) when state changes drastically |
| 1231 | + // (currently we only detect language change - e.g., from error to normal output). |
| 1232 | + previousLanguage == language) |
1220 | 1233 | { |
1221 | 1234 | await outputEditor.RestoreViewStateAsync(state.ViewState, module); |
1222 | 1235 | } |
1223 | 1236 | else if (isOutputLanguage) |
1224 | 1237 | { |
1225 | 1238 | await FoldAllOutputAsync(); |
| 1239 | + } |
1226 | 1240 |
|
| 1241 | + if (isOutputLanguage) |
| 1242 | + { |
1227 | 1243 | // Underline links. |
1228 | 1244 | if (result.Metadata != null && |
1229 | 1245 | LanguageServices.TryGetOutputToOutputMapping(result.Metadata, out var mapping)) |
|
1251 | 1267 | await BlazorMonacoInterop.ExecuteActionAsync(outputEditor.Id, "editor.unfold"); |
1252 | 1268 | } |
1253 | 1269 |
|
1254 | | - private OutputInfo? GetOutput(string type) |
| 1270 | + private OutputInfo? GetOutput(string? type) |
1255 | 1271 | { |
| 1272 | + if (type is null) |
| 1273 | + { |
| 1274 | + return null; |
| 1275 | + } |
| 1276 | + |
1256 | 1277 | if (CurrentCompiledFile is { } currentCompiledFile) |
1257 | 1278 | { |
1258 | 1279 | if (currentCompiledFile.GetOutput(type) is { } output) |
|
1323 | 1344 |
|
1324 | 1345 | // If we are currently displaying cached outputs, but this specific output type is not cached, |
1325 | 1346 | // avoid resolving it and hence starting compilation implicitly. |
1326 | | - if (compiled is { CacheInfo: not null, CachedOutput: null }) |
| 1347 | + if (compiled?.AutoLoadLazyOutputs != true) |
1327 | 1348 | { |
1328 | 1349 | return (new() { Text = "(not cached, press Compile to load this)", Metadata = CompiledFileOutputMetadata.SpecialMessage }, false); |
1329 | 1350 | } |
|
1429 | 1450 | await TrySetCompiledFromCacheAsync(state.GetCompilerConfiguration(), state.ToCompilationInput(), output, new(timestamp), updateOutput: updateOutput); |
1430 | 1451 | StateHasChanged(); |
1431 | 1452 | } |
| 1453 | + else if (updateOutput) |
| 1454 | + { |
| 1455 | + await AutoSelectOutputAsync( |
| 1456 | + updateTimestampMode: OutputActionMode.Never, |
| 1457 | + storeInCacheMode: OutputActionMode.Never); |
| 1458 | + } |
1432 | 1459 | } |
1433 | 1460 |
|
1434 | 1461 | private async Task TrySetCompiledFromCacheAsync(CompilerConfiguration config, CompilationInput input, CompiledAssembly output, CacheInfo info, bool updateOutput) |
|
1452 | 1479 | Output = output, |
1453 | 1480 | CacheInfo = info, |
1454 | 1481 | Start = timestamp, |
1455 | | - End = timestamp |
| 1482 | + End = timestamp, |
| 1483 | + AutoLoadLazyOutputs = false, |
1456 | 1484 | }; |
1457 | 1485 | StateHasChanged(); |
1458 | 1486 |
|
|
1570 | 1598 | StateHasChanged(); |
1571 | 1599 | } |
1572 | 1600 |
|
1573 | | - private void ReloadWorker() |
| 1601 | + internal async Task ReloadWorkerAsync() |
1574 | 1602 | { |
| 1603 | + await Worker.RecreateWorkerAsync(); |
1575 | 1604 | workerError = null; |
1576 | | - StateHasChanged(); |
1577 | | - _ = Worker.RecreateWorkerAsync(); |
1578 | 1605 | } |
1579 | 1606 | } |
0 commit comments