提交 1dd5d8c1 编写于 作者: C Charles Stoner

Avoid re-calculating base types

Conflicts:
	src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb
上级 4e74318b
......@@ -5871,5 +5871,131 @@ End Module
VerifyNoItemsExist(text)
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub InstanceMembersFromBaseOuterType()
Dim text =
<code><![CDATA[
MustInherit Class Test
Private _field As Integer
NotInheritable Class InnerTest
Inherits Test
Sub SomeTest()
Dim x = $$
End Sub
End Class
End Class
]]></code>.Value
VerifyItemExists(text, "_field")
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub InstanceMembersFromBaseOuterType2()
Dim text =
<code><![CDATA[
Class C(Of T)
Sub M()
End Sub
Class N
Inherits C(Of Integer)
Sub Test()
$$ ' M recommended and accessible
End Sub
Class NN
Sub Test2()
' M inaccessible and not recommended
End Sub
End Class
End Class
End Class
]]></code>.Value
VerifyItemExists(text, "M")
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub InstanceMembersFromBaseOuterType3()
Dim text =
<code><![CDATA[
Class C(Of T)
Sub M()
End Sub
Class N
Inherits C(Of Integer)
Sub Test()
' M recommended and accessible
End Sub
Class NN
Sub Test2()
$$ ' M inaccessible and not recommended
End Sub
End Class
End Class
End Class
]]></code>.Value
VerifyItemIsAbsent(text, "M")
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub InstanceMembersFromBaseOuterType4()
Dim text =
<code><![CDATA[
Class C(Of T)
Sub M()
End Sub
Class N
Inherits C(Of Integer)
Sub Test()
M() ' M recommended and accessible
End Sub
Class NN
Inherits N
Sub Test2()
$$ ' M inaccessible and not recommended
End Sub
End Class
End Class
End Class
]]></code>.Value
VerifyItemExists(text, "M")
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub InstanceMembersFromBaseOuterType5()
Dim text =
<code><![CDATA[
Class D
Public Sub Q()
End Sub
End Class
Class C(Of T)
Inherits D
Class N
Sub Test()
$$
End Sub
End Class
End Class
]]></code>.Value
VerifyItemIsAbsent(text, "Q")
End Sub
<Fact, Trait(Traits.Feature, Traits.Features.Completion)>
Public Sub InstanceMembersFromBaseOuterType6()
Dim text =
<code><![CDATA[
Class Base(Of T)
Public X As Integer
End Class
Class Derived
Inherits C(Of Integer)
Class Nested
Sub Test()
$$
End Sub
End Class
End Class
]]></code>.Value
VerifyItemIsAbsent(text, "X")
End Sub
End Class
End Namespace
\ No newline at end of file
......@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Recommendations
{
......@@ -21,13 +22,26 @@ internal abstract class AbstractRecommendationService : IRecommendationService
var result = GetRecommendedSymbolsAtPositionWorker(workspace, semanticModel, position, options, cancellationToken);
var symbols = result.Item1;
var context = result.Item2;
var context = new ShouldIncludeSymbolContext(result.Item2, cancellationToken);
symbols = symbols.Where(s => ShouldIncludeSymbol(s, context, cancellationToken));
symbols = symbols.Where(context.ShouldIncludeSymbol);
return symbols;
}
private bool ShouldIncludeSymbol(ISymbol symbol, AbstractSyntaxContext context, CancellationToken cancellationToken)
private sealed class ShouldIncludeSymbolContext
{
private readonly AbstractSyntaxContext _context;
private readonly CancellationToken _cancellationToken;
private IEnumerable<INamedTypeSymbol> _lazyOuterTypesAndBases;
private IEnumerable<INamedTypeSymbol> _lazyEnclosingTypeBases;
internal ShouldIncludeSymbolContext(AbstractSyntaxContext context, CancellationToken cancellationToken)
{
_context = context;
_cancellationToken = cancellationToken;
}
internal bool ShouldIncludeSymbol(ISymbol symbol)
{
var isMember = false;
switch (symbol.Kind)
......@@ -42,13 +56,13 @@ private bool ShouldIncludeSymbol(ISymbol symbol, AbstractSyntaxContext context,
break;
case SymbolKind.Method:
var methodSymbol = (IMethodSymbol)symbol;
if (methodSymbol.MethodKind == MethodKind.EventAdd ||
methodSymbol.MethodKind == MethodKind.EventRemove ||
methodSymbol.MethodKind == MethodKind.EventRaise ||
methodSymbol.MethodKind == MethodKind.PropertyGet ||
methodSymbol.MethodKind == MethodKind.PropertySet)
switch (((IMethodSymbol)symbol).MethodKind)
{
case MethodKind.EventAdd:
case MethodKind.EventRemove:
case MethodKind.EventRaise:
case MethodKind.PropertyGet:
case MethodKind.PropertySet:
return false;
}
......@@ -65,38 +79,60 @@ private bool ShouldIncludeSymbol(ISymbol symbol, AbstractSyntaxContext context,
return ((ITypeParameterSymbol)symbol).TypeParameterKind != TypeParameterKind.Cref;
}
if (context.IsAttributeNameContext)
if (_context.IsAttributeNameContext)
{
var enclosingSymbol = context.SemanticModel.GetEnclosingNamedType(context.LeftToken.SpanStart, cancellationToken);
return symbol.IsOrContainsAccessibleAttribute(enclosingSymbol, context.SemanticModel.Compilation.Assembly);
var enclosingSymbol = _context.SemanticModel.GetEnclosingNamedType(_context.LeftToken.SpanStart, _cancellationToken);
return symbol.IsOrContainsAccessibleAttribute(enclosingSymbol, _context.SemanticModel.Compilation.Assembly);
}
if (context.IsEnumTypeMemberAccessContext)
if (_context.IsEnumTypeMemberAccessContext)
{
return symbol.Kind == SymbolKind.Field;
}
// In an expression or statement context, we don't want to display instance members declared in outer containing types.
if ((context.IsStatementContext || context.IsAnyExpressionContext) &&
if ((_context.IsStatementContext || _context.IsAnyExpressionContext) &&
!symbol.IsStatic &&
isMember)
{
var outerTypesAndBases = context.GetOuterTypes(cancellationToken).SelectMany(o => o.GetBaseTypesAndThis()).Select(t => t.OriginalDefinition);
var containingTypeOriginalDefinition = symbol.ContainingType.OriginalDefinition;
if (outerTypesAndBases.Contains(containingTypeOriginalDefinition))
if (this.GetOuterTypesAndBases().Contains(containingTypeOriginalDefinition))
{
var enclosingType = context.SemanticModel.GetEnclosingNamedType(context.LeftToken.SpanStart, cancellationToken);
return enclosingType != null && enclosingType.GetBaseTypes().Select(b => b.OriginalDefinition).Contains(containingTypeOriginalDefinition);
return this.GetEnclosingTypeBases().Contains(containingTypeOriginalDefinition);
}
}
var namespaceSymbol = symbol as INamespaceSymbol;
if (namespaceSymbol != null)
{
return namespaceSymbol.ContainsAccessibleTypesOrNamespaces(context.SemanticModel.Compilation.Assembly);
return namespaceSymbol.ContainsAccessibleTypesOrNamespaces(_context.SemanticModel.Compilation.Assembly);
}
return true;
}
private IEnumerable<INamedTypeSymbol> GetOuterTypesAndBases()
{
if (_lazyOuterTypesAndBases == null)
{
_lazyOuterTypesAndBases = _context.GetOuterTypes(_cancellationToken).SelectMany(o => o.GetBaseTypesAndThis()).Select(t => t.OriginalDefinition);
}
return _lazyOuterTypesAndBases;
}
private IEnumerable<INamedTypeSymbol> GetEnclosingTypeBases()
{
if (_lazyEnclosingTypeBases == null)
{
var enclosingType = _context.SemanticModel.GetEnclosingNamedType(_context.LeftToken.SpanStart, _cancellationToken);
_lazyEnclosingTypeBases = (enclosingType == null) ?
SpecializedCollections.EmptyEnumerable<INamedTypeSymbol>() :
enclosingType.GetBaseTypes().Select(b => b.OriginalDefinition);
}
return _lazyEnclosingTypeBases;
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册