From 9237e6692656b799e76be86de661447936d54239 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 25 Aug 2021 13:52:05 +1000 Subject: [PATCH 1/3] Report diagnostic when compiler synthesized new types and runtime doesn't support it --- .../EditAndContinueWorkspaceServiceTests.cs | 38 +++++++++++++++++ .../EditAndContinueDiagnosticDescriptors.cs | 1 + .../EditAndContinueErrorCode.cs | 1 + .../Portable/EditAndContinue/EditSession.cs | 41 ++++++++++++++++++- .../Core/Portable/FeaturesResources.resx | 3 ++ .../Portable/xlf/FeaturesResources.cs.xlf | 5 +++ .../Portable/xlf/FeaturesResources.de.xlf | 5 +++ .../Portable/xlf/FeaturesResources.es.xlf | 5 +++ .../Portable/xlf/FeaturesResources.fr.xlf | 5 +++ .../Portable/xlf/FeaturesResources.it.xlf | 5 +++ .../Portable/xlf/FeaturesResources.ja.xlf | 5 +++ .../Portable/xlf/FeaturesResources.ko.xlf | 5 +++ .../Portable/xlf/FeaturesResources.pl.xlf | 5 +++ .../Portable/xlf/FeaturesResources.pt-BR.xlf | 5 +++ .../Portable/xlf/FeaturesResources.ru.xlf | 5 +++ .../Portable/xlf/FeaturesResources.tr.xlf | 5 +++ .../xlf/FeaturesResources.zh-Hans.xlf | 5 +++ .../xlf/FeaturesResources.zh-Hant.xlf | 5 +++ 18 files changed, 148 insertions(+), 1 deletion(-) diff --git a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs index b53f1653e4ad5..26aa1cc28ae85 100644 --- a/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs +++ b/src/EditorFeatures/Test/EditAndContinue/EditAndContinueWorkspaceServiceTests.cs @@ -1659,6 +1659,44 @@ public async Task Capabilities() EndDebuggingSession(debuggingSession); } + [Fact] + public async Task Capabilities_SynthesizedNewType() + { + var source1 = "class C { void M() { } }"; + var source2 = "class C { void M() { var x = new { Goo = 1 }; } }"; + + using var _ = CreateWorkspace(out var solution, out var service); + solution = AddDefaultTestProject(solution, new[] { source1 }); + var project = solution.Projects.Single(); + solution = solution.WithProjectParseOptions(project.Id, new CSharpParseOptions(LanguageVersion.CSharp10)); + var documentId = solution.Projects.Single().Documents.Single().Id; + + EmitAndLoadLibraryToDebuggee(source1); + + // attached to processes that doesn't allow creating new types + _debuggerService.GetCapabilitiesImpl = () => ImmutableArray.Create("Baseline"); + + // F5 + var debuggingSession = await StartDebuggingSessionAsync(service, solution); + + // update document: + solution = solution.WithDocumentText(documentId, SourceText.From(source2, Encoding.UTF8)); + var document2 = solution.Projects.Single().Documents.Single(); + + // These errors aren't reported as document diagnostics + var diagnostics = await service.GetDocumentDiagnosticsAsync(solution.GetDocument(documentId), s_noActiveSpans, CancellationToken.None); + AssertEx.Empty(diagnostics); + + // They are reported as emit diagnostics + var (updates, emitDiagnostics) = await EmitSolutionUpdateAsync(debuggingSession, solution); + AssertEx.Equal(new[] { $"{document2.Project.Id} Error ENC1007: {FeaturesResources.ChangesRequiredSynthesizedType}" }, InspectDiagnostics(emitDiagnostics)); + + // no emitted delta: + Assert.Empty(updates.Updates); + + EndDebuggingSession(debuggingSession); + } + [Fact] public async Task ValidSignificantChange_EmitError() { diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs index ec65ce92bf5b3..d0657ef43aeb5 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs @@ -170,6 +170,7 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddGeneralDiagnostic(EditAndContinueErrorCode.ChangesDisallowedWhileStoppedAtException, nameof(FeaturesResources.ChangesDisallowedWhileStoppedAtException)); AddGeneralDiagnostic(EditAndContinueErrorCode.DocumentIsOutOfSyncWithDebuggee, nameof(FeaturesResources.DocumentIsOutOfSyncWithDebuggee), DiagnosticSeverity.Warning); AddGeneralDiagnostic(EditAndContinueErrorCode.UnableToReadSourceFileOrPdb, nameof(FeaturesResources.UnableToReadSourceFileOrPdb), DiagnosticSeverity.Warning); + AddGeneralDiagnostic(EditAndContinueErrorCode.ChangeResultsInSynthesizedType, nameof(FeaturesResources.ChangesRequiredSynthesizedType)); s_descriptors = builder.ToImmutable(); } diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs index f83be85d2fe91..78a21fef941d8 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs @@ -12,5 +12,6 @@ internal enum EditAndContinueErrorCode ChangesDisallowedWhileStoppedAtException = 4, DocumentIsOutOfSyncWithDebuggee = 5, UnableToReadSourceFileOrPdb = 6, + ChangeResultsInSynthesizedType = 7, } } diff --git a/src/Features/Core/Portable/EditAndContinue/EditSession.cs b/src/Features/Core/Portable/EditAndContinue/EditSession.cs index f8f73e3d5ad07..27bb90dc3c4ae 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditSession.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditSession.cs @@ -113,6 +113,40 @@ internal EditSession( Analyses = new EditAndContinueDocumentAnalysesCache(BaseActiveStatements, Capabilities); } + /// + /// The compiler has various scenarios that will cause it to synthesize things that might not be covered + /// by existing rude edits, but we still need to ensure the runtime supports them before we proceed. + /// + private async Task GetUnsupportedChangesDiagnosticAsync(EmitDifferenceResult emitResult, CancellationToken cancellationToken) + { + if (!emitResult.Success) + { + return null; + } + + if (emitResult.Baseline is null) + { + return null; + } + + var capabilities = await Capabilities.GetValueAsync(cancellationToken).ConfigureAwait(false); + if (!capabilities.HasFlag(EditAndContinueCapabilities.NewTypeDefinition)) + { + // If the runtime doesn't support adding new types then we expect every row number for any type that is + // emitted will be less than the number of rows in the original metadata. + var highestEmittedTypeDefRow = emitResult.ChangedTypes.Max(t => MetadataTokens.GetRowNumber(t)); + var highestExistingTypeDefRow = emitResult.Baseline.OriginalMetadata.GetMetadataReader().GetTableRowCount(TableIndex.TypeDef); + + if (highestEmittedTypeDefRow > highestExistingTypeDefRow) + { + var descriptor = EditAndContinueDiagnosticDescriptors.GetDescriptor(EditAndContinueErrorCode.ChangeResultsInSynthesizedType); + return Diagnostic.Create(descriptor, Location.None); + } + } + + return null; + } + /// /// Errors to be reported when a project is updated but the corresponding module does not support EnC. /// @@ -834,7 +868,12 @@ public async ValueTask EmitSolutionUpdateAsync(Solution solution cancellationToken); } - if (emitResult.Success) + var unsupportedChangesDiagnostic = await GetUnsupportedChangesDiagnosticAsync(emitResult, cancellationToken).ConfigureAwait(false); + if (unsupportedChangesDiagnostic is not null) + { + diagnostics.Add((newProject.Id, ImmutableArray.Create(unsupportedChangesDiagnostic))); + } + else if (emitResult.Success) { Contract.ThrowIfNull(emitResult.Baseline); diff --git a/src/Features/Core/Portable/FeaturesResources.resx b/src/Features/Core/Portable/FeaturesResources.resx index b253cce40f395..8e0bb77512efc 100644 --- a/src/Features/Core/Portable/FeaturesResources.resx +++ b/src/Features/Core/Portable/FeaturesResources.resx @@ -2920,4 +2920,7 @@ Zero-width positive lookbehind assertions are typically used at the beginning of Renaming {0} requires restarting the application because it is not supported by the runtime. + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + \ No newline at end of file diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf index 699f6b60396c0..ece65257486f7 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.cs.xlf @@ -320,6 +320,11 @@ Ujistěte se, že specifikátor tt použijete pro jazyky, pro které je nezbytn Změny provedené v projektu {0} se nepoužijí, dokud je aplikace spuštěná. + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf index f94713ddcdabc..6249849382ae9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.de.xlf @@ -320,6 +320,11 @@ Stellen Sie sicher, dass Sie den Bezeichner "tt" für Sprachen verwenden, für d Im Projekt "{0}" vorgenommene Änderungen werden nicht angewendet, während die Anwendung ausgeführt wird. + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf index 64072244f4365..6d0d52faf57f9 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.es.xlf @@ -320,6 +320,11 @@ Asegúrese de usar el especificador "tt" para los idiomas para los que es necesa Los cambios realizados en el proyecto "{0}" no se aplicarán mientras se esté ejecutando la aplicación + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf index 3ede175d556c1..7ada0aec37579 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.fr.xlf @@ -320,6 +320,11 @@ Veillez à utiliser le spécificateur "tt" pour les langues où il est nécessai Les changements apportés au projet '{0}' ne sont pas appliqués tant que l'application est en cours d'exécution + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf index db7dd9c84d133..7a5b79b1f745c 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.it.xlf @@ -320,6 +320,11 @@ Assicurarsi di usare l'identificatore "tt" per le lingue per le quali è necessa Le modifiche apportate al progetto '{0}' non verranno applicate mentre l'applicazione è in esecuzione + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf index 1bdcddbd8e376..f0665927bd2af 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ja.xlf @@ -320,6 +320,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma プロジェクト '{0}' で行った変更は、アプリケーションの実行中には適用されません + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf index 335f1fa9bd955..17a32d90a2ecf 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ko.xlf @@ -320,6 +320,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 애플리케이션이 실행되는 동안에는 '{0}' 프로젝트의 변경 내용이 적용되지 않습니다. + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf index 4af4add276369..4caaeb4f6c220 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pl.xlf @@ -320,6 +320,11 @@ Pamiętaj, aby nie używać specyfikatora „tt” dla wszystkich języków, w k Zmiany wprowadzone w projekcie „{0}” nie zostaną zastosowane, gdy aplikacja jest uruchomiona + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf index 78040ce1ddb12..5c7d67395f825 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.pt-BR.xlf @@ -320,6 +320,11 @@ Verifique se o especificador "tt" foi usado para idiomas para os quais é necess As alterações feitas no projeto '{0}' não serão aplicadas enquanto o aplicativo estiver em execução + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf index caeb007b2f396..5239562b40621 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.ru.xlf @@ -320,6 +320,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma Изменения, внесенные в проект "{0}", не будут применены во время выполнения приложения. + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf index b5a4e87981904..4398fd724ea19 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.tr.xlf @@ -320,6 +320,11 @@ AM ve PM arasındaki farkın korunmasının gerekli olduğu diller için "tt" be '{0}' projesinde yapılan değişiklikler, uygulama çalışırken uygulanmayacak + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf index 848c0ab7bd2d1..d44d45e4660e5 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hans.xlf @@ -320,6 +320,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 在应用程序运行时,将不应用在项目“{0}”中所作的更改 + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. diff --git a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf index 08cde3d941665..507396bc505b3 100644 --- a/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf +++ b/src/Features/Core/Portable/xlf/FeaturesResources.zh-Hant.xlf @@ -320,6 +320,11 @@ Make sure to use the "tt" specifier for languages for which it's necessary to ma 將不會在應用程式執行時套用在專案 '{0}' 中所做的變更 + + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + One or more changes result in a new type being created by the compiler, which requires restarting the application because it is not supported by the runtime + + Changing {0} from asynchronous to synchronous requires restarting the application. Changing {0} from asynchronous to synchronous requires restarting the application. From d39029ca93177b72d5d3433140faa7ea05f7ee74 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 25 Aug 2021 15:24:59 +1000 Subject: [PATCH 2/3] Update src/Features/Core/Portable/EditAndContinue/EditSession.cs Co-authored-by: Andrew Hall --- src/Features/Core/Portable/EditAndContinue/EditSession.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Features/Core/Portable/EditAndContinue/EditSession.cs b/src/Features/Core/Portable/EditAndContinue/EditSession.cs index 27bb90dc3c4ae..4340a3d113b0a 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditSession.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditSession.cs @@ -133,7 +133,7 @@ internal EditSession( if (!capabilities.HasFlag(EditAndContinueCapabilities.NewTypeDefinition)) { // If the runtime doesn't support adding new types then we expect every row number for any type that is - // emitted will be less than the number of rows in the original metadata. + // emitted will be less than or equal to the number of rows in the original metadata. var highestEmittedTypeDefRow = emitResult.ChangedTypes.Max(t => MetadataTokens.GetRowNumber(t)); var highestExistingTypeDefRow = emitResult.Baseline.OriginalMetadata.GetMetadataReader().GetTableRowCount(TableIndex.TypeDef); From 4c7aad9ec42365e7273ef7ce1aa57d91e7dffd83 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Thu, 26 Aug 2021 07:47:20 +1000 Subject: [PATCH 3/3] PR feedback --- .../EditAndContinueDiagnosticDescriptors.cs | 2 +- .../EditAndContinueErrorCode.cs | 2 +- .../Portable/EditAndContinue/EditSession.cs | 83 +++++++++---------- 3 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs index d0657ef43aeb5..38f028a9ceb5f 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueDiagnosticDescriptors.cs @@ -170,7 +170,7 @@ void AddGeneralDiagnostic(EditAndContinueErrorCode code, string resourceName, Di AddGeneralDiagnostic(EditAndContinueErrorCode.ChangesDisallowedWhileStoppedAtException, nameof(FeaturesResources.ChangesDisallowedWhileStoppedAtException)); AddGeneralDiagnostic(EditAndContinueErrorCode.DocumentIsOutOfSyncWithDebuggee, nameof(FeaturesResources.DocumentIsOutOfSyncWithDebuggee), DiagnosticSeverity.Warning); AddGeneralDiagnostic(EditAndContinueErrorCode.UnableToReadSourceFileOrPdb, nameof(FeaturesResources.UnableToReadSourceFileOrPdb), DiagnosticSeverity.Warning); - AddGeneralDiagnostic(EditAndContinueErrorCode.ChangeResultsInSynthesizedType, nameof(FeaturesResources.ChangesRequiredSynthesizedType)); + AddGeneralDiagnostic(EditAndContinueErrorCode.AddingTypeRuntimeCapabilityRequired, nameof(FeaturesResources.ChangesRequiredSynthesizedType)); s_descriptors = builder.ToImmutable(); } diff --git a/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs b/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs index 78a21fef941d8..2bf0279cb1ed6 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditAndContinueErrorCode.cs @@ -12,6 +12,6 @@ internal enum EditAndContinueErrorCode ChangesDisallowedWhileStoppedAtException = 4, DocumentIsOutOfSyncWithDebuggee = 5, UnableToReadSourceFileOrPdb = 6, - ChangeResultsInSynthesizedType = 7, + AddingTypeRuntimeCapabilityRequired = 7, } } diff --git a/src/Features/Core/Portable/EditAndContinue/EditSession.cs b/src/Features/Core/Portable/EditAndContinue/EditSession.cs index 4340a3d113b0a..0b95b74bcb335 100644 --- a/src/Features/Core/Portable/EditAndContinue/EditSession.cs +++ b/src/Features/Core/Portable/EditAndContinue/EditSession.cs @@ -119,15 +119,8 @@ internal EditSession( /// private async Task GetUnsupportedChangesDiagnosticAsync(EmitDifferenceResult emitResult, CancellationToken cancellationToken) { - if (!emitResult.Success) - { - return null; - } - - if (emitResult.Baseline is null) - { - return null; - } + Debug.Assert(emitResult.Success); + Debug.Assert(emitResult.Baseline is not null); var capabilities = await Capabilities.GetValueAsync(cancellationToken).ConfigureAwait(false); if (!capabilities.HasFlag(EditAndContinueCapabilities.NewTypeDefinition)) @@ -139,7 +132,7 @@ internal EditSession( if (highestEmittedTypeDefRow > highestExistingTypeDefRow) { - var descriptor = EditAndContinueDiagnosticDescriptors.GetDescriptor(EditAndContinueErrorCode.ChangeResultsInSynthesizedType); + var descriptor = EditAndContinueDiagnosticDescriptors.GetDescriptor(EditAndContinueErrorCode.AddingTypeRuntimeCapabilityRequired); return Diagnostic.Create(descriptor, Location.None); } } @@ -868,42 +861,46 @@ public async ValueTask EmitSolutionUpdateAsync(Solution solution cancellationToken); } - var unsupportedChangesDiagnostic = await GetUnsupportedChangesDiagnosticAsync(emitResult, cancellationToken).ConfigureAwait(false); - if (unsupportedChangesDiagnostic is not null) - { - diagnostics.Add((newProject.Id, ImmutableArray.Create(unsupportedChangesDiagnostic))); - } - else if (emitResult.Success) + if (emitResult.Success) { Contract.ThrowIfNull(emitResult.Baseline); - var updatedMethodTokens = emitResult.UpdatedMethods.SelectAsArray(h => MetadataTokens.GetToken(h)); - var changedTypeTokens = emitResult.ChangedTypes.SelectAsArray(h => MetadataTokens.GetToken(h)); - - // Determine all active statements whose span changed and exception region span deltas. - GetActiveStatementAndExceptionRegionSpans( - mvid, - oldActiveStatementsMap, - updatedMethodTokens, - NonRemappableRegions, - projectChanges.ActiveStatementChanges, - out var activeStatementsInUpdatedMethods, - out var moduleNonRemappableRegions, - out var exceptionRegionUpdates); - - deltas.Add(new ManagedModuleUpdate( - mvid, - ilStream.ToImmutableArray(), - metadataStream.ToImmutableArray(), - pdbStream.ToImmutableArray(), - projectChanges.LineChanges, - updatedMethodTokens, - changedTypeTokens, - activeStatementsInUpdatedMethods, - exceptionRegionUpdates)); - - nonRemappableRegions.Add((mvid, moduleNonRemappableRegions)); - emitBaselines.Add((newProject.Id, emitResult.Baseline)); + var unsupportedChangesDiagnostic = await GetUnsupportedChangesDiagnosticAsync(emitResult, cancellationToken).ConfigureAwait(false); + if (unsupportedChangesDiagnostic is not null) + { + diagnostics.Add((newProject.Id, ImmutableArray.Create(unsupportedChangesDiagnostic))); + isBlocked = true; + } + else + { + var updatedMethodTokens = emitResult.UpdatedMethods.SelectAsArray(h => MetadataTokens.GetToken(h)); + var changedTypeTokens = emitResult.ChangedTypes.SelectAsArray(h => MetadataTokens.GetToken(h)); + + // Determine all active statements whose span changed and exception region span deltas. + GetActiveStatementAndExceptionRegionSpans( + mvid, + oldActiveStatementsMap, + updatedMethodTokens, + NonRemappableRegions, + projectChanges.ActiveStatementChanges, + out var activeStatementsInUpdatedMethods, + out var moduleNonRemappableRegions, + out var exceptionRegionUpdates); + + deltas.Add(new ManagedModuleUpdate( + mvid, + ilStream.ToImmutableArray(), + metadataStream.ToImmutableArray(), + pdbStream.ToImmutableArray(), + projectChanges.LineChanges, + updatedMethodTokens, + changedTypeTokens, + activeStatementsInUpdatedMethods, + exceptionRegionUpdates)); + + nonRemappableRegions.Add((mvid, moduleNonRemappableRegions)); + emitBaselines.Add((newProject.Id, emitResult.Baseline)); + } } else {