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

more refactoring

上级 c3e89aed
...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
using Microsoft.CodeAnalysis.Semantics; using Microsoft.CodeAnalysis.Semantics;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
using Microsoft.CodeAnalysis.PooledObjects;
namespace Microsoft.CodeAnalysis namespace Microsoft.CodeAnalysis
{ {
...@@ -147,11 +148,23 @@ public override void Accept(OperationVisitor visitor) ...@@ -147,11 +148,23 @@ public override void Accept(OperationVisitor visitor)
return visitor.VisitNoneOperation(this, argument); 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( private static readonly ObjectPool<Queue<IOperation>> s_queuePool =
HashSet<IOperation> operationAlreadyProcessed, IOperation operation, TextSpan span) 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) void EnqueueChildOperations(Queue<IOperation> queue, IOperation parent)
{ {
...@@ -162,96 +175,89 @@ 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 operationQueue = s_queuePool.Allocate();
var parentChildQueue = new Queue<IOperation>();
EnqueueChildOperations(parentChildQueue, operation);
// walk down the child operation to find parent operation try
// every child returned by the queue should already have Parent operation set
IOperation child;
while ((child = parentChildQueue.Dequeue()) != null)
{ {
if (!operationAlreadyProcessed.Add(child)) EnqueueChildOperations(operationQueue, root);
{
// don't process IOperation we already processed otherwise,
// we can walk down same tree multiple times
continue;
}
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 var operation = operationQueue.Dequeue();
return child.Parent;
}
if (!child.Syntax.FullSpan.IntersectsWith(span)) if (!operationAlreadyProcessed.Add(operation))
{ {
// not related node, don't walk down // don't process IOperation we already processed otherwise,
continue; // 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 return null;
EnqueueChildOperations(parentChildQueue, child); }
finally
{
operationQueue.Clear();
s_queuePool.Free(operationQueue);
} }
return null;
} }
private IOperation SearchParentOperation() private IOperation SearchParentOperation()
{ {
// do we have a pool for hashset? var operationAlreadyProcessed = PooledHashSet<IOperation>.GetInstance();
var operationAlreadyProcessed = new HashSet<IOperation>();
var targetNode = Syntax; var targetNode = Syntax;
var currentCandidate = targetNode.Parent;
while (currentCandidate != null) // start from current node since one node can have multiple operations mapped to
{ var currentCandidate = targetNode;
Debug.Assert(currentCandidate.FullSpan.IntersectsWith(targetNode.FullSpan));
foreach (var childNode in currentCandidate.ChildNodes()) try
{
while (currentCandidate != null)
{ {
if (!childNode.FullSpan.IntersectsWith(targetNode.FullSpan)) Debug.Assert(currentCandidate.FullSpan.IntersectsWith(targetNode.FullSpan));
{
// skip unrelated node
continue;
}
// get child operation // get operation
var childOperation = _semanticModel.GetOperationInternal(childNode); var tree = _semanticModel.GetOperationInternal(currentCandidate);
if (childOperation != null) if (tree != null)
{ {
// there is no operation for this node // walk down operation tree to see whether this tree contains parent of this operation
continue; var parent = WalkDownOperationToFindParent(operationAlreadyProcessed, tree, targetNode.FullSpan);
if (parent != null)
{
return parent;
}
} }
// record we have processed this node // move up the tree
if (!operationAlreadyProcessed.Add(childOperation)) currentCandidate = currentCandidate.Parent;
{
// 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;
}
} }
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. // 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.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
...@@ -27,6 +28,9 @@ public static bool HasErrors(this IOperation operation, Compilation compilation, ...@@ -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); 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) public static IEnumerable<IOperation> Descendants(this IOperation operation)
{ {
if (operation == null) if (operation == null)
...@@ -46,26 +50,33 @@ public static IEnumerable<IOperation> DescendantsAndSelf(this IOperation operati ...@@ -46,26 +50,33 @@ public static IEnumerable<IOperation> DescendantsAndSelf(this IOperation operati
yield return operation; yield return operation;
var stack = new Stack<IEnumerator<IOperation>>(); var stack = s_childEnumeratorStackPool.Allocate();
stack.Push(operation.Children.GetEnumerator()); stack.Push(operation.Children.GetEnumerator());
IEnumerator<IOperation> iterator; while (stack.Count > 0)
while ((iterator = stack.Pop()) != null)
{ {
var iterator = stack.Pop();
if (!iterator.MoveNext()) if (!iterator.MoveNext())
{ {
continue; continue;
} }
var current = iterator.Current; var current = iterator.Current;
yield return current;
// push current iterator back in to the stack // push current iterator back in to the stack
stack.Push(iterator); stack.Push(iterator);
// push children iterator to the stack // 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)) 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.
先完成此消息的编辑!
想要评论请 注册