File: AbstractRemoveUnnecessaryCastDiagnosticAnalyzer.cs
Web Access
Project: ..\..\..\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.RemoveUnnecessaryCast
{
    internal abstract class AbstractRemoveUnnecessaryCastDiagnosticAnalyzer<
        TLanguageKindEnum,
        TCastExpression> : AbstractBuiltInUnnecessaryCodeStyleDiagnosticAnalyzer
        where TLanguageKindEnum : struct
        where TCastExpression : SyntaxNode
    {
        protected AbstractRemoveUnnecessaryCastDiagnosticAnalyzer()
            : base(IDEDiagnosticIds.RemoveUnnecessaryCastDiagnosticId,
                   EnforceOnBuildValues.RemoveUnnecessaryCast,
                   option: null,
                   fadingOption: null,
                   new LocalizableResourceString(nameof(AnalyzersResources.Remove_Unnecessary_Cast), AnalyzersResources.ResourceManager, typeof(AnalyzersResources)),
                   new LocalizableResourceString(nameof(CompilerExtensionsResources.Cast_is_redundant), CompilerExtensionsResources.ResourceManager, typeof(CompilerExtensionsResources)))
        {
        }
 
        protected abstract ImmutableArray<TLanguageKindEnum> SyntaxKindsOfInterest { get; }
        protected abstract TextSpan GetFadeSpan(TCastExpression node);
        protected abstract bool IsUnnecessaryCast(SemanticModel model, TCastExpression node, CancellationToken cancellationToken);
 
        public override DiagnosticAnalyzerCategory GetAnalyzerCategory()
            => DiagnosticAnalyzerCategory.SemanticSpanAnalysis;
 
        protected override void InitializeWorker(AnalysisContext context)
            => context.RegisterSyntaxNodeAction(AnalyzeSyntax, SyntaxKindsOfInterest);
 
        private void AnalyzeSyntax(SyntaxNodeAnalysisContext context)
        {
            var diagnostic = TryRemoveCastExpression(
                context.SemanticModel,
                (TCastExpression)context.Node,
                context.CancellationToken);
 
            if (diagnostic != null)
            {
                context.ReportDiagnostic(diagnostic);
            }
        }
 
        private Diagnostic? TryRemoveCastExpression(SemanticModel model, TCastExpression node, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
 
            if (!IsUnnecessaryCast(model, node, cancellationToken))
            {
                return null;
            }
 
            var tree = model.SyntaxTree;
            if (tree.OverlapsHiddenPosition(node.Span, cancellationToken))
            {
                return null;
            }
 
            return Diagnostic.Create(
                Descriptor,
                node.SyntaxTree.GetLocation(GetFadeSpan(node)),
                ImmutableArray.Create(node.GetLocation()));
        }
    }
}