提交 73674b38 编写于 作者: J Jason Malinowski

Refactor GoToDefinitionHelpers.TryGoToDefinition to simplify the API

TryGoToDefinition accepted a containingTypeSymbol which was used
to do some specific logic to see if third-party navigation is allowed.
Move that logic to the AbstractGoToDefinitionService and just pass the
result of the logic through.
上级 6812f553
......@@ -51,9 +51,14 @@ public bool TryGoToDefinition(Document document, int position, CancellationToken
if (symbol != null)
{
var containingTypeSymbol = GetContainingTypeSymbol(position, document, cancellationToken);
if (GoToDefinitionHelpers.TryGoToDefinition(symbol, document.Project, _presenters, containingTypeSymbol, throwOnHiddenDefinition: true, cancellationToken: cancellationToken))
var isThirdPartyNavigationAllowed = IsThirdPartyNavigationAllowed(symbol, position, document, cancellationToken);
if (GoToDefinitionHelpers.TryGoToDefinition(symbol,
document.Project,
_presenters,
thirdPartyNavigationAllowed: isThirdPartyNavigationAllowed,
throwOnHiddenDefinition: true,
cancellationToken: cancellationToken))
{
return true;
}
......@@ -62,7 +67,7 @@ public bool TryGoToDefinition(Document document, int position, CancellationToken
return false;
}
private static ITypeSymbol GetContainingTypeSymbol(int caretPosition, Document document, CancellationToken cancellationToken)
private static bool IsThirdPartyNavigationAllowed(ISymbol symbolToNavigateTo, int caretPosition, Document document, CancellationToken cancellationToken)
{
var syntaxRoot = document.GetSyntaxRootAsync(cancellationToken).WaitAndGetResult(cancellationToken);
var syntaxFactsService = document.GetLanguageService<ISyntaxFactsService>();
......@@ -71,10 +76,29 @@ private static ITypeSymbol GetContainingTypeSymbol(int caretPosition, Document d
if (containingTypeDeclaration != null)
{
var semanticModel = document.GetSemanticModelAsync(cancellationToken).WaitAndGetResult(cancellationToken);
return semanticModel.GetDeclaredSymbol(containingTypeDeclaration, cancellationToken) as ITypeSymbol;
var containingTypeSymbol = semanticModel.GetDeclaredSymbol(containingTypeDeclaration, cancellationToken) as ITypeSymbol;
// Allow third parties to navigate to all symbols except types/constructors
// if we are navigating from the corresponding type.
if (containingTypeSymbol != null &&
(symbolToNavigateTo is ITypeSymbol || symbolToNavigateTo.IsConstructor()))
{
var candidateTypeSymbol = symbolToNavigateTo is ITypeSymbol
? symbolToNavigateTo
: symbolToNavigateTo.ContainingType;
if (containingTypeSymbol == candidateTypeSymbol)
{
// We are navigating from the same type, so don't allow third parties to perform the navigation.
// This ensures that if we navigate to a class from within that class, we'll stay in the same file
// rather than navigate to, say, XAML.
return false;
}
}
}
return null;
return true;
}
}
}
......@@ -20,9 +20,9 @@ internal static class GoToDefinitionHelpers
ISymbol symbol,
Project project,
IEnumerable<Lazy<INavigableItemsPresenter>> presenters,
ITypeSymbol containingTypeSymbol,
bool throwOnHiddenDefinition,
CancellationToken cancellationToken)
CancellationToken cancellationToken,
bool thirdPartyNavigationAllowed = true,
bool throwOnHiddenDefinition = false)
{
var alias = symbol as IAliasSymbol;
if (alias != null)
......@@ -49,7 +49,7 @@ internal static class GoToDefinitionHelpers
symbol = definition ?? symbol;
if (TryThirdPartyNavigation(symbol, solution, containingTypeSymbol))
if (thirdPartyNavigationAllowed && TryThirdPartyNavigation(symbol, solution))
{
return true;
}
......@@ -115,27 +115,8 @@ internal static class GoToDefinitionHelpers
}
}
private static bool TryThirdPartyNavigation(ISymbol symbol, Solution solution, ITypeSymbol containingTypeSymbol)
private static bool TryThirdPartyNavigation(ISymbol symbol, Solution solution)
{
// Allow third parties to navigate to all symbols except types/constructors
// if we are navigating from the corresponding type.
if (containingTypeSymbol != null &&
(symbol is ITypeSymbol || symbol.IsConstructor()))
{
var candidateTypeSymbol = symbol is ITypeSymbol
? symbol
: symbol.ContainingType;
if (containingTypeSymbol == candidateTypeSymbol)
{
// We are navigating from the same type, so don't allow third parties to perform the navigation.
// This ensures that if we navigate to a class from within that class, we'll stay in the same file
// rather than navigate to, say, XAML.
return false;
}
}
var symbolNavigationService = solution.Workspace.Services.GetService<ISymbolNavigationService>();
// Notify of navigation so third parties can intercept the navigation
......
......@@ -186,8 +186,7 @@ public override bool TryGoToDefinition(ISymbol symbol, Project project, Cancella
}
return GoToDefinitionHelpers.TryGoToDefinition(
searchSymbol, searchProject, _navigableItemsPresenters,
containingTypeSymbol: null, throwOnHiddenDefinition: false, cancellationToken: cancellationToken);
searchSymbol, searchProject, _navigableItemsPresenters, cancellationToken: cancellationToken);
}
public override bool TryFindAllReferences(ISymbol symbol, Project project, CancellationToken cancellationToken)
......
......@@ -37,7 +37,7 @@ Namespace Microsoft.VisualStudio.LanguageServices.UnitTests.GoToDefinition
Dim presenter = New MockNavigableItemsPresenter()
Dim success = GoToDefinitionHelpers.TryGoToDefinition(
symbolInfo.Symbol, document.Project, {New Lazy(Of INavigableItemsPresenter)(Function() presenter)}, Nothing, throwOnHiddenDefinition:=False, cancellationToken:=CancellationToken.None)
symbolInfo.Symbol, document.Project, {New Lazy(Of INavigableItemsPresenter)(Function() presenter)}, thirdPartyNavigationAllowed:=True, throwOnHiddenDefinition:=False, cancellationToken:=CancellationToken.None)
Assert.Equal(expectSuccess, success)
End Using
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册