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 9 10 11

using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis.Diagnostics;

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

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

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

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

            private ImmutableArray<CodeFixProvider> CreateFixers(string language)
            {
                // check whether the analyzer reference knows how to return fixers directly.
35
                var codeFixProviderFactory = _reference as ICodeFixProviderFactory;
36 37 38 39 40 41
                if (codeFixProviderFactory != null)
                {
                    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
                IEnumerable<TypeInfo> typeInfos = null;
49
                var builder = ArrayBuilder<CodeFixProvider>.GetInstance();
50 51 52 53

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

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

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