提交 699eed6a 编写于 作者: C Cyrus Najmabadi

restore file

上级 d7d64d39
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using System.Threading;
namespace Microsoft.CodeAnalysis
{
internal partial struct SymbolKey
{
private static class BodyLevelSymbolKey
{
public static void Create(ISymbol symbol, SymbolKeyWriter visitor)
{
var containingSymbol = symbol.ContainingSymbol;
while (containingSymbol.DeclaringSyntaxReferences.IsDefaultOrEmpty)
{
containingSymbol = containingSymbol.ContainingSymbol;
}
var compilation = ((ISourceAssemblySymbol)symbol.ContainingAssembly).Compilation;
var kind = symbol.Kind;
var localName = symbol.Name;
// Use two mechanisms to try to find the symbol across compilations. First, we use a whitespace
// insensitive system where we keep track of the list of all locals in the container and we just store
// our index in it.
//
// The above works for cases where the symbol has a real declaration and can be found by walking the
// declarations of the container. However, not all symbols can be found that way. For example, error
// 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();
visitor.WriteString(localName);
visitor.WriteSymbolKey(containingSymbol);
visitor.WriteInteger(ordinal);
visitor.WriteLocation(symbol.Locations[0]);
visitor.WriteInteger((int)kind);
return;
int GetOrdinal()
{
foreach (var possibleSymbol in EnumerateSymbols(compilation, containingSymbol, kind, localName, visitor.CancellationToken))
{
if (possibleSymbol.symbol.Equals(symbol))
return possibleSymbol.ordinal;
}
return int.MaxValue;
}
}
public static SymbolKeyResolution Resolve(SymbolKeyReader reader)
{
var cancellationToken = reader.CancellationToken;
var localName = reader.ReadString();
var containingSymbolResolution = reader.ReadSymbolKey();
var ordinal = reader.ReadInteger();
var location = reader.ReadLocation();
var kind = (SymbolKind)reader.ReadInteger();
var containingSymbol = containingSymbolResolution.Symbol;
if (containingSymbol != null)
{
if (ordinal != int.MaxValue)
{
foreach (var symbol in EnumerateSymbols(reader.Compilation, containingSymbol, kind, localName, cancellationToken))
{
if (symbol.ordinal == ordinal)
return new SymbolKeyResolution(symbol.symbol);
}
}
else
{
var resolution = reader.ResolveLocation(location);
if (resolution != null)
return resolution.Value;
}
}
return new SymbolKeyResolution();
}
private static IEnumerable<(ISymbol symbol, int ordinal)> EnumerateSymbols(
Compilation compilation, ISymbol containingSymbol,
SymbolKind kind, string localName,
CancellationToken cancellationToken)
{
var ordinal = 0;
foreach (var declaringLocation in containingSymbol.DeclaringSyntaxReferences)
{
// This operation can potentially fail. If containingSymbol came from
// a SpeculativeSemanticModel, containingSymbol.ContainingAssembly.Compilation
// may not have been rebuilt to reflect the trees used by the
// SpeculativeSemanticModel to produce containingSymbol. In that case,
// asking the ContainingAssembly's compilation for a SemanticModel based
// on trees for containingSymbol with throw an ArgumentException.
// Unfortunately, the best way to avoid this (currently) is to see if
// we're asking for a model for a tree that's part of the compilation.
// (There's no way to get back to a SemanticModel from a symbol).
// TODO (rchande): It might be better to call compilation.GetSemanticModel
// and catch the ArgumentException. The compilation internally has a
// Dictionary<SyntaxTree, ...> that it uses to check if the SyntaxTree
// is applicable wheras the public interface requires us to enumerate
// the entire IEnumerable of trees in the Compilation.
if (!Contains(compilation.SyntaxTrees, declaringLocation.SyntaxTree))
{
continue;
}
var node = declaringLocation.GetSyntax(cancellationToken);
if (node.Language == LanguageNames.VisualBasic)
{
node = node.Parent;
}
var semanticModel = compilation.GetSemanticModel(node.SyntaxTree);
foreach (var token in node.DescendantNodes())
{
var symbol = semanticModel.GetDeclaredSymbol(token, cancellationToken);
if (symbol != null &&
symbol.Kind == kind &&
SymbolKey.Equals(compilation, symbol.Name, localName))
{
yield return (symbol, ordinal++);
}
}
}
}
private static bool Contains(IEnumerable<SyntaxTree> trees, SyntaxTree tree)
{
foreach (var current in trees)
{
if (current == tree)
{
return true;
}
}
return false;
}
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册