提交 8b346175 编写于 作者: P Paul Vick

Rework based on comments

上级 8648f918
......@@ -556,11 +556,6 @@ public bool IsDeclaration(SyntaxNode node)
throw new NotImplementedException();
}
public bool IsMethodDeclaration(SyntaxNode node)
{
throw new NotImplementedException();
}
public string GetText(int kind)
{
throw new NotImplementedException();
......
......@@ -528,10 +528,6 @@ End Class]]></a>.Value.NormalizeLineEndings()
Throw New NotImplementedException
End Function
Public Function IsMethodDeclaration(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsMethodDeclaration
Throw New NotImplementedException
End Function
Public Function GetText(kind As Integer) As String Implements ISyntaxFactsService.GetText
Throw New NotImplementedException()
End Function
......
......@@ -165,34 +165,6 @@ public string GetDisplayName(SemanticModel semanticModel, SyntaxNode node)
}
}
public string ConstructFullName(SemanticModel semanticModel, SyntaxNode methodNode)
{
var name = semanticModel.GetDeclaredSymbol(methodNode).Name;
var parent = methodNode.Parent;
while (parent != null)
{
if (parent.IsKind(SyntaxKind.ClassDeclaration))
{
name = semanticModel.GetDeclaredSymbol(parent).Name + (!string.IsNullOrEmpty(name) ? "+" + name : "");
}
else if (parent.IsKind(SyntaxKind.NamespaceDeclaration))
{
// ToDisplayString returns the immmediate namespace's FQN.
name = semanticModel.GetDeclaredSymbol(parent).ToDisplayString() + (!string.IsNullOrEmpty(name) ? "." + name : "");
break;
}
else
{
// bail out loop when we encounterd a node which is not namespace/type.
break;
}
parent = parent.Parent;
}
return name;
}
private static string GetEnclosingScopeString(SyntaxNode node, SemanticModel semanticModel, SymbolDisplayFormat symbolDisplayFormat)
{
var scopeNode = node;
......
......@@ -18,6 +18,10 @@ namespace Microsoft.CodeAnalysis.CodeLens
[ExportWorkspaceService(typeof(ICodeLensReferencesService)), Shared]
internal sealed class CodeLensReferenceService : ICodeLensReferencesService
{
private static readonly SymbolDisplayFormat MethodDisplayFormat =
new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces);
private async Task<T> FindAsync<T>(Solution solution, DocumentId documentId, SyntaxNode syntaxNode,
Func<CodeLensFindReferencesProgress, Task<T>> onResults, Func<CodeLensFindReferencesProgress, Task<T>> onCapped,
int searchCap, CancellationToken cancellationToken) where T: class
......@@ -195,30 +199,30 @@ public async Task<IEnumerable<ReferenceLocationDescriptor>> FindReferenceLocatio
}, onCapped: null, searchCap: 0, cancellationToken: cancellationToken).ConfigureAwait(false);
}
private static SyntaxNode FindEnclosingMethodNode(Document document, int position)
private static ISymbol GetEnclosingMethod(SemanticModel semanticModel, Location location)
{
var getSyntaxRootTask = document.GetSyntaxRootAsync();
var root = getSyntaxRootTask.Result;
var enclosingSymbol = semanticModel.GetEnclosingSymbol(location.SourceSpan.Start);
if (!root.FullSpan.Contains(position))
for (var current = enclosingSymbol; current != null; current = current.ContainingSymbol)
{
return null;
}
if (current.Kind != SymbolKind.Method)
{
continue;
}
var token = root.FindToken(position);
var node = token.Parent;
var syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();
var method = (IMethodSymbol)current;
if (method.IsAccessor())
{
return method.AssociatedSymbol;
}
while (node != null)
{
if (syntaxFacts.IsMethodDeclaration(node))
if (method.MethodKind != MethodKind.AnonymousFunction)
{
break;
return method;
}
node = node.Parent;
}
return node;
return null;
}
private static async Task<ReferenceMethodDescriptor> TryCreateMethodDescriptorAsync(Location commonLocation, Solution solution, CancellationToken cancellationToken)
......@@ -236,17 +240,7 @@ private static async Task<ReferenceMethodDescriptor> TryCreateMethodDescriptorAs
return null;
}
var methodNode = FindEnclosingMethodNode(document, commonLocation.SourceSpan.Start);
if (methodNode == null)
{
return null;
}
var displayInfoService = document.GetLanguageService<ICodeLensDisplayInfoService>();
var fullName = displayInfoService.ConstructFullName(semanticModel, methodNode);
cancellationToken.ThrowIfCancellationRequested();
var fullName = GetEnclosingMethod(semanticModel, commonLocation)?.ToDisplayString(MethodDisplayFormat);
return !string.IsNullOrEmpty(fullName) ? new ReferenceMethodDescriptor(fullName, document.FilePath) : null;
}
......
......@@ -15,10 +15,5 @@ internal interface ICodeLensDisplayInfoService : ILanguageService
/// Gets the DisplayName for the given node
/// </summary>
string GetDisplayName(SemanticModel semanticModel, SyntaxNode node);
/// <summary>
/// Given a semantic model and methodNode, this method returns FQN with '+' as delimiter for the nested type
/// </summary>
string ConstructFullName(SemanticModel semanticModel, SyntaxNode methodNode);
}
}
......@@ -11,15 +11,15 @@ internal sealed class ReferenceMethodDescriptor
/// Describe a caller method of a callee
/// </summary>
/// <param name="methodFullName">Method's fully qualified name</param>
/// <param name="methodFullPath">Method full path</param>
/// <param name="methodFilePath">Method full path</param>
/// <remarks>
/// Method full name is expected to be in the .NET full name type convention. That is,
/// namespace/type is delimited by '.' and nested type is delimited by '+'
/// </remarks>
public ReferenceMethodDescriptor(string methodFullName, string methodFullPath)
public ReferenceMethodDescriptor(string methodFullName, string methodFilePath)
{
FullName = methodFullName;
FullPath = methodFullPath;
FilePath = methodFilePath;
}
/// <summary>
......@@ -30,6 +30,6 @@ public ReferenceMethodDescriptor(string methodFullName, string methodFullPath)
/// <summary>
/// Returns method's file path.
/// </summary>
public string FullPath { get; private set; }
public string FilePath { get; private set; }
}
}
......@@ -146,7 +146,7 @@
<Compile Include="CodeFixes\Suppression\ExportSuppressionFixProviderAttribute.cs" />
<Compile Include="CodeFixes\Suppression\WrapperCodeFixProvider.cs" />
<Compile Include="CodeFixes\Suppression\AbstractSuppressionCodeFixProvider.cs" />
<Compile Include="CodeLens\CodeLenseReferenceService.cs" />
<Compile Include="CodeLens\CodeLensReferenceService.cs" />
<Compile Include="CodeLens\CodeLensFindReferenceProgress.cs" />
<Compile Include="CodeLens\ICodeLensReferencesService.cs" />
<Compile Include="CodeLens\ICodeLensDisplayInfoService.cs" />
......
......@@ -158,40 +158,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeLens
Return rootName
End Function
Public Function ConstructFullName(semanticModel As SemanticModel, methodNode As SyntaxNode) As String Implements ICodeLensDisplayInfoService.ConstructFullName
Dim isTopLevelNodeAClass = True
Dim parent = methodNode.Parent
Dim name = semanticModel.GetDeclaredSymbol(methodNode).Name
While parent IsNot Nothing
' construct to be like {namespace, type, childType, method}
If parent.IsKind(SyntaxKind.ClassBlock) Then
name = semanticModel.GetDeclaredSymbol(parent).Name + If(Not String.IsNullOrEmpty(name), "+" + name, "")
ElseIf parent.IsKind(SyntaxKind.NamespaceBlock) Then
name = semanticModel.GetDeclaredSymbol(parent).Name + If(Not String.IsNullOrEmpty(name), "." + name, "")
isTopLevelNodeAClass = False
Exit While
ElseIf parent.IsKind(SyntaxKind.SubBlock) OrElse parent.IsKind(SyntaxKind.FunctionBlock) Then
' Emperical observation shows that SyntaxKind.SubStatement's parent is SyntaxKind.SubBlock. We need to skip this statement.
Else
' bail out loop when we encounterd a node which is not namespace/type.
Exit While
End If
parent = parent.Parent
End While
If isTopLevelNodeAClass Then
' VB FQN requires the containing root namespace to be included. Tried finding the root namespace here.
Dim symbol = semanticModel.GetDeclaredSymbol(methodNode)
Dim rootName = GetRootNamespace(symbol)
If Not String.IsNullOrEmpty(rootName) Then
name = rootName + If(Not String.IsNullOrEmpty(name), "." + name, "")
End If
End If
return name
End Function
End Class
End Namespace
......@@ -403,11 +403,6 @@ private PredefinedOperator GetPredefinedOperator(SyntaxToken token)
return PredefinedOperator.None;
}
public bool IsMethodDeclaration(SyntaxNode node)
{
return node.IsKind(SyntaxKind.MethodDeclaration);
}
public string GetText(int kind)
{
return SyntaxFacts.GetText((SyntaxKind)kind);
......
......@@ -36,7 +36,6 @@ internal interface ISyntaxFactsService : ILanguageService
bool IsUsingOrExternOrImport(SyntaxNode node);
bool IsGlobalAttribute(SyntaxNode node);
bool IsDeclaration(SyntaxNode node);
bool IsMethodDeclaration(SyntaxNode node);
string GetText(int kind);
......
......@@ -1440,17 +1440,5 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return False
End Function
Public Function IsMethodDeclaration(node As SyntaxNode) As Boolean Implements ISyntaxFactsService.IsMethodDeclaration
Select Case node.Kind()
Case SyntaxKind.SubBlock,
SyntaxKind.SubStatement,
SyntaxKind.FunctionBlock,
SyntaxKind.FunctionStatement
Return True
End Select
Return False
End Function
End Class
End Namespace
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册