// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Collections.Immutable; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.AnalyzerPowerPack.Utilities; using Microsoft.CodeAnalysis; namespace Microsoft.AnalyzerPowerPack.Design { /// /// CA1012: Abstract classes should not have public constructors /// [DiagnosticAnalyzer(LanguageNames.CSharp, LanguageNames.VisualBasic)] public sealed class CA1012DiagnosticAnalyzer : AbstractNamedTypeAnalyzer { internal const string RuleId = "CA1012"; private static readonly LocalizableString s_localizableTitle = new LocalizableResourceString(nameof(AnalyzerPowerPackRulesResources.AbstractTypesShouldNotHavePublicConstructors), AnalyzerPowerPackRulesResources.ResourceManager, typeof(AnalyzerPowerPackRulesResources)); private static readonly LocalizableString s_localizableMessage = new LocalizableResourceString(nameof(AnalyzerPowerPackRulesResources.TypeIsAbstractButHasPublicConstructors), AnalyzerPowerPackRulesResources.ResourceManager, typeof(AnalyzerPowerPackRulesResources)); internal static DiagnosticDescriptor Rule = new DiagnosticDescriptor(RuleId, s_localizableTitle, s_localizableMessage, AnalyzerPowerPackDiagnosticCategory.Design, DiagnosticSeverity.Warning, isEnabledByDefault: false, helpLinkUri: "http://msdn.microsoft.com/library/ms182126.aspx", customTags: DiagnosticCustomTags.Microsoft); public override ImmutableArray SupportedDiagnostics { get { return ImmutableArray.Create(Rule); } } protected override void AnalyzeSymbol(INamedTypeSymbol symbol, Compilation compilation, Action addDiagnostic, AnalyzerOptions options, CancellationToken cancellationToken) { if (symbol.IsAbstract) { // TODO: Should we also check symbol.GetResultantVisibility() == SymbolVisibility.Public? var hasAnyPublicConstructors = symbol.InstanceConstructors.Any( (constructor) => constructor.DeclaredAccessibility == Accessibility.Public); if (hasAnyPublicConstructors) { addDiagnostic(symbol.CreateDiagnostic(Rule, symbol.Name)); } } } } }