提交 941b6cea 编写于 作者: C Cyrus Najmabadi

Improve searching for symbols when a name is known ahead of time.

上级 04d57fd6
......@@ -1447,8 +1447,10 @@ private MethodSymbol FindEntryPoint(CancellationToken cancellationToken, out Imm
else
{
mainType = null;
EntryPointCandidateFinder.FindCandidatesInNamespace(globalNamespace, entryPointCandidates, cancellationToken);
var candidates = this.GetSymbolsWithName(WellKnownMemberNames.EntryPointMethodName, SymbolFilter.Member, cancellationToken)
.OfType<MethodSymbol>()
.Where(m => m.IsEntryPointCandidate);
entryPointCandidates.AddRange(candidates);
// Global code is the entry point, ignore all other Mains.
var scriptClass = this.ScriptClass;
......@@ -3033,7 +3035,25 @@ public override IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predi
throw new ArgumentException(CSharpResources.NoNoneSearchCriteria, nameof(filter));
}
return new SymbolSearcher(this).GetSymbolsWithName(predicate, filter, cancellationToken);
return new PredicateSymbolSearcher(this, filter, predicate, cancellationToken).GetSymbolsWithName();
}
/// <summary>
/// Return source declaration symbols whose name matches the provided name
/// </summary>
internal override IEnumerable<ISymbol> GetSymbolsWithName(string name, SymbolFilter filter = SymbolFilter.TypeAndMember, CancellationToken cancellationToken = default(CancellationToken))
{
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (filter == SymbolFilter.None)
{
throw new ArgumentException(CSharpResources.NoNoneSearchCriteria, nameof(filter));
}
return new NameSymbolSearcher(this, filter, name, cancellationToken).GetSymbolsWithName();
}
#endregion
......@@ -3096,38 +3116,57 @@ internal bool EnableEnumArrayBlockInitialization
}
}
private class SymbolSearcher
private abstract class AbstractSymbolSearcher
{
private static readonly ObjectPool<Dictionary<Declaration, NamespaceOrTypeSymbol>> s_cachePool =
new ObjectPool<Dictionary<Declaration, NamespaceOrTypeSymbol>>(() => new Dictionary<Declaration, NamespaceOrTypeSymbol>());
private readonly Dictionary<Declaration, NamespaceOrTypeSymbol> _cache;
private readonly CSharpCompilation _compilation;
private readonly bool _includeNamespace;
private readonly bool _includeType;
private readonly bool _includeMember;
private readonly CancellationToken _cancellationToken;
public SymbolSearcher(CSharpCompilation compilation)
protected AbstractSymbolSearcher(
CSharpCompilation compilation, SymbolFilter filter, CancellationToken cancellationToken)
{
_cache = new Dictionary<Declaration, NamespaceOrTypeSymbol>();
_cache = s_cachePool.Allocate();
_compilation = compilation;
_includeNamespace = (filter & SymbolFilter.Namespace) == SymbolFilter.Namespace;
_includeType = (filter & SymbolFilter.Type) == SymbolFilter.Type;
_includeMember = (filter & SymbolFilter.Member) == SymbolFilter.Member;
_cancellationToken = cancellationToken;
}
public IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, SymbolFilter filter, CancellationToken cancellationToken)
protected abstract bool Matches(string name);
protected abstract bool ShouldCheckTypeForMembers(MergedTypeDeclaration current);
public IEnumerable<ISymbol> GetSymbolsWithName()
{
var result = new HashSet<ISymbol>();
var spine = new List<MergedNamespaceOrTypeDeclaration>();
var spine = ArrayBuilder<MergedNamespaceOrTypeDeclaration>.GetInstance();
AppendSymbolsWithName(spine, _compilation.MergedRootDeclaration, result);
AppendSymbolsWithName(spine, _compilation.MergedRootDeclaration, predicate, filter, result, cancellationToken);
spine.Free();
_cache.Clear();
s_cachePool.Free(_cache);
return result;
}
private void AppendSymbolsWithName(
List<MergedNamespaceOrTypeDeclaration> spine, MergedNamespaceOrTypeDeclaration current,
Func<string, bool> predicate, SymbolFilter filter, HashSet<ISymbol> set, CancellationToken cancellationToken)
ArrayBuilder<MergedNamespaceOrTypeDeclaration> spine, MergedNamespaceOrTypeDeclaration current,
HashSet<ISymbol> set)
{
var includeNamespace = (filter & SymbolFilter.Namespace) == SymbolFilter.Namespace;
var includeType = (filter & SymbolFilter.Type) == SymbolFilter.Type;
var includeMember = (filter & SymbolFilter.Member) == SymbolFilter.Member;
if (current.Kind == DeclarationKind.Namespace)
{
if (includeNamespace && predicate(current.Name))
if (_includeNamespace && Matches(current.Name))
{
var container = GetSpineSymbol(spine);
var symbol = GetSymbol(container, current);
......@@ -3139,7 +3178,7 @@ public IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, Sym
}
else
{
if (includeType && predicate(current.Name))
if (_includeType && Matches(current.Name))
{
var container = GetSpineSymbol(spine);
var symbol = GetSymbol(container, current);
......@@ -3149,25 +3188,26 @@ public IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, Sym
}
}
if (includeMember)
if (_includeMember)
{
AppendMemberSymbolsWithName(spine, current, predicate, set, cancellationToken);
var typeDeclaration = (MergedTypeDeclaration)current;
if (ShouldCheckTypeForMembers(typeDeclaration))
{
AppendMemberSymbolsWithName(spine, typeDeclaration, set);
}
}
}
spine.Add(current);
foreach (var child in current.Children.OfType<MergedNamespaceOrTypeDeclaration>())
foreach (var child in current.Children)
{
if (includeMember || includeType)
if (child is MergedNamespaceOrTypeDeclaration mergedNamespaceOrType)
{
AppendSymbolsWithName(spine, child, predicate, filter, set, cancellationToken);
continue;
}
if (child.Kind == DeclarationKind.Namespace)
{
AppendSymbolsWithName(spine, child, predicate, filter, set, cancellationToken);
if (_includeMember || _includeType || child.Kind == DeclarationKind.Namespace)
{
AppendSymbolsWithName(spine, mergedNamespaceOrType, set);
}
}
}
......@@ -3176,8 +3216,7 @@ public IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, Sym
}
private void AppendMemberSymbolsWithName(
List<MergedNamespaceOrTypeDeclaration> spine, MergedNamespaceOrTypeDeclaration current,
Func<string, bool> predicate, HashSet<ISymbol> set, CancellationToken cancellationToken)
ArrayBuilder<MergedNamespaceOrTypeDeclaration> spine, MergedTypeDeclaration current, HashSet<ISymbol> set)
{
spine.Add(current);
......@@ -3188,7 +3227,7 @@ public IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, Sym
{
if (!member.IsTypeOrTypeAlias() &&
(member.CanBeReferencedByName || member.IsExplicitInterfaceImplementation() || member.IsIndexer()) &&
predicate(member.Name))
Matches(member.Name))
{
set.Add(member);
}
......@@ -3198,7 +3237,7 @@ public IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, Sym
spine.RemoveAt(spine.Count - 1);
}
private NamespaceOrTypeSymbol GetSpineSymbol(List<MergedNamespaceOrTypeDeclaration> spine)
protected NamespaceOrTypeSymbol GetSpineSymbol(ArrayBuilder<MergedNamespaceOrTypeDeclaration> spine)
{
if (spine.Count == 0)
{
......@@ -3276,5 +3315,56 @@ private void AddCache(IEnumerable<NamespaceOrTypeSymbol> symbols)
}
}
}
private class PredicateSymbolSearcher : AbstractSymbolSearcher
{
private readonly Func<string, bool> _predicate;
public PredicateSymbolSearcher(
CSharpCompilation compilation, SymbolFilter filter, Func<string, bool> predicate, CancellationToken cancellationToken)
: base(compilation, filter, cancellationToken)
{
_predicate = predicate;
}
protected override bool ShouldCheckTypeForMembers(MergedTypeDeclaration current)
{
// Note: this preserves the behavior the compiler has always had when a predicate
// is passed in. We could potentially be smarter by checking the predicate
// against the list of member names in the type declaration first.
return true;
}
protected override bool Matches(string name)
=> _predicate(name);
}
private class NameSymbolSearcher : AbstractSymbolSearcher
{
private readonly string _name;
public NameSymbolSearcher(
CSharpCompilation compilation, SymbolFilter filter, string name, CancellationToken cancellationToken)
: base(compilation, filter, cancellationToken)
{
_name = name;
}
protected override bool ShouldCheckTypeForMembers(MergedTypeDeclaration current)
{
foreach (var typeDecl in current.Declarations)
{
if (typeDecl.MemberNames.Contains(_name))
{
return true;
}
}
return false;
}
protected override bool Matches(string name)
=> _name == name;
}
}
}
......@@ -61,15 +61,7 @@ public override object VisitNamedType(NamedTypeSymbol symbol, object arg)
case SymbolKind.Method:
{
MethodSymbol method = (MethodSymbol)member;
if (method.IsPartialDefinition())
{
if ((object)method.PartialImplementationPart == null)
{
continue;
}
}
var method = (MethodSymbol)member;
if (method.IsEntryPointCandidate)
{
_entryPointCandidates.Add(method);
......
......@@ -613,9 +613,17 @@ internal bool IsSubmissionInitializer
/// </summary>
internal bool IsEntryPointCandidate
{
get { return IsStatic && Name == WellKnownMemberNames.EntryPointMethodName; }
}
get
{
if (this.IsPartialDefinition() &&
this.PartialImplementationPart is null)
{
return false;
}
return IsStatic && Name == WellKnownMemberNames.EntryPointMethodName;
}
}
internal override TResult Accept<TArgument, TResult>(CSharpSymbolVisitor<TArgument, TResult> visitor, TArgument argument)
{
......
......@@ -2907,6 +2907,11 @@ internal string GetMessage(ITypeSymbol source, ITypeSymbol destination)
/// </summary>
public abstract IEnumerable<ISymbol> GetSymbolsWithName(Func<string, bool> predicate, SymbolFilter filter = SymbolFilter.TypeAndMember, CancellationToken cancellationToken = default(CancellationToken));
/// <summary>
/// Return source declaration symbols whose name matches the provided name
/// </summary>
internal abstract IEnumerable<ISymbol> GetSymbolsWithName(string name, SymbolFilter filter = SymbolFilter.TypeAndMember, CancellationToken cancellationToken = default(CancellationToken));
#endregion
internal void MakeMemberMissing(WellKnownMember member)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册