提交 853ba76b 编写于 作者: H Heejae Chang

made more analyzer exception to include inner exceptions

上级 a382c8ba
......@@ -9,6 +9,7 @@
<Import_RootNamespace>AnalyzerDriver</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)AnalyzerExceptionDescriptionBuilder.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DeclarationComputer.cs" />
<Compile Include="$(MSBuildThisFileDirectory)DeclarationInfo.cs" />
</ItemGroup>
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Linq;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics
{
internal static class AnalyzerExceptionDescriptionBuilder
{
// Description separator
private static readonly string Separator = Environment.NewLine + "-----" + Environment.NewLine;
public static string CreateDiagnosticDescription(this Exception exception)
{
var aggregateException = exception as AggregateException;
if (aggregateException != null)
{
var flattened = aggregateException.Flatten();
return string.Join(Separator, flattened.InnerExceptions.Select(e => GetExceptionMessage(e)));
}
if (exception != null)
{
return string.Join(Separator, GetExceptionMessage(exception), CreateDiagnosticDescription(exception.InnerException));
}
return string.Empty;
}
private static string GetExceptionMessage(Exception exception)
{
var fileNotFoundException = exception as FileNotFoundException;
if (fileNotFoundException == null)
{
return exception.Message;
}
var fusionLog = DesktopShim.FileNotFoundException.TryGetFusionLog(fileNotFoundException);
if (fusionLog == null)
{
return exception.Message;
}
return string.Join(Separator, fileNotFoundException.Message, fusionLog);
}
}
}
......@@ -41,7 +41,7 @@
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
</PropertyGroup>
<ItemGroup>
<Content Include="$(NuGetPackageRoot)\Microsoft.DiaSymReader.Native\$(MicrosoftDiaSymReaderNativeVersion)\runtimes\win\native\Microsoft.DiaSymReader.Native.x86.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
......@@ -56,6 +56,9 @@
<Compile Include="..\..\Shared\CoreClrShim.cs">
<Link>CoreClrShim.cs</Link>
</Compile>
<Compile Include="..\..\Shared\DesktopShim.cs">
<Link>DesktopShim.cs</Link>
</Compile>
<Compile Include="AdditionalTextFile.cs" />
<Compile Include="AssemblyUtilities.cs" />
<Compile Include="Binding\AbstractLookupSymbolsInfo.cs" />
......@@ -761,4 +764,4 @@
<ImportGroup Label="Targets">
<Import Project="..\..\..\..\build\Targets\VSL.Imports.targets" />
</ImportGroup>
</Project>
</Project>
\ No newline at end of file
......@@ -16,6 +16,7 @@
using CodeBlockAnalyzerStateData = Microsoft.CodeAnalysis.Diagnostics.AnalysisState.CodeBlockAnalyzerStateData;
using DeclarationAnalyzerStateData = Microsoft.CodeAnalysis.Diagnostics.AnalysisState.DeclarationAnalyzerStateData;
namespace Microsoft.CodeAnalysis.Diagnostics
{
/// <summary>
......@@ -776,7 +777,7 @@ internal static Diagnostic CreateAnalyzerExceptionDiagnostic(DiagnosticAnalyzer
var title = CodeAnalysisResources.CompilerAnalyzerFailure;
var messageFormat = CodeAnalysisResources.CompilerAnalyzerThrows;
var messageArguments = new[] { analyzerName, e.GetType().ToString(), e.Message };
var description = string.Format(CodeAnalysisResources.CompilerAnalyzerThrowsDescription, analyzerName, e.ToString());
var description = string.Format(CodeAnalysisResources.CompilerAnalyzerThrowsDescription, analyzerName, e.CreateDiagnosticDescription());
var descriptor = GetAnalyzerExceptionDiagnosticDescriptor(AnalyzerExceptionDiagnosticId, title, description, messageFormat);
return Diagnostic.Create(descriptor, Location.None, messageArguments);
}
......@@ -786,7 +787,7 @@ internal static Diagnostic CreateDriverExceptionDiagnostic(Exception e)
var title = CodeAnalysisResources.AnalyzerDriverFailure;
var messageFormat = CodeAnalysisResources.AnalyzerDriverThrows;
var messageArguments = new[] { e.GetType().ToString(), e.Message };
var description = string.Format(CodeAnalysisResources.AnalyzerDriverThrowsDescription, e.ToString());
var description = string.Format(CodeAnalysisResources.AnalyzerDriverThrowsDescription, e.CreateDiagnosticDescription());
var descriptor = GetAnalyzerExceptionDiagnosticDescriptor(AnalyzerDriverExceptionDiagnosticId, title, description, messageFormat);
return Diagnostic.Create(descriptor, Location.None, messageArguments);
}
......
......@@ -13,13 +13,13 @@ namespace Roslyn.Utilities
/// </summary>
internal static class CoreClrShim
{
internal static class AssemblyLoadContext
{
internal static readonly Type Type = ReflectionUtilities.TryGetType(
"System.Runtime.Loader.AssemblyLoadContext, System.Runtime.Loader, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
}
internal static class CodePagesEncodingProvider
{
internal static readonly Type Type = ReflectionUtilities.TryGetType(
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Reflection;
using System.Runtime.ExceptionServices;
namespace Roslyn.Utilities
{
/// <summary>
/// This is a bridge for APIs that are only available on CoreCLR or .NET 4.6
/// and NOT on .NET 4.5. The compiler currently targets .NET 4.5 and CoreCLR
/// so this shim is necessary for switching on the dependent behavior.
/// </summary>
internal static class DesktopShim
{
internal static class FileNotFoundException
{
internal static readonly Type Type = ReflectionUtilities.TryGetType(
"System.IO.FileNotFoundException, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
private static PropertyInfo s_fusionLog = Type?.GetTypeInfo().GetDeclaredProperty("FusionLog");
internal static string TryGetFusionLog(object obj) => s_fusionLog.GetValue(obj) as string;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis.ErrorReporting;
using Roslyn.Utilities;
......@@ -35,9 +33,6 @@ internal static class AnalyzerHelper
private const string AnalyzerExceptionDiagnosticCategory = "Intellisense";
// Description separator
private static readonly string Separator = Environment.NewLine + "-----" + Environment.NewLine;
public static bool IsBuiltInAnalyzer(this DiagnosticAnalyzer analyzer)
{
return analyzer is IBuiltInAnalyzer || analyzer is DocumentDiagnosticAnalyzer || analyzer is ProjectDiagnosticAnalyzer || analyzer.IsCompilerAnalyzer();
......@@ -127,7 +122,7 @@ internal static Diagnostic CreateAnalyzerExceptionDiagnostic(DiagnosticAnalyzer
var descriptor = new DiagnosticDescriptor(AnalyzerExceptionDiagnosticId,
title: FeaturesResources.UserDiagnosticAnalyzerFailure,
messageFormat: FeaturesResources.UserDiagnosticAnalyzerThrows,
description: string.Format(FeaturesResources.UserDiagnosticAnalyzerThrowsDescription, analyzerName, e.ToString()),
description: string.Format(FeaturesResources.UserDiagnosticAnalyzerThrowsDescription, analyzerName, e.CreateDiagnosticDescription()),
category: AnalyzerExceptionDiagnosticCategory,
defaultSeverity: DiagnosticSeverity.Warning,
isEnabledByDefault: true,
......@@ -183,19 +178,19 @@ public static DiagnosticData CreateAnalyzerLoadFailureDiagnostic(string fullPath
id = Choose(language, WRN_UnableToLoadAnalyzerId, WRN_UnableToLoadAnalyzerIdCS, WRN_UnableToLoadAnalyzerIdVB);
messageFormat = FeaturesResources.WRN_UnableToLoadAnalyzer;
message = string.Format(FeaturesResources.WRN_UnableToLoadAnalyzer, fullPath, e.Message);
description = CreateDescription(e.Exception);
description = e.Exception.CreateDiagnosticDescription();
break;
case AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToCreateAnalyzer:
id = Choose(language, WRN_AnalyzerCannotBeCreatedId, WRN_AnalyzerCannotBeCreatedIdCS, WRN_AnalyzerCannotBeCreatedIdVB);
messageFormat = FeaturesResources.WRN_AnalyzerCannotBeCreated;
message = string.Format(FeaturesResources.WRN_AnalyzerCannotBeCreated, e.TypeName, fullPath, e.Message);
description = CreateDescription(e.Exception);
description = e.Exception.CreateDiagnosticDescription();
break;
case AnalyzerLoadFailureEventArgs.FailureErrorCode.NoAnalyzers:
id = Choose(language, WRN_NoAnalyzerInAssemblyId, WRN_NoAnalyzerInAssemblyIdCS, WRN_NoAnalyzerInAssemblyIdVB);
messageFormat = FeaturesResources.WRN_NoAnalyzerInAssembly;
message = string.Format(FeaturesResources.WRN_NoAnalyzerInAssembly, fullPath);
description = CreateDescription(e.Exception);
description = e.Exception.CreateDiagnosticDescription();
break;
case AnalyzerLoadFailureEventArgs.FailureErrorCode.None:
default:
......@@ -209,57 +204,6 @@ public static DiagnosticData CreateAnalyzerLoadFailureDiagnostic(string fullPath
return true;
}
private static string CreateDescription(Exception exception)
{
var aggregateException = exception as AggregateException;
if (aggregateException != null)
{
var flattened = aggregateException.Flatten();
return string.Join(Separator, flattened.InnerExceptions.Select(e => GetExceptionMessage(e)));
}
if (exception != null)
{
return string.Join(Separator, GetExceptionMessage(exception), CreateDescription(exception.InnerException));
}
return string.Empty;
}
private static string GetExceptionMessage(Exception exception)
{
var fileNotFoundException = exception as FileNotFoundException;
if (fileNotFoundException == null)
{
return exception.Message;
}
var fusionLog = GetFusionLogIfPossible(fileNotFoundException);
if (fusionLog == null)
{
return exception.Message;
}
return string.Join(Separator, fileNotFoundException.Message, fusionLog);
}
private static string GetFusionLogIfPossible(FileNotFoundException exception)
{
try
{
// since Feature is in portable layer, I am using reflection here. so that we can get
// most detail info on desktop when analyzer is failed to load. otherwise, we either
// don't put this information or need to do quite complex plumbing for quite simple thing
// that is not in hot path.
var info = exception.GetType().GetRuntimeProperty("FusionLog");
return info.GetValue(exception) as string;
}
catch
{
return null;
}
}
private static string Choose(string language, string noLanguageMessage, string csharpMessage, string vbMessage)
{
if (language == null)
......
......@@ -71,6 +71,9 @@
<InternalsVisibleToMoq Include="DynamicProxyGenAssembly2" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\..\Compilers\Shared\DesktopShim.cs">
<Link>Shared\Utilities\DesktopShim.cs</Link>
</Compile>
<Compile Include="AddMissingReference\AbstractAddMissingReferenceCodeFixProvider.cs" />
<Compile Include="AddMissingReference\CodeAction.cs" />
<Compile Include="ChangeSignature\AbstractChangeSignatureCodeRefactoringProvider.cs" />
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册