File: CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer.cs
Web Access
Project: ..\..\..\src\Features\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.Features.csproj (Microsoft.CodeAnalysis.CSharp.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.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.LanguageService;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports
{
    [DiagnosticAnalyzer(LanguageNames.CSharp)]
    internal sealed class CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer :
        AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer<UsingDirectiveSyntax>
    {
        public CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer()
            : base(new LocalizableResourceString(nameof(CSharpAnalyzersResources.Using_directive_is_unnecessary), CSharpAnalyzersResources.ResourceManager, typeof(CSharpAnalyzersResources)))
        {
        }
 
        protected override ISyntaxFacts SyntaxFacts
            => CSharpSyntaxFacts.Instance;
 
        // C# has no need to do any merging of using statements.  Only VB needs to
        // merge import clauses to an import statement if it all the import clauses
        // are unnecessary.
        protected override ImmutableArray<SyntaxNode> MergeImports(ImmutableArray<UsingDirectiveSyntax> unnecessaryImports)
            => ImmutableArray<SyntaxNode>.CastUp(unnecessaryImports);
 
        protected override IUnnecessaryImportsProvider<UsingDirectiveSyntax> UnnecessaryImportsProvider
            => CSharpUnnecessaryImportsProvider.Instance;
 
        protected override bool IsRegularCommentOrDocComment(SyntaxTrivia trivia)
            => trivia.IsRegularComment() || trivia.IsDocComment();
 
        protected override SyntaxToken? TryGetLastToken(SyntaxNode node)
            // No special behavior needed for C#
            => null;
 
        protected override IEnumerable<TextSpan> GetFixableDiagnosticSpans(
            IEnumerable<SyntaxNode> nodes, SyntaxTree tree, CancellationToken cancellationToken)
        {
            Contract.ThrowIfFalse(nodes.Any());
 
            var nodesContainingUnnecessaryUsings = new HashSet<SyntaxNode>();
            foreach (var node in nodes)
            {
                var nodeContainingUnnecessaryUsings = node.GetAncestors().First(n => n is BaseNamespaceDeclarationSyntax or CompilationUnitSyntax);
                if (!nodesContainingUnnecessaryUsings.Add(nodeContainingUnnecessaryUsings))
                {
                    continue;
                }
 
                yield return nodeContainingUnnecessaryUsings is BaseNamespaceDeclarationSyntax namespaceDeclaration
                    ? namespaceDeclaration.Usings.GetContainedSpan()
                    : ((CompilationUnitSyntax)nodeContainingUnnecessaryUsings).Usings.GetContainedSpan();
            }
        }
    }
}