From a04c693a8013aa6564bd02b8afe82e857d9dc51f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 1 Jul 2021 15:09:19 -0700 Subject: [PATCH] Support EditorBrowsable in Fully-Qualify --- .../FullyQualify/FullyQualifyTests.cs | 151 ++++++++++++++++++ .../AbstractFullyQualifyCodeFixProvider.cs | 15 +- 2 files changed, 163 insertions(+), 3 deletions(-) diff --git a/src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyTests.cs b/src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyTests.cs index 576268ba8a189..0972bcbfd8125 100644 --- a/src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyTests.cs +++ b/src/EditorFeatures/CSharpTest/FullyQualify/FullyQualifyTests.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.CSharp.CodeFixes.FullyQualify; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; @@ -1496,5 +1497,155 @@ await TestInRegularAndScriptAsync( @"using M = [|Math|]", @"using M = System.Math"); } + + [Fact] + [WorkItem(54544, "https://github.com/dotnet/roslyn/issues/54544")] + public async Task TestAddUsingsEditorBrowsableNeverSameProject() + { + const string InitialWorkspace = @" + + + +using System.ComponentModel; +namespace ProjectLib +{ + [EditorBrowsable(EditorBrowsableState.Never)] + public class Project + { + } +} + + +class Program +{ + static void Main(string[] args) + { + Project p = new [|Project()|]; + } +} + + +"; + + const string ExpectedDocumentText = @" +class Program +{ + static void Main(string[] args) + { + Project p = new [|ProjectLib.Project()|]; + } +} +"; + + await TestInRegularAndScript1Async(InitialWorkspace, ExpectedDocumentText); + } + + [Fact] + [WorkItem(54544, "https://github.com/dotnet/roslyn/issues/54544")] + public async Task TestAddUsingsEditorBrowsableNeverDifferentProject() + { + const string InitialWorkspace = @" + + + +imports System.ComponentModel +namespace ProjectLib + <EditorBrowsable(EditorBrowsableState.Never)> + public class Project + end class +end namespace + + + + lib + +class Program +{ + static void Main(string[] args) + { + [|Project|] p = new Project(); + } +} + + +"; + await TestMissingAsync(InitialWorkspace); + } + + [Fact] + [WorkItem(54544, "https://github.com/dotnet/roslyn/issues/54544")] + public async Task TestAddUsingsEditorBrowsableAdvancedDifferentProjectOptionOn() + { + const string InitialWorkspace = @" + + + +imports System.ComponentModel +namespace ProjectLib + <EditorBrowsable(EditorBrowsableState.Advanced)> + public class Project + end class +end namespace + + + + lib + +class Program +{ + static void Main(string[] args) + { + [|Project|] p = new Project(); + } +} + + +"; + + const string ExpectedDocumentText = @" +class Program +{ + static void Main(string[] args) + { + ProjectLib.Project p = new Project(); + } +} +"; + await TestInRegularAndScript1Async(InitialWorkspace, ExpectedDocumentText); + } + + [Fact] + [WorkItem(54544, "https://github.com/dotnet/roslyn/issues/54544")] + public async Task TestAddUsingsEditorBrowsableAdvancedDifferentProjectOptionOff() + { + const string InitialWorkspace = @" + + + +imports System.ComponentModel +namespace ProjectLib + <EditorBrowsable(EditorBrowsableState.Advanced)> + public class Project + end class +end namespace + + + + lib + +class Program +{ + static void Main(string[] args) + { + [|Project|] p = new Project(); + } +} + + +"; + + await TestMissingAsync(InitialWorkspace, new TestParameters( + options: Option(CompletionOptions.HideAdvancedMembers, true))); + } } } diff --git a/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs b/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs index 6bf9986323c93..57b067df08fb8 100644 --- a/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs +++ b/src/Features/Core/Portable/FullyQualify/AbstractFullyQualifyCodeFixProvider.cs @@ -9,11 +9,14 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Completion; using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.Internal.Log; using Microsoft.CodeAnalysis.LanguageServices; using Microsoft.CodeAnalysis.Shared.Extensions; +using Microsoft.CodeAnalysis.Shared.Utilities; using Roslyn.Utilities; +using static Microsoft.CodeAnalysis.Shared.Utilities.EditorBrowsableHelpers; namespace Microsoft.CodeAnalysis.CodeFixes.FullyQualify { @@ -62,7 +65,7 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context) var semanticModel = await document.GetRequiredSemanticModelAsync(cancellationToken).ConfigureAwait(false); - var matchingTypes = await GetMatchingTypesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false); + var matchingTypes = await GetMatchingTypesAsync(document, semanticModel, node, cancellationToken).ConfigureAwait(false); var matchingNamespaces = await GetMatchingNamespacesAsync(project, semanticModel, node, cancellationToken).ConfigureAwait(false); if (matchingTypes.IsEmpty && matchingNamespaces.IsEmpty) @@ -144,10 +147,11 @@ private async Task ProcessNodeAsync(Document document, SyntaxNode node } private async Task> GetMatchingTypesAsync( - Project project, SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken) + Document document, SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken) { cancellationToken.ThrowIfCancellationRequested(); + var project = document.Project; var syntaxFacts = project.LanguageServices.GetRequiredService(); syntaxFacts.GetNameAndArityOfSimpleName(node, out var name, out var arity); @@ -167,9 +171,14 @@ private async Task> GetMatchingTypesAsync( symbols = symbols.Concat(attributeSymbols); } + var options = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false); + var hideAdvancedMembers = options.GetOption(CompletionOptions.HideAdvancedMembers); + var editorBrowserInfo = new EditorBrowsableInfo(semanticModel.Compilation); + var validSymbols = symbols .OfType() - .Where(s => IsValidNamedTypeSearchResult(semanticModel, arity, inAttributeContext, looksGeneric, s)) + .Where(s => IsValidNamedTypeSearchResult(semanticModel, arity, inAttributeContext, looksGeneric, s) && + s.IsEditorBrowsable(hideAdvancedMembers, semanticModel.Compilation, editorBrowserInfo)) .ToImmutableArray(); // Check what the current node binds to. If it binds to any symbols, but with