提交 e4983731 编写于 作者: T Tom Meschter

Merge pull request #2430 from tmeschter/RefactorAnalyzerReference

Clean up `AnalyzerReference` and derived types.

I'm doing a lot of other work that uses the `AnalyzerReference` type and its derived types, and the API could stand some clean up and simplification. This includes the following changes/refactorings:

1. Remove `AnalyzerReference.IsUnresolved`.
2. Push `AnalyzerFileReference` down into the CodeAnalysis (Portable) project.
3. Add an `AnalyzerReference.Id` property.
4. Update `AnalyzerFileReference` to take an `IAnalyzerAssemblyLoader` rather than a `Func<string, Assembly>`.

Please see the individual commits for more information.
......@@ -20,7 +20,7 @@ public class AnalyzerFileReferenceTests : TestBase
public static AnalyzerFileReference CreateAnalyzerFileReference(string fullPath)
{
return new AnalyzerFileReference(fullPath, _analyzerLoader.LoadFromPath);
return new AnalyzerFileReference(fullPath, _analyzerLoader);
}
[Fact]
......
......@@ -50,7 +50,6 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="AdditionalTextFile.cs" />
<Compile Include="AnalyzerLoadFailureEventArgs.cs" />
<Compile Include="AssemblyReferenceResolver.cs" />
<Compile Include="CodeAnalysisDesktopResources.Designer.cs">
<AutoGen>True</AutoGen>
......@@ -90,7 +89,6 @@
<Compile Include="Interop\IClrStrongName.cs" />
<Compile Include="Interop\SuppressUnmanagedCodeSecurityAttribute.cs" />
<Compile Include="IVsSQM.cs" />
<Compile Include="AnalyzerFileReference.cs" />
<Compile Include="MetadataFileReferenceResolver.cs" />
<Compile Include="PathKind.cs" />
<Compile Include="PathUtilities.cs" />
......
......@@ -398,7 +398,7 @@ private AnalyzerFileReference ResolveAnalyzerReference(CommandLineAnalyzerRefere
if (resolvedPath != null)
{
return new AnalyzerFileReference(resolvedPath, analyzerLoader.LoadFromPath);
return new AnalyzerFileReference(resolvedPath, analyzerLoader);
}
return null;
......
......@@ -50,18 +50,6 @@ Microsoft.CodeAnalysis.CommandLineSourceFile.IsScript.get -> bool
Microsoft.CodeAnalysis.CommandLineSourceFile.Path.get -> string
Microsoft.CodeAnalysis.DesktopStrongNameProvider
Microsoft.CodeAnalysis.DesktopStrongNameProvider.DesktopStrongNameProvider(System.Collections.Immutable.ImmutableArray<string> keyFileSearchPaths = default(System.Collections.Immutable.ImmutableArray<string>)) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.AnalyzerFileReference(string fullPath, System.Func<string, System.Reflection.Assembly> getAssembly) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.AnalyzerLoadFailed -> System.EventHandler<Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs>
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Equals(Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference other) -> bool
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetAssembly() -> System.Reflection.Assembly
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.AnalyzerLoadFailureEventArgs(Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode errorCode, System.Exception ex, string typeName) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.NoAnalyzers = 3 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.None = 0 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToCreateAnalyzer = 2 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToLoadAnalyzer = 1 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.FileSystemExtensions
Microsoft.CodeAnalysis.RuleSet
Microsoft.CodeAnalysis.RuleSet.FilePath.get -> string
......@@ -93,12 +81,6 @@ override Microsoft.CodeAnalysis.CommandLineReference.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.CommandLineReference.GetHashCode() -> int
override Microsoft.CodeAnalysis.DesktopStrongNameProvider.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.DesktopStrongNameProvider.GetHashCode() -> int
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Display.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.FullPath.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetAnalyzers(string language) -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetAnalyzersForAllLanguages() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetHashCode() -> int
override Microsoft.CodeAnalysis.SourceFileResolver.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.SourceFileResolver.GetHashCode() -> int
override Microsoft.CodeAnalysis.SourceFileResolver.NormalizePath(string path, string baseFilePath) -> string
......@@ -108,9 +90,6 @@ override Microsoft.CodeAnalysis.XmlFileResolver.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.XmlFileResolver.GetHashCode() -> int
override Microsoft.CodeAnalysis.XmlFileResolver.OpenRead(string resolvedPath) -> System.IO.Stream
override Microsoft.CodeAnalysis.XmlFileResolver.ResolveReference(string path, string baseFilePath) -> string
readonly Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.ErrorCode -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
readonly Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.Exception -> System.Exception
readonly Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.TypeName -> string
static Microsoft.CodeAnalysis.CommandLineParser.SplitCommandLineIntoArguments(string commandLine, bool removeHashComments) -> System.Collections.Generic.IEnumerable<string>
static Microsoft.CodeAnalysis.FileSystemExtensions.Emit(this Microsoft.CodeAnalysis.Compilation compilation, string outputPath, string pdbPath = null, string xmlDocPath = null, string win32ResourcesPath = null, System.Collections.Generic.IEnumerable<Microsoft.CodeAnalysis.ResourceDescription> manifestResources = null, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.Emit.EmitResult
static Microsoft.CodeAnalysis.RuleSet.GetDiagnosticOptionsFromRulesetFile(string rulesetFileFullPath, out System.Collections.Generic.Dictionary<string, Microsoft.CodeAnalysis.ReportDiagnostic> specificDiagnosticOptions) -> Microsoft.CodeAnalysis.ReportDiagnostic
......
......@@ -116,6 +116,8 @@
<Compile Include="Desktop\AssemblyVersion.cs" />
<Compile Include="Desktop\DesktopAssemblyIdentityComparer.cs" />
<Compile Include="Desktop\DesktopAssemblyIdentityComparer.Fx.cs" />
<Compile Include="DiagnosticAnalyzer\AnalyzerFileReference.cs" />
<Compile Include="DiagnosticAnalyzer\AnalyzerLoadFailureEventArgs.cs" />
<Compile Include="DiagnosticAnalyzer\CompilerDiagnosticAnalyzer.CompilationAnalyzer.cs" />
<Compile Include="DiagnosticAnalyzer\CompilerDiagnosticAnalyzer.cs" />
<Compile Include="DiagnosticAnalyzer\IAnalyzerAssemblyLoader.cs" />
......
......@@ -27,9 +27,10 @@ namespace Microsoft.CodeAnalysis.Diagnostics
public sealed partial class AnalyzerFileReference : AnalyzerReference, IEquatable<AnalyzerReference>
{
private readonly string _fullPath;
private readonly Func<string, Assembly> _getAssembly;
private readonly IAnalyzerAssemblyLoader _assemblyLoader;
private string _lazyDisplayName;
private string _lazyId;
private ImmutableArray<DiagnosticAnalyzer> _lazyAllAnalyzers;
private ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> _lazyAnalyzersPerLanguage;
private Assembly _lazyAssembly;
......@@ -39,32 +40,26 @@ public sealed partial class AnalyzerFileReference : AnalyzerReference, IEquatabl
public event EventHandler<AnalyzerLoadFailureEventArgs> AnalyzerLoadFailed;
/// <summary>
/// Creates an AnalyzerFileReference with the given <paramref name="fullPath"/>.
/// Creates an AnalyzerFileReference with the given <paramref name="fullPath"/> and <paramref name="assemblyLoader"/>.
/// </summary>
/// <param name="fullPath">Full path of the analyzer assembly.</param>
/// <param name="getAssembly">Function for loading the analyzer assembly</param>
public AnalyzerFileReference(string fullPath, Func<string, Assembly> getAssembly)
/// <param name="assemblyLoader">Loader for obtaining the <see cref="Assembly"/> from the <paramref name="fullPath"/></param>
public AnalyzerFileReference(string fullPath, IAnalyzerAssemblyLoader assemblyLoader)
{
if (fullPath == null)
{
throw new ArgumentNullException(nameof(fullPath));
}
// TODO: remove full path normalization
CompilerPathUtilities.RequireAbsolutePath(fullPath, nameof(fullPath));
try
{
_fullPath = Path.GetFullPath(fullPath);
}
catch (Exception e)
if (assemblyLoader == null)
{
throw new ArgumentException(e.Message, "fullPath");
throw new ArgumentNullException(nameof(assemblyLoader));
}
_fullPath = fullPath;
_lazyAllAnalyzers = default(ImmutableArray<DiagnosticAnalyzer>);
_lazyAnalyzersPerLanguage = ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>>.Empty;
_getAssembly = getAssembly;
_assemblyLoader = assemblyLoader;
}
public override ImmutableArray<DiagnosticAnalyzer> GetAnalyzersForAllLanguages()
......@@ -118,35 +113,29 @@ public override string FullPath
}
}
private static string GetAssemblyNameFromPath(string path)
public override string Display
{
// AssemblyName.GetAssemblyName(path) is not available on CoreCLR.
// Use our metadata reader to do the equivalent thing.
using (var reader = new PEReader(FileUtilities.OpenRead(path)))
get
{
var metadataReader = reader.GetMetadataReader();
var assemblyDefinition = metadataReader.GetAssemblyDefinition();
return metadataReader.GetString(assemblyDefinition.Name);
if (_lazyDisplayName == null)
{
_lazyDisplayName = Path.GetFileName(this.FullPath);
}
return _lazyDisplayName;
}
}
public override string Display
public override string Id
{
get
{
if (_lazyDisplayName == null)
if (_lazyId == null)
{
try
{
_lazyDisplayName = GetAssemblyNameFromPath(_fullPath);
}
catch (Exception)
{ }
_lazyDisplayName = _lazyDisplayName ?? Path.GetFileName(this.FullPath);
_lazyId = Path.GetFileName(this.FullPath).ToLower();
}
return _lazyDisplayName;
return _lazyId;
}
}
......@@ -266,14 +255,13 @@ private IEnumerable<DiagnosticAnalyzer> GetAnalyzersForTypeNames(Assembly analyz
DiagnosticAnalyzer analyzer = null;
try
{
var type = analyzerAssembly.GetType(typeName, throwOnError: true, ignoreCase: false);
var type = analyzerAssembly.GetType(typeName);
if (DerivesFromDiagnosticAnalyzer(type))
{
analyzer = (DiagnosticAnalyzer)Activator.CreateInstance(type);
}
}
catch (Exception e) when (e is TypeLoadException || e is BadImageFormatException || e is FileNotFoundException || e is FileLoadException ||
e is ArgumentException || e is NotSupportedException || e is TargetInvocationException || e is MemberAccessException)
catch (Exception e)
{
this.AnalyzerLoadFailed?.Invoke(this, new AnalyzerLoadFailureEventArgs(AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToCreateAnalyzer, e, typeName));
analyzer = null;
......@@ -408,8 +396,7 @@ public bool Equals(AnalyzerReference other)
if (other != null)
{
return other.Display == this.Display &&
other.FullPath == this.FullPath &&
other.IsUnresolved == this.IsUnresolved;
other.FullPath == this.FullPath;
}
return base.Equals(other);
......@@ -417,16 +404,14 @@ public bool Equals(AnalyzerReference other)
public override int GetHashCode()
{
return Hash.Combine(this.Display,
Hash.Combine(this.FullPath, this.IsUnresolved.GetHashCode()));
return Hash.Combine(this.Display, this.FullPath.GetHashCode());
}
public Assembly GetAssembly()
{
if (_lazyAssembly == null)
{
var assembly = _getAssembly(_fullPath);
Interlocked.CompareExchange(ref _lazyAssembly, assembly, null);
_lazyAssembly = _assemblyLoader.LoadFromPath(_fullPath);
}
return _lazyAssembly;
......
......@@ -17,6 +17,7 @@ public sealed class AnalyzerImageReference : AnalyzerReference
private readonly ImmutableArray<DiagnosticAnalyzer> _analyzers;
private readonly string _fullPath;
private readonly string _display;
private readonly string _id;
public AnalyzerImageReference(ImmutableArray<DiagnosticAnalyzer> analyzers, string fullPath = null, string display = null)
{
......@@ -28,6 +29,7 @@ public AnalyzerImageReference(ImmutableArray<DiagnosticAnalyzer> analyzers, stri
_analyzers = analyzers;
_fullPath = fullPath;
_display = display;
_id = Guid.NewGuid().ToString();
}
public override ImmutableArray<DiagnosticAnalyzer> GetAnalyzersForAllLanguages()
......@@ -56,6 +58,14 @@ public override string Display
}
}
public override string Id
{
get
{
return _id;
}
}
private string GetDebuggerDisplay()
{
var sb = new StringBuilder();
......
......@@ -25,18 +25,24 @@ protected AnalyzerReference()
/// <summary>
/// Path or name used in error messages to identity the reference.
/// </summary>
/// <remarks>
/// Should not be null.
/// </remarks>
public virtual string Display
{
get { return null; }
}
/// <summary>
/// Returns true if this reference is an unresolved reference.
/// A unique identifier for this analyzer reference.
/// </summary>
public virtual bool IsUnresolved
{
get { return false; }
}
/// <remarks>
/// Should not be null.
/// Note that this and <see cref="FullPath"/> serve different purposes. An analyzer reference may not
/// have a path, but it always has an ID. Further, two analyzer references with different paths may
/// represent two copies of the same analyzer, in which case the IDs should also be the same.
/// </remarks>
public abstract string Id { get; }
/// <summary>
/// Gets all the diagnostic analyzers defined in this assembly reference, irrespective of the language supported by the analyzer.
......
......@@ -17,6 +17,11 @@ public sealed class UnresolvedAnalyzerReference : AnalyzerReference
public UnresolvedAnalyzerReference(string unresolvedPath)
{
if (unresolvedPath == null)
{
throw new ArgumentNullException(nameof(unresolvedPath));
}
_unresolvedPath = unresolvedPath;
}
......@@ -36,9 +41,12 @@ public override string FullPath
}
}
public override bool IsUnresolved
public override string Id
{
get { return true; }
get
{
return _unresolvedPath;
}
}
public override ImmutableArray<DiagnosticAnalyzer> GetAnalyzersForAllLanguages()
......
......@@ -233,8 +233,20 @@ Microsoft.CodeAnalysis.DiagnosticSeverity.Warning = 2 -> Microsoft.CodeAnalysis.
Microsoft.CodeAnalysis.Diagnostics.AnalysisContext
Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.RegisterSymbolAction(System.Action<Microsoft.CodeAnalysis.Diagnostics.SymbolAnalysisContext> action, params Microsoft.CodeAnalysis.SymbolKind[] symbolKinds) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.RegisterSyntaxNodeAction<TLanguageKindEnum>(System.Action<Microsoft.CodeAnalysis.Diagnostics.SyntaxNodeAnalysisContext> action, params TLanguageKindEnum[] syntaxKinds) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.AnalyzerFileReference(string fullPath, Microsoft.CodeAnalysis.IAnalyzerAssemblyLoader assemblyLoader) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.AnalyzerLoadFailed -> System.EventHandler<Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs>
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Equals(Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference other) -> bool
Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetAssembly() -> System.Reflection.Assembly
Microsoft.CodeAnalysis.Diagnostics.AnalyzerImageReference
Microsoft.CodeAnalysis.Diagnostics.AnalyzerImageReference.AnalyzerImageReference(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer> analyzers, string fullPath = null, string display = null) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.AnalyzerLoadFailureEventArgs(Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode errorCode, System.Exception ex, string typeName) -> void
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.NoAnalyzers = 3 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.None = 0 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToCreateAnalyzer = 2 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode.UnableToLoadAnalyzer = 1 -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions
Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions.AdditionalFiles.get -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AdditionalText>
Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions.AnalyzerOptions(System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.AdditionalText> additionalFiles) -> void
......@@ -1535,6 +1547,7 @@ abstract Microsoft.CodeAnalysis.Diagnostics.AnalysisContext.RegisterSyntaxTreeAc
abstract Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference.FullPath.get -> string
abstract Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference.GetAnalyzers(string language) -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
abstract Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference.GetAnalyzersForAllLanguages() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
abstract Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference.Id.get -> string
abstract Microsoft.CodeAnalysis.Diagnostics.CodeBlockStartAnalysisContext<TLanguageKindEnum>.RegisterCodeBlockEndAction(System.Action<Microsoft.CodeAnalysis.Diagnostics.CodeBlockAnalysisContext> action) -> void
abstract Microsoft.CodeAnalysis.Diagnostics.CodeBlockStartAnalysisContext<TLanguageKindEnum>.RegisterSyntaxNodeAction(System.Action<Microsoft.CodeAnalysis.Diagnostics.SyntaxNodeAnalysisContext> action, System.Collections.Immutable.ImmutableArray<TLanguageKindEnum> syntaxKinds) -> void
abstract Microsoft.CodeAnalysis.Diagnostics.CompilationStartAnalysisContext.RegisterCodeBlockAction(System.Action<Microsoft.CodeAnalysis.Diagnostics.CodeBlockAnalysisContext> action) -> void
......@@ -1739,17 +1752,25 @@ override Microsoft.CodeAnalysis.CompilationReference.Display.get -> string
override Microsoft.CodeAnalysis.Diagnostic.ToString() -> string
override Microsoft.CodeAnalysis.DiagnosticDescriptor.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.DiagnosticDescriptor.GetHashCode() -> int
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Display.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.FullPath.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetAnalyzers(string language) -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetAnalyzersForAllLanguages() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.GetHashCode() -> int
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerFileReference.Id.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerImageReference.Display.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerImageReference.FullPath.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerImageReference.GetAnalyzers(string language) -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerImageReference.GetAnalyzersForAllLanguages() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerImageReference.Id.get -> string
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.Diagnostics.AnalyzerOptions.GetHashCode() -> int
override Microsoft.CodeAnalysis.Diagnostics.UnresolvedAnalyzerReference.Display.get -> string
override Microsoft.CodeAnalysis.Diagnostics.UnresolvedAnalyzerReference.FullPath.get -> string
override Microsoft.CodeAnalysis.Diagnostics.UnresolvedAnalyzerReference.GetAnalyzers(string language) -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.UnresolvedAnalyzerReference.GetAnalyzersForAllLanguages() -> System.Collections.Immutable.ImmutableArray<Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer>
override Microsoft.CodeAnalysis.Diagnostics.UnresolvedAnalyzerReference.IsUnresolved.get -> bool
override Microsoft.CodeAnalysis.Diagnostics.UnresolvedAnalyzerReference.Id.get -> string
override Microsoft.CodeAnalysis.Emit.EmitOptions.Equals(object obj) -> bool
override Microsoft.CodeAnalysis.Emit.EmitOptions.GetHashCode() -> int
override Microsoft.CodeAnalysis.Emit.SemanticEdit.Equals(object obj) -> bool
......@@ -1865,6 +1886,9 @@ override sealed Microsoft.CodeAnalysis.Diagnostics.DiagnosticAnalyzer.ToString()
override sealed Microsoft.CodeAnalysis.LocalizableString.Equals(object other) -> bool
override sealed Microsoft.CodeAnalysis.LocalizableString.GetHashCode() -> int
override sealed Microsoft.CodeAnalysis.LocalizableString.ToString() -> string
readonly Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.ErrorCode -> Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.FailureErrorCode
readonly Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.Exception -> System.Exception
readonly Microsoft.CodeAnalysis.Diagnostics.AnalyzerLoadFailureEventArgs.TypeName -> string
readonly Microsoft.CodeAnalysis.Emit.EmitBaseline.OriginalMetadata -> Microsoft.CodeAnalysis.ModuleMetadata
readonly Microsoft.CodeAnalysis.Emit.SemanticEdit.Kind -> Microsoft.CodeAnalysis.Emit.SemanticEditKind
readonly Microsoft.CodeAnalysis.Emit.SemanticEdit.NewSymbol -> Microsoft.CodeAnalysis.ISymbol
......@@ -2078,7 +2102,6 @@ virtual Microsoft.CodeAnalysis.Diagnostic.DefaultSeverity.get -> Microsoft.CodeA
virtual Microsoft.CodeAnalysis.Diagnostic.Properties.get -> System.Collections.Immutable.ImmutableDictionary<string, string>
virtual Microsoft.CodeAnalysis.DiagnosticFormatter.Format(Microsoft.CodeAnalysis.Diagnostic diagnostic, System.IFormatProvider formatter = null) -> string
virtual Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference.Display.get -> string
virtual Microsoft.CodeAnalysis.Diagnostics.AnalyzerReference.IsUnresolved.get -> bool
virtual Microsoft.CodeAnalysis.Emit.EmitResult.GetDebuggerDisplay() -> string
virtual Microsoft.CodeAnalysis.Location.GetDebuggerDisplay() -> string
virtual Microsoft.CodeAnalysis.Location.GetLineSpan() -> Microsoft.CodeAnalysis.FileLinePositionSpan
......
......@@ -221,6 +221,14 @@ public override string FullPath
}
}
public override string Id
{
get
{
return "MockAnalyzerReference";
}
}
public override ImmutableArray<DiagnosticAnalyzer> GetAnalyzers(string language)
{
return ImmutableArray.Create<DiagnosticAnalyzer>(Analyzer);
......
......@@ -68,6 +68,14 @@ public override string FullPath
}
}
public override string Id
{
get
{
return nameof(TestAnalyzerReferenceByLanguage);
}
}
public override ImmutableArray<DiagnosticAnalyzer> GetAnalyzersForAllLanguages()
{
return _analyzersMap.SelectMany(kvp => kvp.Value).ToImmutableArray();
......
......@@ -10,6 +10,7 @@ Imports Microsoft.CodeAnalysis.CodeActions
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeFixes.Suppression
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.ErrorLogger
Imports Microsoft.CodeAnalysis.Host
......@@ -19,13 +20,10 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.CodeFixes.UnitTests
Public Class CodeFixServiceTests
Dim _assemblyLoader As IAnalyzerAssemblyLoader = New InMemoryAssemblyLoader()
Public Function CreateAnalyzerFileReference(ByVal fullPath As String) As AnalyzerFileReference
Return New AnalyzerFileReference(
fullPath,
Function(p)
Dim bytes = File.ReadAllBytes(p)
Return Assembly.Load(bytes)
End Function)
Return New AnalyzerFileReference(fullPath, _assemblyLoader)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)>
......
......@@ -21,13 +21,10 @@ Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Public Class DiagnosticServiceTests
Dim _assemblyLoader As IAnalyzerAssemblyLoader = New InMemoryAssemblyLoader()
Public Function CreateAnalyzerFileReference(ByVal fullPath As String) As AnalyzerFileReference
Return New AnalyzerFileReference(
fullPath,
Function(p)
Dim bytes = File.ReadAllBytes(p)
Return Assembly.Load(bytes)
End Function)
Return New AnalyzerFileReference(fullPath, _assemblyLoader)
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Diagnostics)>
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.IO
Imports System.Reflection
Namespace Microsoft.CodeAnalysis.Editor.Implementation.Diagnostics.UnitTests
Public Class InMemoryAssemblyLoader
Implements IAnalyzerAssemblyLoader
Public Sub AddDependencyLocation(fullPath As String) Implements IAnalyzerAssemblyLoader.AddDependencyLocation
End Sub
Public Function LoadFromPath(fullPath As String) As Assembly Implements IAnalyzerAssemblyLoader.LoadFromPath
Dim bytes = File.ReadAllBytes(fullPath)
Return Assembly.Load(bytes)
End Function
End Class
End Namespace
......@@ -191,6 +191,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CallHierarchy\CallHierarchyTests.vb" />
<Compile Include="Diagnostics\InMemoryAssemblyLoader.vb" />
<Compile Include="Utilities\MockDocumentNavigationServiceProvider.vb" />
<Compile Include="Utilities\MockSymbolNavigationServiceProvider.vb" />
<Compile Include="CodeFixes\CodeFixServiceTests.vb" />
......
......@@ -71,6 +71,11 @@ internal sealed partial class HostAnalyzerManager
/// </summary>
private ImmutableDictionary<DiagnosticAnalyzer, HashSet<string>> _compilerDiagnosticAnalyzerDescriptorMap;
/// <summary>
/// Loader for VSIX-based analyzers.
/// </summary>
private static readonly IAnalyzerAssemblyLoader s_assemblyLoader = new LoadContextAssemblyLoader();
public HostAnalyzerManager(IEnumerable<HostDiagnosticAnalyzerPackage> hostAnalyzerPackages, AbstractHostDiagnosticUpdateSource hostDiagnosticUpdateSource) :
this(CreateAnalyzerReferencesFromPackages(hostAnalyzerPackages), hostAnalyzerPackages.ToImmutableArrayOrEmpty(), hostDiagnosticUpdateSource)
{
......@@ -103,7 +108,7 @@ internal sealed partial class HostAnalyzerManager
/// </summary>
public string GetAnalyzerReferenceIdentity(AnalyzerReference reference)
{
return GetAnalyzerReferenceId(reference);
return reference.Id;
}
/// <summary>
......@@ -346,11 +351,6 @@ private void UpdateCompilerAnalyzerMapIfNeeded(string language, ImmutableArray<D
}
}
private static string GetAnalyzerReferenceId(AnalyzerReference reference)
{
return reference.Display ?? FeaturesResources.Unknown;
}
private bool CheckAnalyzerReferenceIdentity(AnalyzerReference reference)
{
if (reference == null)
......@@ -358,7 +358,7 @@ private bool CheckAnalyzerReferenceIdentity(AnalyzerReference reference)
return false;
}
return !_hostAnalyzerReferencesMap.ContainsKey(GetAnalyzerReferenceId(reference));
return !_hostAnalyzerReferencesMap.ContainsKey(reference.Id);
}
private static ImmutableDictionary<string, ImmutableArray<DiagnosticAnalyzer>> CreateDiagnosticAnalyzersPerReferenceMap(
......@@ -386,7 +386,7 @@ private bool CheckAnalyzerReferenceIdentity(AnalyzerReference reference)
var builder = ImmutableDictionary.CreateBuilder<string, AnalyzerReference>();
foreach (var reference in analyzerReferences)
{
var key = GetAnalyzerReferenceId(reference);
var key = reference.Id;
// filter out duplicated analyzer reference
if (builder.ContainsKey(key))
......@@ -409,14 +409,10 @@ private static ImmutableArray<AnalyzerReference> CreateAnalyzerReferencesFromPac
var analyzerAssemblies = analyzerPackages.SelectMany(p => p.Assemblies);
// We want to load the analyzer assembly assets in default context.
// Use Assembly.Load instead of Assembly.LoadFrom to ensure that if the assembly is ngen'ed, then the native image gets loaded.
Func<string, Assembly> getAssembly = (fullPath) => Assembly.Load(AssemblyName.GetAssemblyName(fullPath));
var builder = ImmutableArray.CreateBuilder<AnalyzerReference>();
foreach (var analyzerAssembly in analyzerAssemblies.Distinct(StringComparer.OrdinalIgnoreCase))
{
builder.Add(new AnalyzerFileReference(analyzerAssembly, getAssembly));
builder.Add(new AnalyzerFileReference(analyzerAssembly, s_assemblyLoader));
}
return builder.ToImmutable();
......@@ -443,5 +439,19 @@ private static ImmutableArray<AnalyzerReference> CreateAnalyzerReferencesFromPac
return current;
}
private class LoadContextAssemblyLoader : IAnalyzerAssemblyLoader
{
public void AddDependencyLocation(string fullPath)
{
}
public Assembly LoadFromPath(string fullPath)
{
// We want to load the analyzer assembly assets in default context.
// Use Assembly.Load instead of Assembly.LoadFrom to ensure that if the assembly is ngen'ed, then the native image gets loaded.
return Assembly.Load(AssemblyName.GetAssemblyName(fullPath));
}
}
}
}
......@@ -62,7 +62,7 @@ public AnalyzerReference GetReference()
{
if (File.Exists(_fullPath))
{
_analyzerReference = new AnalyzerFileReference(_fullPath, _loader.LoadFromPath);
_analyzerReference = new AnalyzerFileReference(_fullPath, _loader);
((AnalyzerFileReference)_analyzerReference).AnalyzerLoadFailed += OnAnalyzerLoadError;
}
else
......
......@@ -44,7 +44,7 @@ public override ImageMoniker OverlayIconMoniker
{
get
{
if (_analyzerReference.IsUnresolved)
if (_analyzerReference is UnresolvedAnalyzerReference)
{
return KnownMonikers.OverlayWarning;
}
......@@ -85,7 +85,7 @@ public void Remove()
private static string GetNameText(AnalyzerReference analyzerReference)
{
if (analyzerReference.IsUnresolved)
if (analyzerReference is UnresolvedAnalyzerReference)
{
return analyzerReference.FullPath;
}
......
......@@ -2563,7 +2563,7 @@ public void TestAddRemoveAnalyzerReference()
var project = solution.Projects.First();
var myAnalyzerPath = GetSolutionFileName(@"Analyzers\MyAnalyzer.dll");
var aref = new AnalyzerFileReference(myAnalyzerPath, p => Assembly.Load(File.ReadAllBytes(p)));
var aref = new AnalyzerFileReference(myAnalyzerPath, new InMemoryAssemblyLoader());
// add reference to MyAnalyzer.dll
ws.TryApplyChanges(project.AddAnalyzerReference(aref).Solution);
......@@ -2620,5 +2620,18 @@ public void TestOpenProject_BadLink()
var docs = proj.Documents.ToList();
Assert.Equal(3, docs.Count);
}
private class InMemoryAssemblyLoader : IAnalyzerAssemblyLoader
{
public void AddDependencyLocation(string fullPath)
{
}
public Assembly LoadFromPath(string fullPath)
{
var bytes = File.ReadAllBytes(fullPath);
return Assembly.Load(bytes);
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册