Skip to content

Commit bf00990

Browse files
Stop roslyn library crashing Visual Studio during conversion
1 parent 0301eb0 commit bf00990

1 file changed

Lines changed: 36 additions & 3 deletions

File tree

ICSharpCode.CodeConverter/Shared/ProjectConversion.cs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,42 @@ private static async Task<IEnumerable<ConversionResult>> ConvertProjectContents(
156156
private async Task<(string Path, SyntaxNode Node, string[] Errors)[]> Convert(
157157
IProgress<ConversionProgress> progress)
158158
{
159-
var firstPassResults = await ExecutePhase(_documentsToConvert, FirstPass, progress, "Phase 1 of 2:");
160-
var (proj1, docs1) = await _projectContentsConverter.GetConvertedProject(firstPassResults);
161-
return await ExecutePhase(proj1.GetDocuments(docs1), SecondPass, progress, "Phase 2 of 2:");
159+
var originalErrorHandler = ExchangeFatalErrorHandler(e =>
160+
progress.Report(new ConversionProgress($"https://github.com/dotnet/roslyn threw an exception: {e}"))
161+
);
162+
try {
163+
var firstPassResults = await ExecutePhase(_documentsToConvert, FirstPass, progress, "Phase 1 of 2:");
164+
var (proj1, docs1) = await _projectContentsConverter.GetConvertedProject(firstPassResults);
165+
return await ExecutePhase(proj1.GetDocuments(docs1), SecondPass, progress, "Phase 2 of 2:");
166+
} finally {
167+
ExchangeFatalErrorHandler(originalErrorHandler);
168+
}
169+
}
170+
171+
/// <summary>
172+
/// Use this to stop the library exiting the process without telling us.
173+
/// </summary>
174+
/// <remarks>
175+
/// The simplification code in particular is quite buggy, scattered with "throw ExceptionUtilities.Unreachable" with no particular reasoning for why the code wouldn't be reachable.
176+
/// It then uses FatalError.ReportUnlessCanceled rather than FatalError.ReportWithoutCrashUnlessCanceled causing fatal crashes with Environment.FailFast
177+
/// While this presumably allows them to get good low-level debugging info from the windows error reports caused, it just means that people come to this project complaining about VS crashes.
178+
/// See https://github.com/icsharpcode/CodeConverter/issues/521 and https://github.com/icsharpcode/CodeConverter/issues/484
179+
/// There are other ways to find these bugs - just run the expander/reducer on a couple of whole open source projects and the bugs will pile up.
180+
/// </remarks>
181+
private static Action<Exception> ExchangeFatalErrorHandler(Action<Exception> errorHandler)
182+
{
183+
if (errorHandler == null) return null;
184+
try {
185+
var fataErrorType = Type.GetType("Microsoft.CodeAnalysis.FatalError, Microsoft.CodeAnalysis");
186+
var fatalHandlerField = fataErrorType.GetField("s_fatalHandler");
187+
var originalHandler = (Action<Exception>)fatalHandlerField.GetValue(null);
188+
if (originalHandler != null) {
189+
fatalHandlerField.SetValue(null, errorHandler);
190+
}
191+
return originalHandler;
192+
} catch (Exception) {
193+
return null;
194+
}
162195
}
163196

164197
private async Task<(string Path, SyntaxNode Node, string[] Errors)[]> ExecutePhase<T>(IEnumerable<T> parameters, Func<T, Progress<string>, Task<(string treeFilePath, SyntaxNode convertedDoc,

0 commit comments

Comments
 (0)