mirror of https://github.com/icsharpcode/ILSpy.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
73 lines
2.5 KiB
73 lines
2.5 KiB
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) |
|
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) |
|
|
|
using System; |
|
using System.Collections.Generic; |
|
using System.Linq; |
|
using ICSharpCode.NRefactory.VB.Dom; |
|
|
|
namespace ICSharpCode.NRefactory.VB.Visitors |
|
{ |
|
/// <summary> |
|
/// Sets StartLocation and EndLocation (region) of every node to union of regions of its children. |
|
/// Parsers don't do this by default: |
|
/// e.g. "a.Foo()" is InvocationExpression, its region includes only the "()" and it has a child MemberReferenceExpression, with region ".Foo". |
|
/// </summary> |
|
public class SetRegionInclusionVisitor : NodeTrackingDomVisitor |
|
{ |
|
Stack<INode> parentNodes = new Stack<INode>(); |
|
|
|
public SetRegionInclusionVisitor() |
|
{ |
|
parentNodes.Push(null); |
|
} |
|
|
|
protected override void BeginVisit(INode node) |
|
{ |
|
base.BeginVisit(node); |
|
|
|
// Only push nodes on the stack which have valid position information. |
|
if (node != null && |
|
node.StartLocation.X >= 1 && node.StartLocation.Y >= 1 && |
|
node.EndLocation.X >= 1 && node.EndLocation.Y >= 1) { |
|
|
|
if (node is PropertyDeclaration) { |
|
// PropertyDeclaration has correctly set BodyStart and BodyEnd by the parser, |
|
// but it has no subnode "body", just 2 children GetRegion and SetRegion which don't span |
|
// the whole (BodyStart, BodyEnd) region => We have to handle PropertyDeclaration as a special case. |
|
node.EndLocation = ((PropertyDeclaration)node).BodyEnd; |
|
} |
|
|
|
this.parentNodes.Push(node); |
|
} |
|
} |
|
|
|
protected override void EndVisit(INode node) |
|
{ |
|
base.EndVisit(node); |
|
|
|
// Only remove those nodes which have actually been pushed before. |
|
if (this.parentNodes.Count > 0 && INode.ReferenceEquals(this.parentNodes.Peek(), node)) { |
|
// remove this node |
|
this.parentNodes.Pop(); |
|
// fix region of parent |
|
var parent = this.parentNodes.Peek(); |
|
if (parent == null) |
|
return; |
|
if (node.StartLocation < parent.StartLocation) |
|
parent.StartLocation = node.StartLocation; |
|
if (node.EndLocation > parent.EndLocation) |
|
parent.EndLocation = node.EndLocation; |
|
} |
|
|
|
// Block statement as a special case - we want it without the '{' and '}' |
|
if (node is BlockStatement) { |
|
var firstSatement = node.Children.FirstOrDefault(); |
|
if (firstSatement != null) { |
|
node.StartLocation = firstSatement.StartLocation; |
|
node.EndLocation = node.Children.Last().EndLocation; |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|