@@ -552,7 +552,7 @@ internal static async IAsyncEnumerable<DocumentId> GetChangedDocumentsAsync(Trac
552
552
ArrayBuilder < Diagnostic > diagnostics ,
553
553
CancellationToken cancellationToken )
554
554
{
555
- using var _2 = ArrayBuilder < ( Document ? oldDocument , Document ? newDocument ) > . GetInstance ( out var documents ) ;
555
+ using var _ = ArrayBuilder < ( Document ? oldDocument , Document ? newDocument ) > . GetInstance ( out var documents ) ;
556
556
var hasOutOfSyncDocument = false ;
557
557
558
558
foreach ( var newDocument in documentDifferences . ChangedOrAdded )
@@ -833,7 +833,12 @@ internal static void MergePartialEdits(
833
833
addedSymbols = [ .. addedSymbolsBuilder ] ;
834
834
}
835
835
836
- public async ValueTask < SolutionUpdate > EmitSolutionUpdateAsync ( Solution solution , ActiveStatementSpanProvider solutionActiveStatementSpanProvider , UpdateId updateId , CancellationToken cancellationToken )
836
+ public async ValueTask < SolutionUpdate > EmitSolutionUpdateAsync (
837
+ Solution solution ,
838
+ ActiveStatementSpanProvider solutionActiveStatementSpanProvider ,
839
+ UpdateId updateId ,
840
+ ImmutableDictionary < ProjectId , RunningProjectInfo > runningProjects ,
841
+ CancellationToken cancellationToken )
837
842
{
838
843
var projectDiagnostics = ArrayBuilder < Diagnostic > . GetInstance ( ) ;
839
844
@@ -875,8 +880,7 @@ void UpdateChangedDocumentsStaleness(bool isStale)
875
880
876
881
var oldSolution = DebuggingSession . LastCommittedSolution ;
877
882
878
- var blockUpdates = false ;
879
- var hasEmitErrors = false ;
883
+ var hasPersistentErrors = false ;
880
884
foreach ( var newProject in solution . Projects )
881
885
{
882
886
try
@@ -934,7 +938,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
934
938
projectDiagnostics . Add ( mvidReadError ) ;
935
939
936
940
Telemetry . LogProjectAnalysisSummary ( ProjectAnalysisSummary . ValidChanges , newProject . State . ProjectInfo . Attributes . TelemetryId , projectDiagnostics ) ;
937
- blockUpdates = true ;
938
941
continue ;
939
942
}
940
943
@@ -963,15 +966,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
963
966
var ( changedDocumentAnalyses , hasOutOfSyncChangedDocument ) =
964
967
await AnalyzeDocumentsAsync ( solution , documentDifferences , solutionActiveStatementSpanProvider , projectDiagnostics , cancellationToken ) . ConfigureAwait ( false ) ;
965
968
966
- // The diagnostic hasn't been reported by GetDocumentDiagnosticsAsync since out-of-sync documents are likely to be synchronized
967
- // before the changes are attempted to be applied. If we still have any out-of-sync documents we report warnings and ignore changes in them.
968
- // If in future the file is updated so that its content matches the PDB checksum, the document transitions to a matching state,
969
- // and we consider any further changes to it for application.
970
- if ( projectDiagnostics . Any ( static d => d . IsDocumentReadError ( ) ) )
971
- {
972
- blockUpdates = true ;
973
- }
974
-
975
969
if ( hasOutOfSyncChangedDocument )
976
970
{
977
971
// The project is considered stale as long as it has at least one document that is out-of-sync.
@@ -992,6 +986,7 @@ void UpdateChangedDocumentsStaleness(bool isStale)
992
986
{
993
987
// only remember the first syntax error we encounter:
994
988
syntaxError ??= changedDocumentAnalysis . SyntaxError ;
989
+ hasPersistentErrors = true ;
995
990
996
991
Log . Write ( $ "Changed document '{ changedDocumentAnalysis . FilePath } ' has syntax error: { changedDocumentAnalysis . SyntaxError } ") ;
997
992
}
@@ -1015,17 +1010,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
1015
1010
// an additional process that doesn't support EnC (or detaches from such process). Before we apply edits
1016
1011
// we need to check with the debugger.
1017
1012
var moduleBlockingDiagnosticId = await ReportModuleDiagnosticsAsync ( mvid , oldProject , newProject , changedDocumentAnalyses , projectDiagnostics , cancellationToken ) . ConfigureAwait ( false ) ;
1018
- var isModuleEncBlocked = moduleBlockingDiagnosticId != null ;
1019
-
1020
- if ( isModuleEncBlocked )
1021
- {
1022
- blockUpdates = true ;
1023
- }
1024
-
1025
- if ( projectSummary is ProjectAnalysisSummary . SyntaxErrors or ProjectAnalysisSummary . RudeEdits )
1026
- {
1027
- blockUpdates = true ;
1028
- }
1029
1013
1030
1014
// Report rude edit diagnostics - these can be blocking (errors) or non-blocking (warnings):
1031
1015
foreach ( var analysis in changedDocumentAnalyses )
@@ -1044,7 +1028,7 @@ void UpdateChangedDocumentsStaleness(bool isStale)
1044
1028
}
1045
1029
}
1046
1030
1047
- if ( isModuleEncBlocked || projectSummary != ProjectAnalysisSummary . ValidChanges )
1031
+ if ( moduleBlockingDiagnosticId != null || projectSummary != ProjectAnalysisSummary . ValidChanges )
1048
1032
{
1049
1033
Telemetry . LogProjectAnalysisSummary ( projectSummary , newProject . State . ProjectInfo . Attributes . TelemetryId , projectDiagnostics ) ;
1050
1034
@@ -1062,7 +1046,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
1062
1046
// This is consistent with reporting compilation errors - the IDE reports them for all TFMs regardless of what framework the app is running on.
1063
1047
Telemetry . LogProjectAnalysisSummary ( projectSummary , newProject . State . ProjectInfo . Attributes . TelemetryId , projectDiagnostics ) ;
1064
1048
1065
- blockUpdates = true ;
1066
1049
await LogDocumentChangesAsync ( generation : null , cancellationToken ) . ConfigureAwait ( false ) ;
1067
1050
continue ;
1068
1051
}
@@ -1136,8 +1119,12 @@ void UpdateChangedDocumentsStaleness(bool isStale)
1136
1119
1137
1120
if ( ! emitResult . Success )
1138
1121
{
1139
- // error
1140
- blockUpdates = hasEmitErrors = true ;
1122
+ hasPersistentErrors = true ;
1123
+
1124
+ // Stop emitting deltas, we will discard the updates emitted so far.
1125
+ // Persistent errors need to be fixed before we attempt rebuilding the projects.
1126
+ // The baseline solution snapshot will not be moved forward and next call to
1127
+ // EmitSolutionUpdatesAsync will calculate changes for all updated projects again.
1141
1128
break ;
1142
1129
}
1143
1130
@@ -1147,8 +1134,7 @@ void UpdateChangedDocumentsStaleness(bool isStale)
1147
1134
if ( unsupportedChangesDiagnostic is not null )
1148
1135
{
1149
1136
projectDiagnostics . Add ( unsupportedChangesDiagnostic ) ;
1150
- blockUpdates = true ;
1151
- break ;
1137
+ continue ;
1152
1138
}
1153
1139
1154
1140
var updatedMethodTokens = emitResult . UpdatedMethods . SelectAsArray ( h => MetadataTokens . GetToken ( h ) ) ;
@@ -1236,30 +1222,36 @@ async ValueTask LogDocumentChangesAsync(int? generation, CancellationToken cance
1236
1222
}
1237
1223
}
1238
1224
1239
- // log capabilities for edit sessions with changes or reported errors:
1240
- if ( blockUpdates || deltas . Count > 0 )
1225
+ var diagnostics = diagnosticBuilders . SelectAsArray ( entry => new ProjectDiagnostics ( entry . Key , entry . Value . ToImmutableAndFree ( ) ) ) ;
1226
+
1227
+ Telemetry . LogRuntimeCapabilities ( await Capabilities . GetValueAsync ( cancellationToken ) . ConfigureAwait ( false ) ) ;
1228
+
1229
+ if ( hasPersistentErrors )
1241
1230
{
1242
- Telemetry . LogRuntimeCapabilities ( await Capabilities . GetValueAsync ( cancellationToken ) . ConfigureAwait ( false ) ) ;
1231
+ return SolutionUpdate . Empty ( diagnostics , syntaxError , ModuleUpdateStatus . Blocked ) ;
1243
1232
}
1244
1233
1245
- var diagnostics = diagnosticBuilders . SelectAsArray ( entry => new ProjectDiagnostics ( entry . Key , entry . Value . ToImmutableAndFree ( ) ) ) ;
1246
-
1247
- var update = blockUpdates
1248
- ? SolutionUpdate . Empty (
1249
- diagnostics ,
1250
- syntaxError ,
1251
- syntaxError != null || hasEmitErrors ? ModuleUpdateStatus . Blocked : ModuleUpdateStatus . RestartRequired )
1252
- : new SolutionUpdate (
1253
- new ModuleUpdates (
1254
- ( deltas . Count > 0 ) ? ModuleUpdateStatus . Ready : ModuleUpdateStatus . None ,
1255
- deltas . ToImmutable ( ) ) ,
1256
- projectsToStale . ToImmutable ( ) ,
1257
- nonRemappableRegions . ToImmutable ( ) ,
1258
- newProjectBaselines . ToImmutable ( ) ,
1259
- diagnostics ,
1260
- syntaxError ) ;
1261
-
1262
- return update ;
1234
+ var updates = deltas . ToImmutable ( ) ;
1235
+
1236
+ EmitSolutionUpdateResults . GetProjectsToRebuildAndRestart (
1237
+ solution ,
1238
+ updates ,
1239
+ diagnostics ,
1240
+ runningProjects ,
1241
+ out var projectsToRestart ,
1242
+ out var projectsToRebuild ) ;
1243
+
1244
+ var moduleUpdates = new ModuleUpdates ( deltas . IsEmpty && projectsToRebuild . IsEmpty ? ModuleUpdateStatus . None : ModuleUpdateStatus . Ready , updates ) ;
1245
+
1246
+ return new SolutionUpdate (
1247
+ moduleUpdates ,
1248
+ projectsToStale . ToImmutable ( ) ,
1249
+ nonRemappableRegions . ToImmutable ( ) ,
1250
+ newProjectBaselines . ToImmutable ( ) ,
1251
+ diagnostics ,
1252
+ syntaxError ,
1253
+ projectsToRestart ,
1254
+ projectsToRebuild ) ;
1263
1255
}
1264
1256
catch ( Exception e ) when ( LogException ( e ) && FatalError . ReportAndPropagateUnlessCanceled ( e , cancellationToken ) )
1265
1257
{
0 commit comments