提交 c40060f4 编写于 作者: H Heejae Chang

more refactoring

上级 c3e89aed
......@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.Semantics;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis
{
......@@ -147,11 +148,23 @@ public override void Accept(OperationVisitor visitor)
return visitor.VisitNoneOperation(this, argument);
}
public override IEnumerable<IOperation> Children => _getChildren().NullToEmpty();
public override IEnumerable<IOperation> Children
{
get
{
foreach (var child in _getChildren().NullToEmpty().WhereNotNull())
{
yield return Operation.SetParentOperation(child, this);
}
}
}
}
private static IOperation WalkDownOperationToFindParent(
HashSet<IOperation> operationAlreadyProcessed, IOperation operation, TextSpan span)
private static readonly ObjectPool<Queue<IOperation>> s_queuePool =
new ObjectPool<Queue<IOperation>>(() => new Queue<IOperation>(), 10);
private IOperation WalkDownOperationToFindParent(
HashSet<IOperation> operationAlreadyProcessed, IOperation root, TextSpan span)
{
void EnqueueChildOperations(Queue<IOperation> queue, IOperation parent)
{
......@@ -162,96 +175,89 @@ void EnqueueChildOperations(Queue<IOperation> queue, IOperation parent)
}
}
// do we have a pool for queue?
var parentChildQueue = new Queue<IOperation>();
EnqueueChildOperations(parentChildQueue, operation);
var operationQueue = s_queuePool.Allocate();
// walk down the child operation to find parent operation
// every child returned by the queue should already have Parent operation set
IOperation child;
while ((child = parentChildQueue.Dequeue()) != null)
try
{
if (!operationAlreadyProcessed.Add(child))
{
// don't process IOperation we already processed otherwise,
// we can walk down same tree multiple times
continue;
}
EnqueueChildOperations(operationQueue, root);
if (child == operation)
// walk down the tree to find parent operation
// every operation returned by the queue should already have Parent operation set
while (operationQueue.Count > 0)
{
// parent found
return child.Parent;
}
var operation = operationQueue.Dequeue();
if (!child.Syntax.FullSpan.IntersectsWith(span))
{
// not related node, don't walk down
continue;
if (!operationAlreadyProcessed.Add(operation))
{
// don't process IOperation we already processed otherwise,
// we can walk down same tree multiple times
continue;
}
if (operation == this)
{
// parent found
return operation.Parent;
}
if (!operation.Syntax.FullSpan.IntersectsWith(span))
{
// not related node, don't walk down
continue;
}
// queue children so that we can do breadth first search
EnqueueChildOperations(operationQueue, operation);
}
// queue children so that we can do breadth first search
EnqueueChildOperations(parentChildQueue, child);
return null;
}
finally
{
operationQueue.Clear();
s_queuePool.Free(operationQueue);
}
return null;
}
private IOperation SearchParentOperation()
{
// do we have a pool for hashset?
var operationAlreadyProcessed = new HashSet<IOperation>();
var operationAlreadyProcessed = PooledHashSet<IOperation>.GetInstance();
var targetNode = Syntax;
var currentCandidate = targetNode.Parent;
while (currentCandidate != null)
{
Debug.Assert(currentCandidate.FullSpan.IntersectsWith(targetNode.FullSpan));
// start from current node since one node can have multiple operations mapped to
var currentCandidate = targetNode;
foreach (var childNode in currentCandidate.ChildNodes())
try
{
while (currentCandidate != null)
{
if (!childNode.FullSpan.IntersectsWith(targetNode.FullSpan))
{
// skip unrelated node
continue;
}
Debug.Assert(currentCandidate.FullSpan.IntersectsWith(targetNode.FullSpan));
// get child operation
var childOperation = _semanticModel.GetOperationInternal(childNode);
if (childOperation != null)
// get operation
var tree = _semanticModel.GetOperationInternal(currentCandidate);
if (tree != null)
{
// there is no operation for this node
continue;
// walk down operation tree to see whether this tree contains parent of this operation
var parent = WalkDownOperationToFindParent(operationAlreadyProcessed, tree, targetNode.FullSpan);
if (parent != null)
{
return parent;
}
}
// record we have processed this node
if (!operationAlreadyProcessed.Add(childOperation))
{
// we already processed this tree. no need to dig down
continue;
}
// check easy case first
if (childOperation == this)
{
// found parent, go up the spine until we found non-null parent Operation
return currentCandidate.AncestorsAndSelf().Select(n => _semanticModel.GetOperationInternal(n)).WhereNotNull().FirstOrDefault();
}
// walk down child operation tree to see whether sub tree contains the given operation
var parent = WalkDownOperationToFindParent(operationAlreadyProcessed, childOperation, targetNode.FullSpan);
if (parent != null)
{
return parent;
}
// move up the tree
currentCandidate = currentCandidate.Parent;
}
currentCandidate = currentCandidate.Parent;
// root node. there is no parent
return null;
}
finally
{
// put the hashset back to the pool
operationAlreadyProcessed.Free();
}
// root node. there is no parent
return null;
}
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
......@@ -27,6 +28,9 @@ public static bool HasErrors(this IOperation operation, Compilation compilation,
return model.GetDiagnostics(operation.Syntax.Span, cancellationToken).Any(d => d.DefaultSeverity == DiagnosticSeverity.Error);
}
private static readonly ObjectPool<Stack<IEnumerator<IOperation>>> s_childEnumeratorStackPool =
new ObjectPool<Stack<IEnumerator<IOperation>>>(() => new Stack<IEnumerator<IOperation>>(), 10);
public static IEnumerable<IOperation> Descendants(this IOperation operation)
{
if (operation == null)
......@@ -46,26 +50,33 @@ public static IEnumerable<IOperation> DescendantsAndSelf(this IOperation operati
yield return operation;
var stack = new Stack<IEnumerator<IOperation>>();
var stack = s_childEnumeratorStackPool.Allocate();
stack.Push(operation.Children.GetEnumerator());
IEnumerator<IOperation> iterator;
while ((iterator = stack.Pop()) != null)
while (stack.Count > 0)
{
var iterator = stack.Pop();
if (!iterator.MoveNext())
{
continue;
}
var current = iterator.Current;
yield return current;
// push current iterator back in to the stack
stack.Push(iterator);
// push children iterator to the stack
stack.Push(current.Children.GetEnumerator());
if (current != null)
{
yield return current;
stack.Push(current.Children.GetEnumerator());
}
}
stack.Clear();
s_childEnumeratorStackPool.Free(stack);
}
public static IOperation GetRootOperation(this ISymbol symbol, CancellationToken cancellationToken = default(CancellationToken))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册