Skip to content

Commit

Permalink
Merge pull request #47590 from genlu/EditorBrowsable
Browse files Browse the repository at this point in the history
Check EditorBrowsable attribute for unimported ext-methods completion
  • Loading branch information
genlu authored Sep 11, 2020
2 parents 0dda365 + 604006f commit 3a976eb
Show file tree
Hide file tree
Showing 2 changed files with 169 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Roslyn.Utilities;
using Xunit;

namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Completion.CompletionProviders
Expand All @@ -30,11 +31,14 @@ public ExtensionMethodImportCompletionProviderTests(CSharpTestWorkspaceFixture w

private bool IsExpandedCompletion { get; set; } = true;

private bool HideAdvancedMembers { get; set; } = false;

protected override OptionSet WithChangedOptions(OptionSet options)
{
return options
.WithChangedOption(CompletionOptions.ShowItemsFromUnimportedNamespaces, LanguageNames.CSharp, ShowImportCompletionItemsOptionValue)
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion);
.WithChangedOption(CompletionServiceOptions.IsExpandedCompletion, IsExpandedCompletion)
.WithChangedOption(CompletionOptions.HideAdvancedMembers, LanguageNames.CSharp, HideAdvancedMembers);
}

protected override TestComposition GetComposition()
Expand Down Expand Up @@ -1723,6 +1727,166 @@ await VerifyImportItemExistsAsync(
expectedDescriptionOrNull: $"({CSharpFeaturesResources.extension}) bool int.ExtentionMethod<T>(T a) (+{NonBreakingSpaceString}2{NonBreakingSpaceString}{FeaturesResources.generic_overloads})");
}

[InlineData(ReferenceType.Project)]
[InlineData(ReferenceType.Metadata)]
[Theory, Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(47551, "https://github.com/dotnet/roslyn/issues/47551")]
public async Task TestBrowsableAlways(ReferenceType refType)
{
var srcDoc = @"
class Program
{
void M()
{
new Goo().$$
}
}";

var refDoc = @"
public class Goo
{
}
namespace Foo
{
public static class GooExtensions
{
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Always)]
public static void Bar(this Goo goo, int x)
{
}
}
}";

var markup = refType switch
{
ReferenceType.Project => CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp),
ReferenceType.Metadata => CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp),
_ => null,
};

await VerifyImportItemExistsAsync(
markup,
"Bar",
glyph: (int)Glyph.ExtensionMethodPublic,
inlineDescription: "Foo");
}

[InlineData(ReferenceType.Project)]
[InlineData(ReferenceType.Metadata)]
[Theory, Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(47551, "https://github.com/dotnet/roslyn/issues/47551")]
public async Task TestBrowsableNever(ReferenceType refType)
{
var srcDoc = @"
class Program
{
void M()
{
new Goo().$$
}
}";

var refDoc = @"
public class Goo
{
}
namespace Foo
{
public static class GooExtensions
{
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]
public static void Bar(this Goo goo, int x)
{
}
}
}";

var (markup, shouldContainItem) = refType switch
{
ReferenceType.Project => (CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), true),
ReferenceType.Metadata => (CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), false),
_ => throw ExceptionUtilities.Unreachable,
};

if (shouldContainItem)
{
await VerifyImportItemExistsAsync(
markup,
"Bar",
glyph: (int)Glyph.ExtensionMethodPublic,
inlineDescription: "Foo");
}
else
{
await VerifyImportItemIsAbsentAsync(
markup,
"Bar",
inlineDescription: "Foo");
}
}

[InlineData(ReferenceType.Project, true)]
[InlineData(ReferenceType.Project, false)]
[InlineData(ReferenceType.Metadata, true)]
[InlineData(ReferenceType.Metadata, false)]
[Theory, Trait(Traits.Feature, Traits.Features.Completion)]
[WorkItem(47551, "https://github.com/dotnet/roslyn/issues/47551")]
public async Task TestBrowsableAdvanced(ReferenceType refType, bool hideAdvanced)
{
HideAdvancedMembers = hideAdvanced;

var srcDoc = @"
class Program
{
void M()
{
new Goo().$$
}
}";

var refDoc = @"
public class Goo
{
}
namespace Foo
{
public static class GooExtensions
{
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
public static void Bar(this Goo goo, int x)
{
}
}
}";

var (markup, shouldContainItem) = (refType, hideAdvanced) switch
{
(ReferenceType.Project, _) => (CreateMarkupForProjectWithProjectReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), true),
(ReferenceType.Metadata, true) => (CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), false),
(ReferenceType.Metadata, false) => (CreateMarkupForProjectWithMetadataReference(srcDoc, refDoc, LanguageNames.CSharp, LanguageNames.CSharp), true),
_ => throw ExceptionUtilities.Unreachable,
};

if (shouldContainItem)
{
await VerifyImportItemExistsAsync(
markup,
"Bar",
glyph: (int)Glyph.ExtensionMethodPublic,
inlineDescription: "Foo");
}
else
{
await VerifyImportItemIsAbsentAsync(
markup,
"Bar",
inlineDescription: "Foo");
}
}

private Task VerifyImportItemExistsAsync(string markup, string expectedItem, int glyph, string inlineDescription, string displayTextSuffix = null, string expectedDescriptionOrNull = null)
=> VerifyItemExistsAsync(markup, expectedItem, displayTextSuffix: displayTextSuffix, glyph: glyph, inlineDescription: inlineDescription, expectedDescriptionOrNull: expectedDescriptionOrNull);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,10 @@ public Task PopulateIndicesAsync(CancellationToken cancellationToken)
symbols.AddRange(result);
}

return (symbols.ToImmutable(), isPartialResult);
var browsableSymbols = symbols.ToImmutable()
.FilterToVisibleAndBrowsableSymbols(_originatingDocument.ShouldHideAdvancedMembers(), _originatingSemanticModel.Compilation);

return (browsableSymbols, isPartialResult);
}

// Returns all referenced projects and originating project itself.
Expand Down

0 comments on commit 3a976eb

Please sign in to comment.