提交 2cdfd456 编写于 作者: C Cyrus Najmabadi

Add support for cref-type-parameters.

上级 e90cf291
......@@ -4,7 +4,7 @@
using System.Collections.Generic;
using System.Threading;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis
{
......@@ -34,13 +34,11 @@ public static void Create(ISymbol symbol, SymbolKeyWriter visitor)
// locals in VB can't be found using GetDeclaredSymbol. For those, we store the actual local span and
// use GetSymbolInfo to find it.
var ordinal = GetOrdinal();
var span = symbol.Locations[0].SourceSpan;
visitor.WriteString(localName);
visitor.WriteSymbolKey(containingSymbol);
visitor.WriteInteger(ordinal);
visitor.WriteInteger(span.Start);
visitor.WriteInteger(span.Length);
visitor.WriteLocation(symbol.Locations[0]);
visitor.WriteInteger((int)kind);
return;
......@@ -64,8 +62,7 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader)
var localName = reader.ReadString();
var containingSymbolResolution = reader.ReadSymbolKey();
var ordinal = reader.ReadInteger();
var spanStart = reader.ReadInteger();
var spanLength = reader.ReadInteger();
var location = reader.ReadLocation();
var kind = (SymbolKind)reader.ReadInteger();
var containingSymbol = containingSymbolResolution.Symbol;
......@@ -81,23 +78,9 @@ public static SymbolKeyResolution Resolve(SymbolKeyReader reader)
}
else
{
var span = new TextSpan(spanStart, spanLength);
foreach (var containerRef in containingSymbol.DeclaringSyntaxReferences)
{
var containerNode = containerRef.GetSyntax(cancellationToken);
if (containerNode.Parent.Span.Contains(span))
{
var syntaxTree = containerRef.SyntaxTree;
var node = syntaxTree.GetRoot(cancellationToken).FindNode(span, getInnermostNodeForTie: true);
var semanticModel = reader.Compilation.GetSemanticModel(syntaxTree);
var info = semanticModel.GetSymbolInfo(node, cancellationToken);
if (info.Symbol != null)
return new SymbolKeyResolution(info.Symbol);
if (info.CandidateSymbols.Length > 0)
return new SymbolKeyResolution(info.CandidateSymbols, info.CandidateReason);
}
}
var resolution = reader.ResolveLocation(location);
if (resolution != null)
return resolution.Value;
}
}
......
......@@ -9,6 +9,7 @@
using System.Text;
using System.Threading;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
......@@ -445,7 +446,7 @@ private SymbolKeyResolution ReadWorker(SymbolKeyType type)
/// will either be the same as the original amount written, or <c>default</c> will be
/// returned. It will never be less or more. <c>default</c> will be returned if any
/// elements could not be resolved to the requested <typeparamref name="TSymbol"/> type
/// in the provided <see cref="Compilation"/>.
/// in the provided <see cref="SymbolKeyReader.Compilation"/>.
///
/// Callers should <see cref="IDisposable.Dispose"/> the instance returned. No check is
/// necessary if <c>default</c> was returned before calling <see cref="IDisposable.Dispose"/>
......@@ -545,6 +546,23 @@ public Location ReadLocation()
return Location.None;
}
public SymbolKeyResolution? ResolveLocation(Location location)
{
if (location.SourceTree != null)
{
var node = location.FindNode(findInsideTrivia: true, getInnermostNodeForTie: true, CancellationToken);
var semanticModel = Compilation.GetSemanticModel(location.SourceTree);
var info = semanticModel.GetSymbolInfo(node, CancellationToken);
if (info.Symbol != null)
return new SymbolKeyResolution(info.Symbol);
if (info.CandidateSymbols.Length > 0)
return new SymbolKeyResolution(info.CandidateSymbols, info.CandidateReason);
}
return null;
}
private IModuleSymbol GetModule(IEnumerable<IModuleSymbol> modules, string moduleName)
{
foreach (var module in modules)
......
......@@ -12,28 +12,48 @@ private static class TypeParameterSymbolKey
{
public static void Create(ITypeParameterSymbol symbol, SymbolKeyWriter visitor)
{
visitor.WriteString(symbol.MetadataName);
visitor.WriteSymbolKey(symbol.ContainingSymbol);
if (symbol.TypeParameterKind == TypeParameterKind.Cref)
{
visitor.WriteBoolean(true);
visitor.WriteLocation(symbol.Locations[0]);
}
else
{
visitor.WriteBoolean(false);
visitor.WriteString(symbol.MetadataName);
visitor.WriteSymbolKey(symbol.ContainingSymbol);
}
}
public static SymbolKeyResolution Resolve(SymbolKeyReader reader)
{
var metadataName = reader.ReadString();
var containingSymbolResolution = reader.ReadSymbolKey();
var isCref = reader.ReadBoolean();
using var result = PooledArrayBuilder<ITypeParameterSymbol>.GetInstance();
foreach (var containingSymbol in containingSymbolResolution)
if (isCref)
{
foreach (var typeParam in containingSymbol.GetTypeParameters())
var location = reader.ReadLocation();
var resolution = reader.ResolveLocation(location);
return resolution.GetValueOrDefault();
}
else
{
var metadataName = reader.ReadString();
var containingSymbolResolution = reader.ReadSymbolKey();
using var result = PooledArrayBuilder<ITypeParameterSymbol>.GetInstance();
foreach (var containingSymbol in containingSymbolResolution)
{
if (typeParam.MetadataName == metadataName)
foreach (var typeParam in containingSymbol.GetTypeParameters())
{
result.AddIfNotNull(typeParam);
if (typeParam.MetadataName == metadataName)
{
result.AddIfNotNull(typeParam);
}
}
}
}
return CreateResolution(result);
return CreateResolution(result);
}
}
}
}
......
......@@ -87,6 +87,15 @@ internal partial class SolutionState
}
}
}
else if (symbol.IsKind(SymbolKind.TypeParameter, out ITypeParameterSymbol? typeParameter) &&
typeParameter.TypeParameterKind == TypeParameterKind.Cref)
{
// Cref type parameters don't belong to any containing symbol. But we can map them to a doc/project
// using the declaring syntax of the type parameter itself.
var tree = typeParameter.Locations[0].SourceTree;
var doc = this.GetDocumentState(tree, projectId: null);
return doc?.Id.ProjectId;
}
return null;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册