提交 618d74d5 编写于 作者: S Sam Harwell

Simplify extension providers

上级 dd4dbcdb
......@@ -3,84 +3,40 @@
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis.CodeFixes
{
using TypeInfo = System.Reflection.TypeInfo;
internal partial class CodeFixService
{
private class ProjectCodeFixProvider
: AbstractProjectExtensionProvider<CodeFixProvider, ExportCodeFixProviderAttribute>
{
private readonly AnalyzerReference _reference;
private ImmutableDictionary<string, ImmutableArray<CodeFixProvider>> _fixersPerLanguage;
public ProjectCodeFixProvider(AnalyzerReference reference)
: base(reference)
{
_reference = reference;
_fixersPerLanguage = ImmutableDictionary<string, ImmutableArray<CodeFixProvider>>.Empty;
}
public ImmutableArray<CodeFixProvider> GetFixers(string language)
=> ImmutableInterlocked.GetOrAdd(ref _fixersPerLanguage, language, CreateFixers);
protected override bool SupportsLanguage(ExportCodeFixProviderAttribute exportAttribute, string language)
{
return exportAttribute.Languages == null
|| exportAttribute.Languages.Length == 0
|| exportAttribute.Languages.Contains(language);
}
private ImmutableArray<CodeFixProvider> CreateFixers(string language)
protected override bool TryGetExtensionsFromReference(AnalyzerReference reference, out ImmutableArray<CodeFixProvider> extensions)
{
// check whether the analyzer reference knows how to return fixers directly.
if (_reference is ICodeFixProviderFactory codeFixProviderFactory)
{
return codeFixProviderFactory.GetFixers();
}
// otherwise, see whether we can pick it up from reference itself
if (!(_reference is AnalyzerFileReference analyzerFileReference))
{
return ImmutableArray<CodeFixProvider>.Empty;
}
using var builderDisposer = ArrayBuilder<CodeFixProvider>.GetInstance(out var builder);
try
{
var analyzerAssembly = analyzerFileReference.GetAssembly();
var typeInfos = analyzerAssembly.DefinedTypes;
foreach (var typeInfo in typeInfos)
{
if (typeInfo.IsSubclassOf(typeof(CodeFixProvider)))
{
try
{
var attribute = typeInfo.GetCustomAttribute<ExportCodeFixProviderAttribute>();
if (attribute != null)
{
if (attribute.Languages == null ||
attribute.Languages.Length == 0 ||
attribute.Languages.Contains(language))
{
builder.Add((CodeFixProvider)Activator.CreateInstance(typeInfo.AsType()));
}
}
}
catch
{
}
}
}
}
catch
if (reference is ICodeFixProviderFactory codeFixProviderFactory)
{
// REVIEW: is the below message right?
// NOTE: We could report "unable to load analyzer" exception here but it should have been already reported by DiagnosticService.
extensions = codeFixProviderFactory.GetFixers();
return true;
}
return builder.ToImmutable();
extensions = default;
return false;
}
}
}
......
......@@ -807,7 +807,7 @@ static ImmutableArray<IConfigurationFixProvider> GetConfigurationFixProviders(Li
foreach (var reference in project.AnalyzerReferences)
{
var projectCodeFixerProvider = _analyzerReferenceToFixersMap.GetValue(reference, _createProjectCodeFixProvider);
foreach (var fixer in projectCodeFixerProvider.GetFixers(project.Language))
foreach (var fixer in projectCodeFixerProvider.GetExtensions(project.Language))
{
var fixableIds = this.GetFixableDiagnosticIds(fixer, extensionManager);
foreach (var id in fixableIds)
......
......@@ -9,7 +9,6 @@
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
......@@ -229,7 +228,7 @@ ImmutableArray<CodeRefactoringProvider> ComputeProjectRefactorings(Project proje
foreach (var reference in project.AnalyzerReferences)
{
var projectCodeRefactoringProvider = _analyzerReferenceToRefactoringsMap.GetValue(reference, _createProjectCodeRefactoringsProvider);
foreach (var refactoring in projectCodeRefactoringProvider.GetRefactorings(project.Language))
foreach (var refactoring in projectCodeRefactoringProvider.GetExtensions(project.Language))
{
builder.Add(refactoring);
}
......@@ -240,70 +239,31 @@ ImmutableArray<CodeRefactoringProvider> ComputeProjectRefactorings(Project proje
}
private class ProjectCodeRefactoringProvider
: AbstractProjectExtensionProvider<CodeRefactoringProvider, ExportCodeRefactoringProviderAttribute>
{
private readonly AnalyzerReference _reference;
private ImmutableDictionary<string, ImmutableArray<CodeRefactoringProvider>> _refactoringsPerLanguage;
public ProjectCodeRefactoringProvider(AnalyzerReference reference)
: base(reference)
{
_reference = reference;
_refactoringsPerLanguage = ImmutableDictionary<string, ImmutableArray<CodeRefactoringProvider>>.Empty;
}
public ImmutableArray<CodeRefactoringProvider> GetRefactorings(string language)
=> ImmutableInterlocked.GetOrAdd(ref _refactoringsPerLanguage, language, (language, provider) => provider.CreateRefactorings(language), this);
protected override bool SupportsLanguage(ExportCodeRefactoringProviderAttribute exportAttribute, string language)
{
return exportAttribute.Languages == null
|| exportAttribute.Languages.Length == 0
|| exportAttribute.Languages.Contains(language);
}
private ImmutableArray<CodeRefactoringProvider> CreateRefactorings(string language)
protected override bool TryGetExtensionsFromReference(AnalyzerReference reference, out ImmutableArray<CodeRefactoringProvider> extensions)
{
// check whether the analyzer reference knows how to return fixers directly.
if (_reference is ICodeRefactoringProviderFactory codeRefactoringProviderFactory)
{
return codeRefactoringProviderFactory.GetRefactorings();
}
// otherwise, see whether we can pick it up from reference itself
if (!(_reference is AnalyzerFileReference analyzerFileReference))
{
return ImmutableArray<CodeRefactoringProvider>.Empty;
}
var builder = ArrayBuilder<CodeRefactoringProvider>.GetInstance();
try
{
var analyzerAssembly = analyzerFileReference.GetAssembly();
var typeInfos = analyzerAssembly.DefinedTypes;
foreach (var typeInfo in typeInfos)
{
if (typeInfo.IsSubclassOf(typeof(CodeRefactoringProvider)))
{
try
{
var attribute = typeInfo.GetCustomAttribute<ExportCodeRefactoringProviderAttribute>();
if (attribute != null)
{
if (attribute.Languages == null ||
attribute.Languages.Length == 0 ||
attribute.Languages.Contains(language))
{
builder.Add((CodeRefactoringProvider)Activator.CreateInstance(typeInfo.AsType())!);
}
}
}
catch
{
}
}
}
}
catch
if (reference is ICodeRefactoringProviderFactory codeRefactoringProviderFactory)
{
// REVIEW: is the below message right?
// NOTE: We could report "unable to load analyzer" exception here but it should have been already reported by DiagnosticService.
extensions = codeRefactoringProviderFactory.GetRefactorings();
return true;
}
return builder.ToImmutableAndFree();
extensions = default;
return false;
}
}
}
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Immutable;
using System.Reflection;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis
{
internal abstract class AbstractProjectExtensionProvider<TExtension, TExportAttribute>
where TExportAttribute : Attribute
{
private readonly AnalyzerReference _reference;
private ImmutableDictionary<string, ImmutableArray<TExtension>> _extensionsPerLanguage;
public AbstractProjectExtensionProvider(AnalyzerReference reference)
{
_reference = reference;
_extensionsPerLanguage = ImmutableDictionary<string, ImmutableArray<TExtension>>.Empty;
}
public ImmutableArray<TExtension> GetExtensions(string language)
{
return ImmutableInterlocked.GetOrAdd(ref _extensionsPerLanguage, language, (language, provider) => provider.CreateExtensions(language), this);
}
protected virtual bool SupportsLanguage(TExportAttribute exportAttribute, string language)
{
return true;
}
protected virtual bool TryGetExtensionsFromReference(AnalyzerReference reference, out ImmutableArray<TExtension> extensions)
{
extensions = default;
return false;
}
private ImmutableArray<TExtension> CreateExtensions(string language)
{
// check whether the analyzer reference knows how to return fixers directly.
if (TryGetExtensionsFromReference(_reference, out var extensions))
{
return extensions;
}
// otherwise, see whether we can pick it up from reference itself
if (!(_reference is AnalyzerFileReference analyzerFileReference))
{
return ImmutableArray<TExtension>.Empty;
}
using var _ = ArrayBuilder<TExtension>.GetInstance(out var builder);
try
{
var analyzerAssembly = analyzerFileReference.GetAssembly();
var typeInfos = analyzerAssembly.DefinedTypes;
foreach (var typeInfo in typeInfos)
{
if (typeInfo.IsSubclassOf(typeof(TExtension)))
{
try
{
var attribute = typeInfo.GetCustomAttribute<TExportAttribute>();
if (attribute is object && SupportsLanguage(attribute, language))
{
builder.Add((TExtension)Activator.CreateInstance(typeInfo.AsType()));
}
}
catch
{
}
}
}
}
catch
{
// REVIEW: is the below message right?
// NOTE: We could report "unable to load analyzer" exception here but it should have been already reported by DiagnosticService.
}
return builder.ToImmutable();
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册