File: MiscellaneousAnalyzerTests.cs
Web Access
Project: ..\..\..\src\Microsoft.CodeAnalysis.NetAnalyzers\tests\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests.csproj (Microsoft.CodeAnalysis.NetAnalyzers.UnitTests)
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the MIT license.  See License.txt in the project root for license information.
 
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis.Diagnostics;
using Xunit;
 
namespace Microsoft.CodeAnalysis.NetAnalyzers.UnitTests
{
    public class MiscellaneousAnalyzerTests
    {
        private sealed class AnalyzerAssemblyLoader : IAnalyzerAssemblyLoader
        {
            public static IAnalyzerAssemblyLoader Instance = new AnalyzerAssemblyLoader();
 
            private AnalyzerAssemblyLoader() { }
 
            public void AddDependencyLocation(string fullPath) { }
 
            public Assembly LoadFromPath(string fullPath) => Assembly.LoadFrom(fullPath);
        }
 
        [Fact]
        public void TestGlobalizationAnalyzersSubclassAbstractGlobalizationDiagnosticAnalyzer()
        {
            // <repo_root>\artifacts\bin\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests\Debug\netcoreapp3.1\Microsoft.CodeAnalysis.NetAnalyzers.UnitTests.dll
            var testsAssemblyPath = typeof(MiscellaneousAnalyzerTests).Assembly.Location;
 
            var directory = Path.GetDirectoryName(testsAssemblyPath);
 
            foreach (var assembly in new[] { "Microsoft.CodeAnalysis.NetAnalyzers.dll", "Microsoft.CodeAnalysis.CSharp.NetAnalyzers.dll", "Microsoft.CodeAnalysis.VisualBasic.NetAnalyzers.dll" })
            {
                var path = Path.Combine(directory, assembly);
                Assert.True(File.Exists(path), $"File {path} doesn't exist.");
                var analyzerFileReference = new AnalyzerFileReference(path, AnalyzerAssemblyLoader.Instance);
                analyzerFileReference.AnalyzerLoadFailed += AnalyzerFileReference_AnalyzerLoadFailed;
                var analyzers = analyzerFileReference.GetAnalyzersForAllLanguages();
                foreach (var analyzer in analyzers)
                {
                    if (analyzer.SupportedDiagnostics.Length == 0)
                    {
                        continue;
                    }
 
                    var analyzerType = analyzer.GetType();
                    var isAbstractGlobalizationDiagnosticAnalyzer = IsSubClassOfGlobalizationAnalyzer(analyzerType);
                    if (analyzer.SupportedDiagnostics.All(d => d.Category == "Globalization"))
                    {
                        Debug.Assert(isAbstractGlobalizationDiagnosticAnalyzer, $"Analyzer {analyzerType.Name} was expected to inherit AbstractGlobalizationDiagnosticAnalyzer.");
                    }
                    else
                    {
                        // Note: If an analyzer have one Globalization rule and other non-Globalization rules, it shouldn't inherit AbstractGlobalizationDiagnosticAnalyzer.
                        // Instead, it should check for InvariantCulture MSBuild property for the Globalization rules only.
                        Debug.Assert(!isAbstractGlobalizationDiagnosticAnalyzer, $"Analyzer {analyzerType.Name} wasn't expected to inherit AbstractGlobalizationDiagnosticAnalyzer.");
                    }
                }
            }
 
            static void AnalyzerFileReference_AnalyzerLoadFailed(object sender, AnalyzerLoadFailureEventArgs e)
            => throw e.Exception ?? new NotSupportedException(e.Message);
        }
 
        private static bool IsSubClassOfGlobalizationAnalyzer(Type analyzerType)
        {
            var baseType = analyzerType.BaseType;
            while (baseType != null)
            {
                if (baseType.Name == "AbstractGlobalizationDiagnosticAnalyzer")
                    return true;
                baseType = baseType.BaseType;
            }
 
            return false;
        }
    }
}