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

Avoid re-calculating base types

Conflicts:
	src/EditorFeatures/VisualBasicTest/Completion/CompletionProviders/SymbolCompletionProviderTests.vb
上级 4e74318b
...@@ -5871,5 +5871,131 @@ End Module ...@@ -5871,5 +5871,131 @@ End Module
VerifyNoItemsExist(text) VerifyNoItemsExist(text)
End Sub 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 Class
End Namespace End Namespace
\ No newline at end of file
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery; using Microsoft.CodeAnalysis.Shared.Extensions.ContextQuery;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.Recommendations namespace Microsoft.CodeAnalysis.Recommendations
{ {
...@@ -21,82 +22,117 @@ internal abstract class AbstractRecommendationService : IRecommendationService ...@@ -21,82 +22,117 @@ internal abstract class AbstractRecommendationService : IRecommendationService
var result = GetRecommendedSymbolsAtPositionWorker(workspace, semanticModel, position, options, cancellationToken); var result = GetRecommendedSymbolsAtPositionWorker(workspace, semanticModel, position, options, cancellationToken);
var symbols = result.Item1; 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; return symbols;
} }
private bool ShouldIncludeSymbol(ISymbol symbol, AbstractSyntaxContext context, CancellationToken cancellationToken) private sealed class ShouldIncludeSymbolContext
{ {
var isMember = false; private readonly AbstractSyntaxContext _context;
switch (symbol.Kind) private readonly CancellationToken _cancellationToken;
private IEnumerable<INamedTypeSymbol> _lazyOuterTypesAndBases;
private IEnumerable<INamedTypeSymbol> _lazyEnclosingTypeBases;
internal ShouldIncludeSymbolContext(AbstractSyntaxContext context, CancellationToken cancellationToken)
{ {
case SymbolKind.NamedType: _context = context;
var namedType = (INamedTypeSymbol)symbol; _cancellationToken = cancellationToken;
if (namedType.SpecialType == SpecialType.System_Void) }
{
return false;
}
break; internal bool ShouldIncludeSymbol(ISymbol symbol)
{
var isMember = false;
switch (symbol.Kind)
{
case SymbolKind.NamedType:
var namedType = (INamedTypeSymbol)symbol;
if (namedType.SpecialType == SpecialType.System_Void)
{
return false;
}
break;
case SymbolKind.Method:
switch (((IMethodSymbol)symbol).MethodKind)
{
case MethodKind.EventAdd:
case MethodKind.EventRemove:
case MethodKind.EventRaise:
case MethodKind.PropertyGet:
case MethodKind.PropertySet:
return false;
}
isMember = true;
break;
case SymbolKind.Event:
case SymbolKind.Field:
case SymbolKind.Property:
isMember = true;
break;
case SymbolKind.TypeParameter:
return ((ITypeParameterSymbol)symbol).TypeParameterKind != TypeParameterKind.Cref;
}
if (_context.IsAttributeNameContext)
{
var enclosingSymbol = _context.SemanticModel.GetEnclosingNamedType(_context.LeftToken.SpanStart, _cancellationToken);
return symbol.IsOrContainsAccessibleAttribute(enclosingSymbol, _context.SemanticModel.Compilation.Assembly);
}
if (_context.IsEnumTypeMemberAccessContext)
{
return symbol.Kind == SymbolKind.Field;
}
case SymbolKind.Method: // In an expression or statement context, we don't want to display instance members declared in outer containing types.
var methodSymbol = (IMethodSymbol)symbol; if ((_context.IsStatementContext || _context.IsAnyExpressionContext) &&
if (methodSymbol.MethodKind == MethodKind.EventAdd || !symbol.IsStatic &&
methodSymbol.MethodKind == MethodKind.EventRemove || isMember)
methodSymbol.MethodKind == MethodKind.EventRaise || {
methodSymbol.MethodKind == MethodKind.PropertyGet || var containingTypeOriginalDefinition = symbol.ContainingType.OriginalDefinition;
methodSymbol.MethodKind == MethodKind.PropertySet) if (this.GetOuterTypesAndBases().Contains(containingTypeOriginalDefinition))
{ {
return false; return this.GetEnclosingTypeBases().Contains(containingTypeOriginalDefinition);
} }
}
isMember = true; var namespaceSymbol = symbol as INamespaceSymbol;
break; if (namespaceSymbol != null)
{
case SymbolKind.Event: return namespaceSymbol.ContainsAccessibleTypesOrNamespaces(_context.SemanticModel.Compilation.Assembly);
case SymbolKind.Field: }
case SymbolKind.Property:
isMember = true;
break;
case SymbolKind.TypeParameter: return true;
return ((ITypeParameterSymbol)symbol).TypeParameterKind != TypeParameterKind.Cref;
} }
if (context.IsAttributeNameContext) private IEnumerable<INamedTypeSymbol> GetOuterTypesAndBases()
{ {
var enclosingSymbol = context.SemanticModel.GetEnclosingNamedType(context.LeftToken.SpanStart, cancellationToken); if (_lazyOuterTypesAndBases == null)
return symbol.IsOrContainsAccessibleAttribute(enclosingSymbol, context.SemanticModel.Compilation.Assembly); {
} _lazyOuterTypesAndBases = _context.GetOuterTypes(_cancellationToken).SelectMany(o => o.GetBaseTypesAndThis()).Select(t => t.OriginalDefinition);
}
if (context.IsEnumTypeMemberAccessContext) return _lazyOuterTypesAndBases;
{
return symbol.Kind == SymbolKind.Field;
} }
// In an expression or statement context, we don't want to display instance members declared in outer containing types. private IEnumerable<INamedTypeSymbol> GetEnclosingTypeBases()
if ((context.IsStatementContext || context.IsAnyExpressionContext) &&
!symbol.IsStatic &&
isMember)
{ {
var outerTypesAndBases = context.GetOuterTypes(cancellationToken).SelectMany(o => o.GetBaseTypesAndThis()).Select(t => t.OriginalDefinition); if (_lazyEnclosingTypeBases == null)
var containingTypeOriginalDefinition = symbol.ContainingType.OriginalDefinition;
if (outerTypesAndBases.Contains(containingTypeOriginalDefinition))
{ {
var enclosingType = context.SemanticModel.GetEnclosingNamedType(context.LeftToken.SpanStart, cancellationToken); var enclosingType = _context.SemanticModel.GetEnclosingNamedType(_context.LeftToken.SpanStart, _cancellationToken);
return enclosingType != null && enclosingType.GetBaseTypes().Select(b => b.OriginalDefinition).Contains(containingTypeOriginalDefinition); _lazyEnclosingTypeBases = (enclosingType == null) ?
SpecializedCollections.EmptyEnumerable<INamedTypeSymbol>() :
enclosingType.GetBaseTypes().Select(b => b.OriginalDefinition);
} }
}
var namespaceSymbol = symbol as INamespaceSymbol; return _lazyEnclosingTypeBases;
if (namespaceSymbol != null)
{
return namespaceSymbol.ContainsAccessibleTypesOrNamespaces(context.SemanticModel.Compilation.Assembly);
} }
return true;
} }
} }
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册