CodeFixService.ProjectCodeFixProvider.cs 3.5 KB
Newer Older
1
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.
2 3 4 5 6 7 8

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis.Diagnostics;
T
Tomas Matousek 已提交
9
using Microsoft.CodeAnalysis.PooledObjects;
10 11 12

namespace Microsoft.CodeAnalysis.CodeFixes
{
13 14
    using TypeInfo = System.Reflection.TypeInfo;

15 16 17 18
    internal partial class CodeFixService
    {
        private class ProjectCodeFixProvider
        {
19 20
            private readonly AnalyzerReference _reference;
            private ImmutableDictionary<string, ImmutableArray<CodeFixProvider>> _fixersPerLanguage;
21 22 23

            public ProjectCodeFixProvider(AnalyzerReference reference)
            {
24 25
                _reference = reference;
                _fixersPerLanguage = ImmutableDictionary<string, ImmutableArray<CodeFixProvider>>.Empty;
26 27 28 29
            }

            public ImmutableArray<CodeFixProvider> GetFixers(string language)
            {
30
                return ImmutableInterlocked.GetOrAdd(ref _fixersPerLanguage, language, CreateFixers);
31 32 33 34 35
            }

            private ImmutableArray<CodeFixProvider> CreateFixers(string language)
            {
                // check whether the analyzer reference knows how to return fixers directly.
C
CyrusNajmabadi 已提交
36
                if (_reference is ICodeFixProviderFactory codeFixProviderFactory)
37 38 39 40 41
                {
                    return codeFixProviderFactory.GetFixers();
                }

                // otherwise, see whether we can pick it up from reference itself
42
                var analyzerFileReference = _reference as AnalyzerFileReference;
43 44 45 46 47
                if (analyzerFileReference == null)
                {
                    return ImmutableArray<CodeFixProvider>.Empty;
                }

48
                var builder = ArrayBuilder<CodeFixProvider>.GetInstance();
49 50 51

                try
                {
C
Cyrus Najmabadi 已提交
52 53
                    var analyzerAssembly = analyzerFileReference.GetAssembly();
                    var typeInfos = analyzerAssembly.DefinedTypes;
54

55
                    foreach (var typeInfo in typeInfos)
56
                    {
57
                        if (typeInfo.IsSubclassOf(typeof(CodeFixProvider)))
58 59 60
                        {
                            try
                            {
61
                                var attribute = typeInfo.GetCustomAttribute<ExportCodeFixProviderAttribute>();
62 63 64 65 66 67
                                if (attribute != null)
                                {
                                    if (attribute.Languages == null ||
                                        attribute.Languages.Length == 0 ||
                                        attribute.Languages.Contains(language))
                                    {
68
                                        builder.Add((CodeFixProvider)Activator.CreateInstance(typeInfo.AsType()));
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
                                    }
                                }
                            }
                            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.
                }

84
                return builder.ToImmutableAndFree();
85 86 87 88
            }
        }
    }
}