提交 565cdc98 编写于 作者: J Julien 提交者: GitHub

Filter fields in completion on a tuple (#14028)

上级 36cbe2cb
......@@ -8854,5 +8854,41 @@ void foo()
}";
await VerifyItemExistsAsync(markup, "i", matchPriority: SymbolMatchPriority.PreferLocalOrParameterOrRangeVariable);
}
[Fact, Trait(Traits.Feature, Traits.Features.Completion)]
public async Task TupleElements()
{
var markup = @"
class C
{
void foo()
{
var t = (Alice: 1, Item2: 2, ITEM3: 3, 4, 5, 6, 7, 8, Bob: 9);
t.$$
}
}" + TestResources.NetFX.ValueTuple.tuplelib_cs;
await VerifyItemExistsAsync(markup, "Alice");
await VerifyItemExistsAsync(markup, "Bob");
await VerifyItemExistsAsync(markup, "CompareTo");
await VerifyItemExistsAsync(markup, "Equals");
await VerifyItemExistsAsync(markup, "GetHashCode");
await VerifyItemExistsAsync(markup, "GetType");
await VerifyItemExistsAsync(markup, "Item2");
await VerifyItemExistsAsync(markup, "ITEM3");
for (int i = 4; i <= 8; i++)
{
await VerifyItemExistsAsync(markup, "Item" + i);
}
await VerifyItemExistsAsync(markup, "ToString");
await VerifyItemIsAbsentAsync(markup, "Item1");
await VerifyItemIsAbsentAsync(markup, "Item9");
await VerifyItemIsAbsentAsync(markup, "Rest");
// TODO fix once we have a good public API for tuple elements
// See https://github.com/dotnet/roslyn/issues/13229
await VerifyItemExistsAsync(markup, "Item3");
}
}
}
\ No newline at end of file
......@@ -7526,5 +7526,62 @@ End Module
Await VerifyItemExistsAsync(text, "A")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Async Function TupleElements() As Task
Dim text =
<code><![CDATA[
Module Module1
Sub Main()
Dim t = (Alice:=1, Item2:=2, ITEM3:=3, 4, 5, 6, 7, 8, Bob:=9)
t.$$
End Sub
End Module
Namespace System
Public Structure ValueTuple(Of T1, T2)
Public Sub New(item1 As T1, item2 As T2)
End Sub
End Structure
Public Structure ValueTuple(Of T1, T2, T3, T4, T5, T6, T7, TRest)
Public Dim Rest As TRest
Public Sub New(item1 As T1, item2 As T2, item3 As T3, item4 As T4, item5 As T5, item6 As T6, item7 As T7, rest As TRest)
End Sub
Public Overrides Function ToString() As String
Return ""
End Function
Public Overrides Function GetHashCode As Integer
Return 0
End Function
Public Overrides Function CompareTo(value As Object) As Integer
Return 0
End Function
Public Overrides Function GetType As Type
Return Nothing
End Function
End Structure
End Namespace
]]></code>.Value
Await VerifyItemExistsAsync(text, "Alice")
Await VerifyItemExistsAsync(text, "Bob")
Await VerifyItemExistsAsync(text, "CompareTo")
Await VerifyItemExistsAsync(text, "Equals")
Await VerifyItemExistsAsync(text, "GetHashCode")
Await VerifyItemExistsAsync(text, "GetType")
For index = 2 To 8
Await VerifyItemExistsAsync(text, "Item" + index.ToString())
Next
Await VerifyItemExistsAsync(text, "ToString")
Await VerifyItemIsAbsentAsync(text, "Item1")
Await VerifyItemIsAbsentAsync(text, "Item9")
Await VerifyItemIsAbsentAsync(text, "Rest")
End Function
End Class
End Namespace
......@@ -534,7 +534,8 @@ private static IEnumerable<ISymbol> GetSymbolsForNamespaceDeclarationNameContext
? context.SemanticModel.LookupBaseMembers(position)
: excludeInstance
? context.SemanticModel.LookupStaticMembers(position, container)
: context.SemanticModel.LookupSymbols(position, container, includeReducedExtensionMethods: true);
: SuppressDefaultTupleElements(container,
context.SemanticModel.LookupSymbols(position, container, includeReducedExtensionMethods: true));
// If we're showing instance members, don't include nested types
return excludeStatic
......
......@@ -71,6 +71,45 @@ protected static bool IsNonIntersectingNamespace(ISymbol recommendationSymbol, S
declarationSyntax.Span.IntersectsWith(candidateLocation.SourceSpan)));
}
/// <summary>
/// If container is a tuple type, any of its tuple element which has a friendly name will cause
/// the suppression of the corresponding default name (ItemN).
/// In that case, Rest is also removed.
/// </summary>
protected static IEnumerable<ISymbol> SuppressDefaultTupleElements(INamespaceOrTypeSymbol container,
IEnumerable<ISymbol> symbols)
{
if (!container.IsType)
{
return symbols;
}
var type = (ITypeSymbol)container;
if (!type.IsTupleType)
{
return symbols;
}
var tuple = (INamedTypeSymbol)type;
var elementNames = tuple.TupleElementNames;
if (elementNames.IsDefault)
{
return symbols;
}
// TODO This should be revised once we have a good public API for tuple fields
// See https://github.com/dotnet/roslyn/issues/13229
var fieldsToRemove = elementNames.Select((n, i) => IsFriendlyName(i, n) ? "Item" + (i + 1) : null)
.Where(n => n != null).Concat("Rest").ToSet();
return symbols.Where(s => s.Kind != SymbolKind.Field || elementNames.Contains(s.Name) || !fieldsToRemove.Contains(s.Name));
}
private static bool IsFriendlyName(int i, string elementName)
{
return elementName != null && string.Compare(elementName, "Item" + (i + 1), StringComparison.OrdinalIgnoreCase) != 0;
}
private sealed class ShouldIncludeSymbolContext
{
private readonly SyntaxContext _context;
......
......@@ -380,11 +380,14 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Recommendations
Return symbolInfo.CandidateSymbols.Any() AndAlso symbolInfo.CandidateSymbols.All(Function(s) s.IsNamespace())
End Function
Private Function LookupSymbolsInContainer(container As INamespaceOrTypeSymbol, semanticModel As SemanticModel, position As Integer, excludeInstance As Boolean) As ImmutableArray(Of ISymbol)
Return If(
excludeInstance,
semanticModel.LookupStaticMembers(position, container),
semanticModel.LookupSymbols(position, container, includeReducedExtensionMethods:=True))
Private Function LookupSymbolsInContainer(container As INamespaceOrTypeSymbol, semanticModel As SemanticModel, position As Integer, excludeInstance As Boolean) As IEnumerable(Of ISymbol)
If excludeInstance Then
Return semanticModel.LookupStaticMembers(position, container)
Else
Return SuppressDefaultTupleElements(
container,
semanticModel.LookupSymbols(position, container, includeReducedExtensionMethods:=True))
End If
End Function
''' <summary>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册