CodeFixService.ProjectCodeFixProvider.cs 3.6 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.
36
                var codeFixProviderFactory = _reference as ICodeFixProviderFactory;
37 38 39 40 41 42
                if (codeFixProviderFactory != null)
                {
                    return codeFixProviderFactory.GetFixers();
                }

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

49
                IEnumerable<TypeInfo> typeInfos = null;
50
                var builder = ArrayBuilder<CodeFixProvider>.GetInstance();
51 52 53 54

                try
                {
                    Assembly analyzerAssembly = analyzerFileReference.GetAssembly();
55
                    typeInfos = analyzerAssembly.DefinedTypes;
56

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

86
                return builder.ToImmutableAndFree();
87 88 89 90
            }
        }
    }
}