@@ -552,7 +552,7 @@ internal static async IAsyncEnumerable<DocumentId> GetChangedDocumentsAsync(Trac
552552 ArrayBuilder < Diagnostic > diagnostics ,
553553 CancellationToken cancellationToken )
554554 {
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 ) ;
556556 var hasOutOfSyncDocument = false ;
557557
558558 foreach ( var newDocument in documentDifferences . ChangedOrAdded )
@@ -833,7 +833,12 @@ internal static void MergePartialEdits(
833833 addedSymbols = [ .. addedSymbolsBuilder ] ;
834834 }
835835
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 )
837842 {
838843 var projectDiagnostics = ArrayBuilder < Diagnostic > . GetInstance ( ) ;
839844
@@ -875,8 +880,7 @@ void UpdateChangedDocumentsStaleness(bool isStale)
875880
876881 var oldSolution = DebuggingSession . LastCommittedSolution ;
877882
878- var blockUpdates = false ;
879- var hasEmitErrors = false ;
883+ var hasPersistentErrors = false ;
880884 foreach ( var newProject in solution . Projects )
881885 {
882886 try
@@ -934,7 +938,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
934938 projectDiagnostics . Add ( mvidReadError ) ;
935939
936940 Telemetry . LogProjectAnalysisSummary ( ProjectAnalysisSummary . ValidChanges , newProject . State . ProjectInfo . Attributes . TelemetryId , projectDiagnostics ) ;
937- blockUpdates = true ;
938941 continue ;
939942 }
940943
@@ -963,15 +966,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
963966 var ( changedDocumentAnalyses , hasOutOfSyncChangedDocument ) =
964967 await AnalyzeDocumentsAsync ( solution , documentDifferences , solutionActiveStatementSpanProvider , projectDiagnostics , cancellationToken ) . ConfigureAwait ( false ) ;
965968
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-
975969 if ( hasOutOfSyncChangedDocument )
976970 {
977971 // 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)
992986 {
993987 // only remember the first syntax error we encounter:
994988 syntaxError ??= changedDocumentAnalysis . SyntaxError ;
989+ hasPersistentErrors = true ;
995990
996991 Log . Write ( $ "Changed document '{ changedDocumentAnalysis . FilePath } ' has syntax error: { changedDocumentAnalysis . SyntaxError } ") ;
997992 }
@@ -1015,17 +1010,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
10151010 // an additional process that doesn't support EnC (or detaches from such process). Before we apply edits
10161011 // we need to check with the debugger.
10171012 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- }
10291013
10301014 // Report rude edit diagnostics - these can be blocking (errors) or non-blocking (warnings):
10311015 foreach ( var analysis in changedDocumentAnalyses )
@@ -1044,7 +1028,7 @@ void UpdateChangedDocumentsStaleness(bool isStale)
10441028 }
10451029 }
10461030
1047- if ( isModuleEncBlocked || projectSummary != ProjectAnalysisSummary . ValidChanges )
1031+ if ( moduleBlockingDiagnosticId != null || projectSummary != ProjectAnalysisSummary . ValidChanges )
10481032 {
10491033 Telemetry . LogProjectAnalysisSummary ( projectSummary , newProject . State . ProjectInfo . Attributes . TelemetryId , projectDiagnostics ) ;
10501034
@@ -1062,7 +1046,6 @@ void UpdateChangedDocumentsStaleness(bool isStale)
10621046 // This is consistent with reporting compilation errors - the IDE reports them for all TFMs regardless of what framework the app is running on.
10631047 Telemetry . LogProjectAnalysisSummary ( projectSummary , newProject . State . ProjectInfo . Attributes . TelemetryId , projectDiagnostics ) ;
10641048
1065- blockUpdates = true ;
10661049 await LogDocumentChangesAsync ( generation : null , cancellationToken ) . ConfigureAwait ( false ) ;
10671050 continue ;
10681051 }
@@ -1136,8 +1119,12 @@ void UpdateChangedDocumentsStaleness(bool isStale)
11361119
11371120 if ( ! emitResult . Success )
11381121 {
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.
11411128 break ;
11421129 }
11431130
@@ -1147,8 +1134,7 @@ void UpdateChangedDocumentsStaleness(bool isStale)
11471134 if ( unsupportedChangesDiagnostic is not null )
11481135 {
11491136 projectDiagnostics . Add ( unsupportedChangesDiagnostic ) ;
1150- blockUpdates = true ;
1151- break ;
1137+ continue ;
11521138 }
11531139
11541140 var updatedMethodTokens = emitResult . UpdatedMethods . SelectAsArray ( h => MetadataTokens . GetToken ( h ) ) ;
@@ -1236,30 +1222,36 @@ async ValueTask LogDocumentChangesAsync(int? generation, CancellationToken cance
12361222 }
12371223 }
12381224
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 )
12411230 {
1242- Telemetry . LogRuntimeCapabilities ( await Capabilities . GetValueAsync ( cancellationToken ) . ConfigureAwait ( false ) ) ;
1231+ return SolutionUpdate . Empty ( diagnostics , syntaxError , ModuleUpdateStatus . Blocked ) ;
12431232 }
12441233
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 ) ;
12631255 }
12641256 catch ( Exception e ) when ( LogException ( e ) && FatalError . ReportAndPropagateUnlessCanceled ( e , cancellationToken ) )
12651257 {
0 commit comments