提交 4b5567a0 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #14953 from CyrusNajmabadi/moveTypeImports2

Simplify services for remove-unnecessary-import/using.
......@@ -234,8 +234,8 @@
<Compile Include="Diagnostics\MockDiagnosticAnalyzerTests.cs" />
<Compile Include="Diagnostics\RemoveUnnecessaryCast\RemoveUnnecessaryCastTests.cs" />
<Compile Include="Diagnostics\RemoveUnnecessaryCast\RemoveUnnecessaryCastTests_FixAllTests.cs" />
<Compile Include="Diagnostics\RemoveUnnecessaryUsings\RemoveUnnecessaryUsingsTests.cs" />
<Compile Include="Diagnostics\RemoveUnnecessaryUsings\RemoveUnnecessaryUsingsTests_FixAllTests.cs" />
<Compile Include="RemoveUnnecessaryImports\RemoveUnnecessaryImportsTests.cs" />
<Compile Include="RemoveUnnecessaryImports\RemoveUnnecessaryImportsTests_FixAllTests.cs" />
<Compile Include="Diagnostics\SimplifyTypeNames\SimplifyTypeNamesTests_FixAllTests.cs" />
<Compile Include="Diagnostics\SimplifyTypeNames\SimplifyTypeNamesTests.cs" />
<Compile Include="Diagnostics\Suppression\SuppressionTest_FixAllTests.cs" />
......
......@@ -4,20 +4,21 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.RemoveUnusedUsings;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.RemoveUnnecessaryUsings
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnnecessaryImports
{
public partial class RemoveUnnecessaryUsingsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
public partial class RemoveUnnecessaryImportsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
internal override Tuple<DiagnosticAnalyzer, CodeFixProvider> CreateDiagnosticProviderAndFixer(Workspace workspace)
{
return new Tuple<DiagnosticAnalyzer, CodeFixProvider>(
new CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer(), new RemoveUnnecessaryUsingsCodeFixProvider());
new CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer(),
new CSharpRemoveUnnecessaryImportsCodeFixProvider());
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)]
......
// 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.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.RemoveUnnecessaryUsings
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.RemoveUnnecessaryImports
{
public partial class RemoveUnnecessaryUsingsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
public partial class RemoveUnnecessaryImportsTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
{
#region "Fix all occurrences tests"
......@@ -240,4 +241,4 @@ class Program3
#endregion
}
}
}
\ No newline at end of file
......@@ -4,24 +4,24 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames;
using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
using Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles;
using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.VisualStudio.Text.Adornments;
using Microsoft.VisualStudio.Text.Tagging;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics;
using Microsoft.CodeAnalysis.Text.Shared.Extensions;
using Microsoft.CodeAnalysis.CodeStyle;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Squiggles
{
......
......@@ -196,8 +196,8 @@
<Compile Include="QualifyMemberAccess\QualifyMemberAccessTests_FixAllTests.vb" />
<Compile Include="Diagnostics\RemoveUnnecessaryCast\RemoveUnnecessaryCastTests.vb" />
<Compile Include="Diagnostics\RemoveUnnecessaryCast\RemoveUnnecessaryCastTests_FixAllTests.vb" />
<Compile Include="Diagnostics\RemoveUnnecessaryImports\RemoveUnnecessaryImportsTests.vb" />
<Compile Include="Diagnostics\RemoveUnnecessaryImports\RemoveUnnecessaryImportsTests_FixAllTests.vb" />
<Compile Include="RemoveUnnecessaryImports\RemoveUnnecessaryImportsTests.vb" />
<Compile Include="RemoveUnnecessaryImports\RemoveUnnecessaryImportsTests_FixAllTests.vb" />
<Compile Include="Diagnostics\SimplifyTypeNames\SimplifyTypeNamesTests_FixAllTests.vb" />
<Compile Include="Diagnostics\SimplifyTypeNames\SimplifyTypeNamesTests.vb" />
<Compile Include="Diagnostics\Spellcheck\SpellCheckTests.vb" />
......
......@@ -3,15 +3,17 @@
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Extensions
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics
Imports Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.RemoveUnnecessaryImports
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.RemoveUnnecessaryImports
Partial Public Class RemoveUnnecessaryImportsTests
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
Friend Overrides Function CreateDiagnosticProviderAndFixer(workspace As Workspace) As Tuple(Of DiagnosticAnalyzer, CodeFixProvider)
Return New Tuple(Of DiagnosticAnalyzer, CodeFixProvider)(New VisualBasicRemoveUnnecessaryImportsDiagnosticAnalyzer(), New RemoveUnnecessaryImportsCodeFixProvider())
Return New Tuple(Of DiagnosticAnalyzer, CodeFixProvider)(
New VisualBasicRemoveUnnecessaryImportsDiagnosticAnalyzer(),
New VisualBasicRemoveUnnecessaryImportsCodeFixProvider())
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnnecessaryImports)>
......
Option Strict Off
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Option Strict Off
Imports Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.Diagnostics.RemoveUnnecessaryImports
Namespace Microsoft.CodeAnalysis.Editor.VisualBasic.UnitTests.RemoveUnnecessaryImports
Partial Public Class RemoveUnnecessaryImportsTests
Inherits AbstractVisualBasicDiagnosticProviderBasedUserDiagnosticTest
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Generic
Imports System.Collections.Immutable
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.CodeStyle
......@@ -10,7 +9,7 @@ Imports Microsoft.CodeAnalysis.Editor.UnitTests.Squiggles
Imports Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces
Imports Microsoft.CodeAnalysis.Options
Imports Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames
Imports Microsoft.CodeAnalysis.VisualBasic.Diagnostics.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
Imports Microsoft.VisualStudio.Text.Adornments
Imports Microsoft.VisualStudio.Text.Tagging
......
......@@ -57,6 +57,8 @@
</Compile>
<Compile Include="Structure\Providers\ArrowExpressionClauseStructureProvider.cs" />
<Compile Include="ConvertToInterpolatedString\CSharpConvertConcatenationToInterpolatedStringRefactoringProvider.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpRemoveUnnecessaryImportsService.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpUnnecessaryImportsService.cs" />
<Compile Include="Structure\Providers\InitializerExpressionStructureProvider.cs" />
<Compile Include="UseCoalesceExpression\CSharpUseCoalesceExpressionForNullableDiagnosticAnalyzer.cs" />
<Compile Include="UseCoalesceExpression\CSharpUseCoalesceExpressionDiagnosticAnalyzer.cs" />
......@@ -112,7 +114,7 @@
<Compile Include="CodeFixes\NamingStyles\CSharpNamingStyleCodeFixProvider.cs" />
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.RemoveUnnecessaryCastFixAllProvider.cs" />
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.cs" />
<Compile Include="CodeFixes\RemoveUnnecessaryUsings\RemoveUnnecessaryUsingsCodeFixProvider.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpRemoveUnnecessaryImportsCodeFixProvider.cs" />
<Compile Include="CodeFixes\SimplifyTypeNames\SimplifyTypeNamesCodeFixProvider.SimplifyTypeNamesFixAllProvider.cs" />
<Compile Include="CodeFixes\SimplifyTypeNames\SimplifyTypeNamesCodeFixProvider.cs" />
<Compile Include="CodeFixes\Suppression\CSharpSuppressionCodeFixProvider.cs" />
......@@ -294,7 +296,7 @@
<Compile Include="Diagnostics\Analyzers\CSharpNamingStyleDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpUnboundIdentifiersDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpRemoveUnnecessaryCastDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpSimplifyTypeNamesDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpUseExplicitTypeDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\CSharpUseImplicitTypeDiagnosticAnalyzer.cs" />
......@@ -435,8 +437,8 @@
<Compile Include="Structure\Providers\RegionDirectiveStructureProvider.cs" />
<Compile Include="Structure\Providers\SimpleLambdaExpressionStructureProvider.cs" />
<Compile Include="Structure\Providers\TypeDeclarationStructureProvider.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpRemoveUnnecessaryImportsService.cs" />
<Compile Include="RemoveUnnecessaryImports\CSharpRemoveUnnecessaryImportsService.Rewriter.cs" />
<Compile Include="RemoveUnnecessaryImports\AbstractCSharpRemoveUnnecessaryImportsService.cs" />
<Compile Include="RemoveUnnecessaryImports\AbstractCSharpRemoveUnnecessaryImportsService.Rewriter.cs" />
<Compile Include="ReplaceMethodWithProperty\CSharpReplaceMethodWithPropertyService.cs" />
<Compile Include="ReplacePropertyWithMethods\CSharpReplacePropertyWithMethodsService.cs" />
<Compile Include="SignatureHelp\AbstractCSharpSignatureHelpProvider.cs" />
......@@ -472,6 +474,9 @@
<ItemGroup>
<Compile Include="CodeFixes\SpellCheck\CSharpSpellCheckCodeFixProvider.cs" />
</ItemGroup>
<ItemGroup>
<Folder Include="CodeFixes\RemoveUnnecessaryUsings\" />
</ItemGroup>
<Import Project="..\..\..\Compilers\CSharp\CSharpAnalyzerDriver\CSharpAnalyzerDriver.projitems" Label="Shared" />
<Import Project="..\..\..\..\build\Targets\Imports.targets" />
</Project>
\ No newline at end of file
......@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports
{
internal partial class CSharpRemoveUnnecessaryImportsService
internal partial class AbstractCSharpRemoveUnnecessaryImportsService
{
private class Rewriter : CSharpSyntaxRewriter
{
......
// 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.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports
{
internal partial class AbstractCSharpRemoveUnnecessaryImportsService :
AbstractRemoveUnnecessaryImportsService<UsingDirectiveSyntax>
{
public override async Task<Document> RemoveUnnecessaryImportsAsync(
Document document,
Func<SyntaxNode, bool> predicate,
CancellationToken cancellationToken)
{
predicate = predicate ?? Functions<SyntaxNode>.True;
using (Logger.LogBlock(FunctionId.Refactoring_RemoveUnnecessaryImports_CSharp, cancellationToken))
{
var unnecessaryImports = await GetCommonUnnecessaryImportsOfAllContextAsync(
document, predicate, cancellationToken).ConfigureAwait(false);
if (unnecessaryImports == null || unnecessaryImports.Any(import => import.OverlapsHiddenPosition(cancellationToken)))
{
return document;
}
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var oldRoot = (CompilationUnitSyntax)root;
var newRoot = (CompilationUnitSyntax)new Rewriter(unnecessaryImports, cancellationToken).Visit(oldRoot);
cancellationToken.ThrowIfCancellationRequested();
return document.WithSyntaxRoot(await FormatResultAsync(document, newRoot, cancellationToken).ConfigureAwait(false));
}
}
protected override ImmutableArray<UsingDirectiveSyntax> GetUnnecessaryImports(
SemanticModel model, SyntaxNode root,
Func<SyntaxNode, bool> predicate, CancellationToken cancellationToken)
{
predicate = predicate ?? Functions<SyntaxNode>.True;
var diagnostics = model.GetDiagnostics(cancellationToken: cancellationToken);
if (!diagnostics.Any())
{
return ImmutableArray<UsingDirectiveSyntax>.Empty;
}
var unnecessaryImports = new HashSet<UsingDirectiveSyntax>();
foreach (var diagnostic in diagnostics)
{
if (diagnostic.Id == "CS8019")
{
var node = root.FindNode(diagnostic.Location.SourceSpan) as UsingDirectiveSyntax;
if (node != null && predicate(node))
{
unnecessaryImports.Add(node);
}
}
}
return unnecessaryImports.ToImmutableArray();
}
private async Task<SyntaxNode> FormatResultAsync(Document document, CompilationUnitSyntax newRoot, CancellationToken cancellationToken)
{
var spans = new List<TextSpan>();
AddFormattingSpans(newRoot, spans, cancellationToken);
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
return await Formatter.FormatAsync(newRoot, spans, document.Project.Solution.Workspace, options, cancellationToken: cancellationToken).ConfigureAwait(false);
}
private void AddFormattingSpans(
CompilationUnitSyntax compilationUnit,
List<TextSpan> spans,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
spans.Add(TextSpan.FromBounds(0, GetEndPosition(compilationUnit, compilationUnit.Members)));
foreach (var @namespace in compilationUnit.Members.OfType<NamespaceDeclarationSyntax>())
{
AddFormattingSpans(@namespace, spans, cancellationToken);
}
}
private void AddFormattingSpans(
NamespaceDeclarationSyntax namespaceMember,
List<TextSpan> spans,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
spans.Add(TextSpan.FromBounds(namespaceMember.SpanStart, GetEndPosition(namespaceMember, namespaceMember.Members)));
foreach (var @namespace in namespaceMember.Members.OfType<NamespaceDeclarationSyntax>())
{
AddFormattingSpans(@namespace, spans, cancellationToken);
}
}
private int GetEndPosition(SyntaxNode container, SyntaxList<MemberDeclarationSyntax> list)
{
return list.Count > 0 ? list[0].SpanStart : container.Span.End;
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RemoveUnnecessaryImports), Shared]
[ExtensionOrder(After = PredefinedCodeFixProviderNames.AddMissingReference)]
internal class CSharpRemoveUnnecessaryImportsCodeFixProvider : AbstractRemoveUnnecessaryImportsCodeFixProvider
{
protected override string GetTitle()
=> CSharpFeaturesResources.Remove_Unnecessary_Usings;
}
}
\ No newline at end of file
// 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.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Diagnostics.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.RemoveUnnecessaryImports
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports
{
[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer :
RemoveUnnecessaryImportsDiagnosticAnalyzerBase
AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer
{
private static readonly LocalizableString s_TitleAndMessageFormat =
new LocalizableResourceString(nameof(CSharpFeaturesResources.Using_directive_is_unnecessary), CSharpFeaturesResources.ResourceManager, typeof(CSharpFeaturesResources));
protected override LocalizableString GetTitleAndMessageFormatForClassificationIdDescriptor()
{
return s_TitleAndMessageFormat;
}
=> s_TitleAndMessageFormat;
protected override IEnumerable<SyntaxNode> GetUnnecessaryImports(
SemanticModel semanticModel, SyntaxNode root, CancellationToken cancellationToken)
{
return CSharpRemoveUnnecessaryImportsService.GetUnnecessaryImportsShared(
semanticModel, root, predicate: null, cancellationToken: cancellationToken);
}
// 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<SyntaxNode> unnecessaryImports)
=> unnecessaryImports;
protected override IEnumerable<TextSpan> GetFixableDiagnosticSpans(
IEnumerable<SyntaxNode> nodes, SyntaxTree tree, CancellationToken cancellationToken)
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// 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.Generic;
using System.Collections.Immutable;
using System.Composition;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports
{
[ExportLanguageService(typeof(IRemoveUnnecessaryImportsService), LanguageNames.CSharp), Shared]
internal partial class CSharpRemoveUnnecessaryImportsService :
AbstractRemoveUnnecessaryImportsService<UsingDirectiveSyntax>
internal partial class CSharpRemoveUnnecessaryImportsService : AbstractCSharpRemoveUnnecessaryImportsService
{
public static ImmutableArray<UsingDirectiveSyntax> GetUnnecessaryImportsShared(
SemanticModel semanticModel, SyntaxNode root,
Func<SyntaxNode, bool> predicate, CancellationToken cancellationToken)
{
predicate = predicate ?? Functions<SyntaxNode>.True;
var diagnostics = semanticModel.GetDiagnostics(cancellationToken: cancellationToken);
if (!diagnostics.Any())
{
return ImmutableArray<UsingDirectiveSyntax>.Empty;
}
var unnecessaryImports = new HashSet<UsingDirectiveSyntax>();
foreach (var diagnostic in diagnostics)
{
if (diagnostic.Id == "CS8019")
{
var node = root.FindNode(diagnostic.Location.SourceSpan) as UsingDirectiveSyntax;
if (node != null && predicate(node))
{
unnecessaryImports.Add(node);
}
}
}
return unnecessaryImports.ToImmutableArray();
}
public override async Task<Document> RemoveUnnecessaryImportsAsync(
Document document,
Func<SyntaxNode, bool> predicate,
CancellationToken cancellationToken)
{
predicate = predicate ?? Functions<SyntaxNode>.True;
using (Logger.LogBlock(FunctionId.Refactoring_RemoveUnnecessaryImports_CSharp, cancellationToken))
{
var unnecessaryImports = await GetCommonUnnecessaryImportsOfAllContextAsync(
document, predicate, cancellationToken).ConfigureAwait(false);
if (unnecessaryImports == null || unnecessaryImports.Any(import => import.OverlapsHiddenPosition(cancellationToken)))
{
return document;
}
var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
var oldRoot = (CompilationUnitSyntax)root;
var newRoot = (CompilationUnitSyntax)new Rewriter(unnecessaryImports, cancellationToken).Visit(oldRoot);
cancellationToken.ThrowIfCancellationRequested();
return document.WithSyntaxRoot(await FormatResultAsync(document, newRoot, cancellationToken).ConfigureAwait(false));
}
}
protected override ImmutableArray<UsingDirectiveSyntax> GetUnnecessaryImports(
SemanticModel model, SyntaxNode root,
Func<SyntaxNode, bool> predicate, CancellationToken cancellationToken)
{
return GetUnnecessaryImportsShared(model, root, predicate, cancellationToken);
}
private async Task<SyntaxNode> FormatResultAsync(Document document, CompilationUnitSyntax newRoot, CancellationToken cancellationToken)
{
var spans = new List<TextSpan>();
AddFormattingSpans(newRoot, spans, cancellationToken);
var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
return await Formatter.FormatAsync(newRoot, spans, document.Project.Solution.Workspace, options, cancellationToken: cancellationToken).ConfigureAwait(false);
}
private void AddFormattingSpans(
CompilationUnitSyntax compilationUnit,
List<TextSpan> spans,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
spans.Add(TextSpan.FromBounds(0, GetEndPosition(compilationUnit, compilationUnit.Members)));
foreach (var @namespace in compilationUnit.Members.OfType<NamespaceDeclarationSyntax>())
{
AddFormattingSpans(@namespace, spans, cancellationToken);
}
}
private void AddFormattingSpans(
NamespaceDeclarationSyntax namespaceMember,
List<TextSpan> spans,
CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
spans.Add(TextSpan.FromBounds(namespaceMember.SpanStart, GetEndPosition(namespaceMember, namespaceMember.Members)));
foreach (var @namespace in namespaceMember.Members.OfType<NamespaceDeclarationSyntax>())
{
AddFormattingSpans(@namespace, spans, cancellationToken);
}
}
private int GetEndPosition(SyntaxNode container, SyntaxList<MemberDeclarationSyntax> list)
{
return list.Count > 0 ? list[0].SpanStart : container.Span.End;
}
}
}
\ No newline at end of file
// 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.Composition;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
namespace Microsoft.CodeAnalysis.CSharp.RemoveUnnecessaryImports
{
[ExportLanguageService(typeof(IUnnecessaryImportsService), LanguageNames.CSharp), Shared]
internal partial class CSharpUnnecessaryImportsService : AbstractCSharpRemoveUnnecessaryImportsService
{
}
}
\ No newline at end of file
......@@ -106,6 +106,8 @@
</Compile>
<Compile Include="CodeFixes\FixAllOccurrences\FixSomeCodeAction.cs" />
<Compile Include="AddPackage\InstallPackageDirectlyCodeAction.cs" />
<Compile Include="RemoveUnnecessaryImports\AbstractRemoveUnnecessaryImportsCodeFixProvider.cs" />
<Compile Include="RemoveUnnecessaryImports\IUnnecessaryImportsService.cs" />
<Compile Include="NavigateTo\AbstractNavigateToSearchService.SearchResult.cs" />
<Compile Include="AddMissingReference\AbstractAddMissingReferenceCodeFixProvider.cs" />
<Compile Include="AddMissingReference\AddMissingReferenceCodeAction.cs" />
......@@ -418,7 +420,7 @@
<Compile Include="Diagnostics\Analyzers\DocumentDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\ProjectDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\RemoveUnnecessaryCastDiagnosticAnalyzerBase.cs" />
<Compile Include="Diagnostics\Analyzers\RemoveUnnecessaryImportsDiagnosticAnalyzerBase.cs" />
<Compile Include="RemoveUnnecessaryImports\AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.cs" />
<Compile Include="Diagnostics\Analyzers\SimplifyTypeNamesDiagnosticAnalyzerBase.cs" />
<Compile Include="DocumentationComments\AbstractDocumentationCommentFormattingService.cs" />
<Compile Include="DocumentationComments\IDocumentationCommentFormattingService.cs" />
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
// 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.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Diagnostics.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.RemoveUnnecessaryImports;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.CodeFixes.RemoveUnusedUsings
namespace Microsoft.CodeAnalysis.RemoveUnnecessaryImports
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = PredefinedCodeFixProviderNames.RemoveUnnecessaryImports), Shared]
[ExtensionOrder(After = PredefinedCodeFixProviderNames.AddMissingReference)]
internal class RemoveUnnecessaryUsingsCodeFixProvider : CodeFixProvider
internal abstract class AbstractRemoveUnnecessaryImportsCodeFixProvider : CodeFixProvider
{
public sealed override ImmutableArray<string> FixableDiagnosticIds
{
get { return ImmutableArray.Create(CSharpRemoveUnnecessaryImportsDiagnosticAnalyzer.DiagnosticFixableId); }
}
=> ImmutableArray.Create(AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer.DiagnosticFixableId);
public sealed override FixAllProvider GetFixAllProvider()
{
return WellKnownFixAllProviders.BatchFixer;
}
=> WellKnownFixAllProviders.BatchFixer;
public sealed override Task RegisterCodeFixesAsync(CodeFixContext context)
{
context.RegisterCodeFix(
new MyCodeAction(
CSharpFeaturesResources.Remove_Unnecessary_Usings,
GetTitle(),
c => RemoveUnnecessaryImportsAsync(context.Document, c)),
context.Diagnostics);
return SpecializedTasks.EmptyTask;
}
protected abstract string GetTitle();
private Task<Document> RemoveUnnecessaryImportsAsync(
Document document, CancellationToken cancellationToken)
{
......@@ -53,4 +46,4 @@ private class MyCodeAction : CodeAction.DocumentChangeAction
}
}
}
}
}
\ No newline at end of file
......@@ -5,13 +5,14 @@
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Diagnostics.RemoveUnnecessaryImports
namespace Microsoft.CodeAnalysis.RemoveUnnecessaryImports
{
internal abstract class RemoveUnnecessaryImportsDiagnosticAnalyzerBase :
internal abstract class AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer :
DiagnosticAnalyzer, IBuiltInAnalyzer
{
// NOTE: This is a trigger diagnostic, which doesn't show up in the ruleset editor and hence doesn't need a conventional IDE Diagnostic ID string.
......@@ -48,7 +49,9 @@ private DiagnosticDescriptor GetClassificationIdDescriptor()
return _classificationIdDescriptor;
}
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_fixableIdDescriptor, GetClassificationIdDescriptor());
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics =>
ImmutableArray.Create(s_fixableIdDescriptor, GetClassificationIdDescriptor());
public bool OpenFileOnly(Workspace workspace) => true;
public override void Initialize(AnalysisContext context)
......@@ -61,10 +64,20 @@ private void AnalyzeSemanticModel(SemanticModelAnalysisContext context)
var tree = context.SemanticModel.SyntaxTree;
var cancellationToken = context.CancellationToken;
var root = tree.GetRoot();
var unnecessaryImports = GetUnnecessaryImports(context.SemanticModel, root, cancellationToken);
if (unnecessaryImports != null && unnecessaryImports.Any())
var workspace = ((WorkspaceAnalyzerOptions)context.Options).Workspace;
var service = workspace.Services.GetLanguageServices(context.SemanticModel.Compilation.Language)
.GetService<IUnnecessaryImportsService>();
var unnecessaryImports = service.GetUnnecessaryImports(context.SemanticModel, cancellationToken);
if (unnecessaryImports.Any())
{
// The IUnnecessaryImportsService will return individual import pieces that
// need to be removed. For example, it will return individual import-clauses
// from VB. However, we want to mark the entire import statement if we are
// going to remove all the clause. Defer to our subclass to stitch this up
// for us appropriately.
unnecessaryImports = MergeImports(unnecessaryImports);
Func<SyntaxNode, SyntaxToken> getLastTokenFunc = GetLastTokenDelegateForContiguousSpans();
var contiguousSpans = unnecessaryImports.GetContiguousSpans(getLastTokenFunc);
var diagnostics =
......@@ -78,8 +91,7 @@ private void AnalyzeSemanticModel(SemanticModelAnalysisContext context)
}
}
protected abstract IEnumerable<SyntaxNode> GetUnnecessaryImports(
SemanticModel semanticModel, SyntaxNode root, CancellationToken cancellationToken);
protected abstract ImmutableArray<SyntaxNode> MergeImports(ImmutableArray<SyntaxNode> unnecessaryImports);
protected virtual Func<SyntaxNode, SyntaxToken> GetLastTokenDelegateForContiguousSpans()
{
......
......@@ -11,13 +11,22 @@
namespace Microsoft.CodeAnalysis.RemoveUnnecessaryImports
{
internal abstract class AbstractRemoveUnnecessaryImportsService<T> :
IRemoveUnnecessaryImportsService, IEqualityComparer<T> where T : SyntaxNode
IRemoveUnnecessaryImportsService,
IUnnecessaryImportsService,
IEqualityComparer<T> where T : SyntaxNode
{
public Task<Document> RemoveUnnecessaryImportsAsync(Document document, CancellationToken cancellationToken)
=> RemoveUnnecessaryImportsAsync(document, predicate: null, cancellationToken: cancellationToken);
public abstract Task<Document> RemoveUnnecessaryImportsAsync(Document fromDocument, Func<SyntaxNode, bool> predicate, CancellationToken cancellationToken);
public ImmutableArray<SyntaxNode> GetUnnecessaryImports(
SemanticModel model, CancellationToken cancellationToken)
{
var root = model.SyntaxTree.GetRoot(cancellationToken);
return GetUnnecessaryImports(model, root, predicate: null, cancellationToken: cancellationToken).CastArray<SyntaxNode>();
}
protected abstract ImmutableArray<T> GetUnnecessaryImports(
SemanticModel model, SyntaxNode root,
Func<SyntaxNode, bool> predicate, CancellationToken cancellationToken);
......
// 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.Collections.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.Host;
namespace Microsoft.CodeAnalysis.RemoveUnnecessaryImports
{
internal interface IUnnecessaryImportsService : ILanguageService
{
ImmutableArray<SyntaxNode> GetUnnecessaryImports(SemanticModel semanticModel, CancellationToken cancellationToken);
}
}
\ No newline at end of file
......@@ -119,7 +119,7 @@
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.RemoveUnnecessaryCastFixAllProvider.vb" />
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.Rewriter.vb" />
<Compile Include="CodeFixes\RemoveUnnecessaryCast\RemoveUnnecessaryCastCodeFixProvider.vb" />
<Compile Include="CodeFixes\RemoveUnnecessaryImports\RemoveUnnecessaryImportsCodeFixProvider.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsCodeFixProvider.vb" />
<Compile Include="CodeFixes\SimplifyTypeNames\SimplifyTypeNamesCodeFixProvider.SimplifyTypeNamesFixAllProvider.vb" />
<Compile Include="CodeFixes\SimplifyTypeNames\SimplifyTypeNamesCodeFixProvider.vb" />
<Compile Include="CodeFixes\Spellcheck\VisualBasicSpellCheckCodeFixProvider.vb" />
......@@ -298,7 +298,7 @@
<Compile Include="Diagnostics\Analyzers\VisualBasicNamingStyleDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicUnboundIdentifiersDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicRemoveUnnecessaryCastDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicRemoveUnnecessaryImportsDiagnosticAnalyzer.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\Analyzers\VisualBasicSimplifyTypeNamesDiagnosticAnalyzer.vb" />
<Compile Include="Diagnostics\VisualBasicAnalyzerDriverService.vb" />
<Compile Include="DocumentationComments\DocumentationCommentUtilities.vb" />
......@@ -402,9 +402,8 @@
<Compile Include="Structure\Providers\XmlExpressionStructureProvider.vb" />
<Compile Include="Structure\VisualBasicStructureHelpers.vb" />
<Compile Include="Structure\VisualBasicBlockStructureProvider.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsService.Rewriter.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsService.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsService.Visitor.vb" />
<Compile Include="RemoveUnnecessaryImports\AbstractVisualBasicRemoveUnnecessaryImportsService.Rewriter.vb" />
<Compile Include="RemoveUnnecessaryImports\AbstractVisualBasicRemoveUnnecessaryImportsService.vb" />
<Compile Include="ReplacePropertyWithMethods\VisualBasicReplacePropertyWithMethods.vb" />
<Compile Include="SignatureHelp\AbstractIntrinsicOperatorSignatureHelpProvider.vb" />
<Compile Include="SignatureHelp\AbstractSignatureHelpProvider.vb" />
......@@ -448,6 +447,8 @@
<DependentUpon>VBFeaturesResources.resx</DependentUpon>
</Compile>
<Compile Include="Structure\Providers\WithBlockStructureProvider.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicRemoveUnnecessaryImportsService.vb" />
<Compile Include="RemoveUnnecessaryImports\VisualBasicUnnecessaryImportsService.vb" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="VBFeaturesResources.resx">
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Composition
Imports Microsoft.CodeAnalysis.CodeActions
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryImports
Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.RemoveUnnecessaryImports
<ExportCodeFixProviderAttribute(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.RemoveUnnecessaryImports), [Shared]>
<ExtensionOrder(After:=PredefinedCodeFixProviderNames.AddMissingReference)>
Friend Class RemoveUnnecessaryImportsCodeFixProvider
Inherits CodeFixProvider
Public NotOverridable Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String)
Get
Return ImmutableArray.Create(RemoveUnnecessaryImportsDiagnosticAnalyzerBase.DiagnosticFixableId)
End Get
End Property
Public NotOverridable Overrides Function GetFixAllProvider() As FixAllProvider
Return WellKnownFixAllProviders.BatchFixer
End Function
Public NotOverridable Overrides Async Function RegisterCodeFixesAsync(context As CodeFixContext) As Task
Dim document = context.Document
Dim cancellationToken = context.CancellationToken
Dim service = document.GetLanguageService(Of IRemoveUnnecessaryImportsService)()
Dim newDocument = Await service.RemoveUnnecessaryImportsAsync(document, cancellationToken).ConfigureAwait(False)
If newDocument Is document OrElse newDocument Is Nothing Then
Return
End If
context.RegisterCodeFix(
New MyCodeAction(VBFeaturesResources.Remove_Unnecessary_Imports, newDocument),
context.Diagnostics)
End Function
Private Class MyCodeAction
Inherits CodeAction.DocumentChangeAction
Public Sub New(title As String, newDocument As Document)
MyBase.New(title, Function(c) Task.FromResult(newDocument))
End Sub
End Class
End Class
End Namespace
......@@ -6,7 +6,7 @@ Imports Microsoft.CodeAnalysis.VisualBasic
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
Partial Friend Class VisualBasicRemoveUnnecessaryImportsService
Partial Friend Class AbstractVisualBasicRemoveUnnecessaryImportsService
Private Class Rewriter
Inherits VisualBasicSyntaxRewriter
......@@ -119,4 +119,4 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
End Function
End Class
End Class
End Namespace
End Namespace
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Internal.Log
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
Partial Friend MustInherit Class AbstractVisualBasicRemoveUnnecessaryImportsService
Inherits AbstractRemoveUnnecessaryImportsService(Of ImportsClauseSyntax)
Public Overrides Async Function RemoveUnnecessaryImportsAsync(
document As Document,
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken) As Task(Of Document)
predicate = If(predicate, Functions(Of SyntaxNode).True)
Using Logger.LogBlock(FunctionId.Refactoring_RemoveUnnecessaryImports_VisualBasic, cancellationToken)
Dim unnecessaryImports = Await GetCommonUnnecessaryImportsOfAllContextAsync(
document, predicate, cancellationToken).ConfigureAwait(False)
If unnecessaryImports.Any(Function(import) import.OverlapsHiddenPosition(cancellationToken)) Then
Return document
End If
Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False)
Dim oldRoot = DirectCast(root, CompilationUnitSyntax)
Dim newRoot = New Rewriter(unnecessaryImports, cancellationToken).Visit(oldRoot)
newRoot = newRoot.WithAdditionalAnnotations(Formatter.Annotation)
cancellationToken.ThrowIfCancellationRequested()
Return document.WithSyntaxRoot(newRoot)
End Using
End Function
Protected Overrides Function GetUnnecessaryImports(
model As SemanticModel, root As SyntaxNode,
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken) As ImmutableArray(Of ImportsClauseSyntax)
predicate = If(predicate, Functions(Of SyntaxNode).True)
Dim diagnostics = model.GetDiagnostics(cancellationToken:=cancellationToken)
Dim unnecessaryImports = New HashSet(Of ImportsClauseSyntax)
For Each diagnostic In diagnostics
If diagnostic.Id = "BC50000" Then
Dim node = root.FindNode(diagnostic.Location.SourceSpan)
If node IsNot Nothing AndAlso predicate(node) Then
unnecessaryImports.Add(DirectCast(node, ImportsClauseSyntax))
End If
End If
If diagnostic.Id = "BC50001" Then
Dim node = TryCast(root.FindNode(diagnostic.Location.SourceSpan), ImportsStatementSyntax)
If node IsNot Nothing AndAlso predicate(node) Then
unnecessaryImports.AddRange(node.ImportsClauses)
End If
End If
Next
Dim oldRoot = DirectCast(root, CompilationUnitSyntax)
AddRedundantImports(oldRoot, model, unnecessaryImports, predicate, cancellationToken)
Return unnecessaryImports.ToImmutableArray()
End Function
Private Shared Sub AddRedundantImports(
compilationUnit As CompilationUnitSyntax,
semanticModel As SemanticModel,
unnecessaryImports As HashSet(Of ImportsClauseSyntax),
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken)
' Now that we've visited the tree, add any imports that bound to project level
' imports. We definitely can remove them.
For Each statement In compilationUnit.Imports
For Each clause In statement.ImportsClauses
cancellationToken.ThrowIfCancellationRequested()
Dim simpleImportsClause = TryCast(clause, SimpleImportsClauseSyntax)
If simpleImportsClause IsNot Nothing Then
If simpleImportsClause.Alias Is Nothing Then
AddRedundantMemberImportsClause(simpleImportsClause, semanticModel, unnecessaryImports, predicate, cancellationToken)
Else
AddRedundantAliasImportsClause(simpleImportsClause, semanticModel, unnecessaryImports, predicate, cancellationToken)
End If
End If
Next
Next
End Sub
Private Shared Sub AddRedundantAliasImportsClause(
clause As SimpleImportsClauseSyntax,
semanticModel As SemanticModel,
unnecessaryImports As HashSet(Of ImportsClauseSyntax),
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken)
Dim semanticInfo = semanticModel.GetSymbolInfo(clause.Name, cancellationToken)
Dim namespaceOrType = TryCast(semanticInfo.Symbol, INamespaceOrTypeSymbol)
If namespaceOrType Is Nothing Then
Return
End If
Dim compilation = semanticModel.Compilation
Dim aliasSymbol = compilation.AliasImports.FirstOrDefault(Function(a) a.Name = clause.Alias.Identifier.ValueText)
If aliasSymbol IsNot Nothing AndAlso
aliasSymbol.Target.Equals(semanticInfo.Symbol) AndAlso
predicate(clause) Then
unnecessaryImports.Add(clause)
End If
End Sub
Private Shared Sub AddRedundantMemberImportsClause(
clause As SimpleImportsClauseSyntax,
semanticModel As SemanticModel,
unnecessaryImports As HashSet(Of ImportsClauseSyntax),
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken)
Dim semanticInfo = semanticModel.GetSymbolInfo(clause.Name, cancellationToken)
Dim namespaceOrType = TryCast(semanticInfo.Symbol, INamespaceOrTypeSymbol)
If namespaceOrType Is Nothing Then
Return
End If
Dim compilation = semanticModel.Compilation
If compilation.MemberImports.Contains(namespaceOrType) AndAlso
predicate(clause) Then
unnecessaryImports.Add(clause)
End If
End Sub
End Class
End Namespace
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryImports
Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
<ExportCodeFixProvider(LanguageNames.VisualBasic, Name:=PredefinedCodeFixProviderNames.RemoveUnnecessaryImports), [Shared]>
<ExtensionOrder(After:=PredefinedCodeFixProviderNames.AddMissingReference)>
Friend Class VisualBasicRemoveUnnecessaryImportsCodeFixProvider
Inherits AbstractRemoveUnnecessaryImportsCodeFixProvider
Protected Overrides Function GetTitle() As String
Return VBFeaturesResources.Remove_Unnecessary_Imports
End Function
End Class
End Namespace
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Threading
Imports Microsoft.CodeAnalysis.Diagnostics
Imports Microsoft.CodeAnalysis.Diagnostics.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics.RemoveUnnecessaryImports
Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
<DiagnosticAnalyzer(LanguageNames.VisualBasic)>
Friend NotInheritable Class VisualBasicRemoveUnnecessaryImportsDiagnosticAnalyzer
Inherits RemoveUnnecessaryImportsDiagnosticAnalyzerBase
Inherits AbstractRemoveUnnecessaryImportsDiagnosticAnalyzer
Private Shared ReadOnly s_TitleAndMessageFormat As LocalizableString =
New LocalizableResourceString(NameOf(VBFeaturesResources.Imports_statement_is_unnecessary), VBFeaturesResources.ResourceManager, GetType(VBFeaturesResources.VBFeaturesResources))
......@@ -18,10 +20,25 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Diagnostics.RemoveUnnecessaryImport
Return s_TitleAndMessageFormat
End Function
Protected Overrides Function GetUnnecessaryImports(
semanticModel As SemanticModel, root As SyntaxNode, cancellationToken As CancellationToken) As IEnumerable(Of SyntaxNode)
Return VisualBasicRemoveUnnecessaryImportsService.GetUnnecessaryImportsShared(
semanticModel, root, predicate:=Nothing, cancellationToken:=cancellationToken)
''' Takes the import clauses we want to remove and returns them *or* their
''' containing ImportsStatements *if* we wanted to remove all the clauses of
''' that ImportStatement.
Protected Overrides Function MergeImports(unnecessaryImports As ImmutableArray(Of SyntaxNode)) As ImmutableArray(Of SyntaxNode)
Dim result = ArrayBuilder(Of SyntaxNode).GetInstance()
Dim importsClauses = unnecessaryImports.CastArray(Of ImportsClauseSyntax)
For Each clause In importsClauses
If Not result.Contains(clause.Parent) Then
Dim statement = DirectCast(clause.Parent, ImportsStatementSyntax)
If statement.ImportsClauses.All(AddressOf importsClauses.Contains) Then
result.Add(statement)
Else
result.Add(clause)
End If
End If
Next
Return result.ToImmutableAndFree()
End Function
Protected Overrides Function GetFixableDiagnosticSpans(
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Collections.Immutable
Imports System.Composition
Imports System.Threading
Imports Microsoft.CodeAnalysis
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.Internal.Log
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryImports
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
<ExportLanguageService(GetType(IRemoveUnnecessaryImportsService), LanguageNames.VisualBasic), [Shared]>
Partial Friend Class VisualBasicRemoveUnnecessaryImportsService
Inherits AbstractRemoveUnnecessaryImportsService(Of ImportsClauseSyntax)
Friend Class VisualBasicRemoveUnnecessaryImportsService
Inherits AbstractVisualBasicRemoveUnnecessaryImportsService
Public Shared Function GetUnnecessaryImportsShared(
model As SemanticModel,
root As SyntaxNode,
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken) As ImmutableArray(Of SyntaxNode)
predicate = If(predicate, Functions(Of SyntaxNode).True)
Dim unnecessaryImports = GetIndividualUnnecessaryImportsShared(model, root, predicate, cancellationToken)
If Not unnecessaryImports.Any() Then
Return ImmutableArray(Of SyntaxNode).Empty
End If
Return unnecessaryImports.Select(
Function(i) As SyntaxNode
Dim statement = DirectCast(i.Parent, ImportsStatementSyntax)
If statement.ImportsClauses.All(AddressOf unnecessaryImports.Contains) Then
Return statement
Else
Return i
End If
End Function).ToImmutableArray()
End Function
Public Overrides Async Function RemoveUnnecessaryImportsAsync(
document As Document,
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken) As Task(Of Document)
predicate = If(predicate, Functions(Of SyntaxNode).True)
Using Logger.LogBlock(FunctionId.Refactoring_RemoveUnnecessaryImports_VisualBasic, cancellationToken)
Dim unnecessaryImports = Await GetCommonUnnecessaryImportsOfAllContextAsync(
document, predicate, cancellationToken).ConfigureAwait(False)
If unnecessaryImports.Any(Function(import) import.OverlapsHiddenPosition(cancellationToken)) Then
Return document
End If
Dim root = Await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(False)
Dim oldRoot = DirectCast(root, CompilationUnitSyntax)
Dim newRoot = New Rewriter(unnecessaryImports, cancellationToken).Visit(oldRoot)
newRoot = newRoot.WithAdditionalAnnotations(Formatter.Annotation)
cancellationToken.ThrowIfCancellationRequested()
Return document.WithSyntaxRoot(newRoot)
End Using
End Function
Protected Overrides Function GetUnnecessaryImports(
model As SemanticModel, root As SyntaxNode,
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken) As ImmutableArray(Of ImportsClauseSyntax)
Return GetIndividualUnnecessaryImportsShared(model, root, predicate, cancellationToken)
End Function
Private Shared Function GetIndividualUnnecessaryImportsShared(
semanticModel As SemanticModel, root As SyntaxNode,
predicate As Func(Of SyntaxNode, Boolean),
CancellationToken As CancellationToken) As ImmutableArray(Of ImportsClauseSyntax)
Dim diagnostics = semanticModel.GetDiagnostics(cancellationToken:=CancellationToken)
Dim unnecessaryImports = New HashSet(Of ImportsClauseSyntax)
For Each diagnostic In diagnostics
If diagnostic.Id = "BC50000" Then
Dim node = root.FindNode(diagnostic.Location.SourceSpan)
If node IsNot Nothing AndAlso predicate(node) Then
unnecessaryImports.Add(DirectCast(node, ImportsClauseSyntax))
End If
End If
If diagnostic.Id = "BC50001" Then
Dim node = TryCast(root.FindNode(diagnostic.Location.SourceSpan), ImportsStatementSyntax)
If node IsNot Nothing AndAlso predicate(node) Then
unnecessaryImports.AddRange(node.ImportsClauses)
End If
End If
Next
Dim oldRoot = DirectCast(root, CompilationUnitSyntax)
AddRedundantImports(oldRoot, semanticModel, unnecessaryImports, predicate, CancellationToken)
Return unnecessaryImports.ToImmutableArray()
End Function
Private Shared Sub AddRedundantImports(
compilationUnit As CompilationUnitSyntax,
semanticModel As SemanticModel,
unnecessaryImports As HashSet(Of ImportsClauseSyntax),
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken)
' Now that we've visited the tree, add any imports that bound to project level
' imports. We definitely can remove them.
For Each statement In compilationUnit.Imports
For Each clause In statement.ImportsClauses
cancellationToken.ThrowIfCancellationRequested()
Dim simpleImportsClause = TryCast(clause, SimpleImportsClauseSyntax)
If simpleImportsClause IsNot Nothing Then
If simpleImportsClause.Alias Is Nothing Then
AddRedundantMemberImportsClause(simpleImportsClause, semanticModel, unnecessaryImports, predicate, cancellationToken)
Else
AddRedundantAliasImportsClause(simpleImportsClause, semanticModel, unnecessaryImports, predicate, cancellationToken)
End If
End If
Next
Next
End Sub
Private Shared Sub AddRedundantAliasImportsClause(
clause As SimpleImportsClauseSyntax,
semanticModel As SemanticModel,
unnecessaryImports As HashSet(Of ImportsClauseSyntax),
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken)
Dim semanticInfo = semanticModel.GetSymbolInfo(clause.Name, cancellationToken)
Dim namespaceOrType = TryCast(semanticInfo.Symbol, INamespaceOrTypeSymbol)
If namespaceOrType Is Nothing Then
Return
End If
Dim compilation = semanticModel.Compilation
Dim aliasSymbol = compilation.AliasImports.FirstOrDefault(Function(a) a.Name = clause.Alias.Identifier.ValueText)
If aliasSymbol IsNot Nothing AndAlso
aliasSymbol.Target.Equals(semanticInfo.Symbol) AndAlso
predicate(clause) Then
unnecessaryImports.Add(clause)
End If
End Sub
Private Shared Sub AddRedundantMemberImportsClause(
clause As SimpleImportsClauseSyntax,
semanticModel As SemanticModel,
unnecessaryImports As HashSet(Of ImportsClauseSyntax),
predicate As Func(Of SyntaxNode, Boolean),
cancellationToken As CancellationToken)
Dim semanticInfo = semanticModel.GetSymbolInfo(clause.Name, cancellationToken)
Dim namespaceOrType = TryCast(semanticInfo.Symbol, INamespaceOrTypeSymbol)
If namespaceOrType Is Nothing Then
Return
End If
Dim compilation = semanticModel.Compilation
If compilation.MemberImports.Contains(namespaceOrType) AndAlso
predicate(clause) Then
unnecessaryImports.Add(clause)
End If
End Sub
End Class
End Namespace
\ No newline at end of file
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports System.Composition
Imports Microsoft.CodeAnalysis.Host.Mef
Imports Microsoft.CodeAnalysis.RemoveUnnecessaryImports
Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnnecessaryImports
<ExportLanguageService(GetType(IUnnecessaryImportsService), LanguageNames.VisualBasic), [Shared]>
Friend Class VisualBasicUnnecessaryImportsService
Inherits AbstractVisualBasicRemoveUnnecessaryImportsService
End Class
End Namespace
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册