Browse Source

Make AstNode freezable.

newNRvisualizers
Daniel Grunwald 14 years ago
parent
commit
f74bf908bc
  1. 87
      ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs
  2. 6
      ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs
  3. 1
      ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs
  4. 16
      ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs
  5. 30
      ICSharpCode.NRefactory.CSharp/Ast/DocumentationReference.cs
  6. 12
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs
  7. 1
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/EmptyExpression.cs
  8. 7
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs
  9. 15
      ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs
  10. 19
      ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs
  11. 1
      ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/PreProcessorDirective.cs
  12. 14
      ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeDeclaration.cs
  13. 5
      ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs
  14. 49
      ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs
  15. 12
      ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs
  16. 25
      ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs
  17. 5
      ICSharpCode.NRefactory.CSharp/Ast/Roles.cs
  18. 1
      ICSharpCode.NRefactory.CSharp/Ast/Statements/EmptyStatement.cs
  19. 9
      ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/OperatorDeclaration.cs
  20. 9
      ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs
  21. 1
      ICSharpCode.NRefactory.Tests/CSharp/ContextAction/TestRefactoringContext.cs
  22. 18
      ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs
  23. 31
      ICSharpCode.NRefactory/Role.cs

87
ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs

@ -33,12 +33,10 @@ using System.Threading; @@ -33,12 +33,10 @@ using System.Threading;
namespace ICSharpCode.NRefactory.CSharp
{
public abstract class AstNode : AbstractAnnotatable, PatternMatching.INode
public abstract class AstNode : AbstractAnnotatable, ICSharpCode.NRefactory.TypeSystem.IFreezable, PatternMatching.INode
{
/// <summary>
/// Root of an abstract syntax tree.
/// </summary>
public static readonly Role<AstNode> Root = new Role<AstNode> ("Root");
// the Root role must be available when creating the null nodes, so we can't put it in the Roles class
internal static readonly Role<AstNode> RootRole = new Role<AstNode> ("Root");
#region Null
public static readonly AstNode Null = new NullAstNode ();
@ -129,7 +127,42 @@ namespace ICSharpCode.NRefactory.CSharp @@ -129,7 +127,42 @@ namespace ICSharpCode.NRefactory.CSharp
AstNode nextSibling;
AstNode firstChild;
AstNode lastChild;
Role role = Root;
// Flags, from least significant to most significant bits:
// - Role.RoleIndexBits: role index
// - 1 bit: IsFrozen
protected uint flags = RootRole.Index;
// Derived classes may also use a few bits,
// for example Identifier uses 1 bit for IsVerbatim
const uint roleIndexMask = (1u << Role.RoleIndexBits) - 1;
const uint frozenBit = 1u << Role.RoleIndexBits;
protected const int AstNodeFlagsUsedBits = Role.RoleIndexBits + 1;
protected AstNode()
{
if (IsNull)
Freeze();
}
public bool IsFrozen {
get { return (flags & frozenBit) != 0; }
}
public void Freeze()
{
if (!IsFrozen) {
for (AstNode child = firstChild; child != null; child = child.nextSibling)
child.Freeze();
flags |= frozenBit;
}
}
protected void ThrowIfFrozen()
{
if (IsFrozen)
throw new InvalidOperationException("Cannot mutate frozen " + GetType().Name);
}
public abstract NodeType NodeType {
get;
@ -176,16 +209,24 @@ namespace ICSharpCode.NRefactory.CSharp @@ -176,16 +209,24 @@ namespace ICSharpCode.NRefactory.CSharp
}
public Role Role {
get { return role; }
get {
return Role.GetByIndex(flags & roleIndexMask);
}
set {
if (value == null)
throw new ArgumentNullException("value");
if (!value.IsValid(this))
throw new ArgumentException("This node is not valid in the new role.");
role = value;
ThrowIfFrozen();
SetRole(value);
}
}
void SetRole(Role role)
{
flags = (flags & ~roleIndexMask) | role.Index;
}
public AstNode NextSibling {
get { return nextSibling; }
}
@ -258,8 +299,9 @@ namespace ICSharpCode.NRefactory.CSharp @@ -258,8 +299,9 @@ namespace ICSharpCode.NRefactory.CSharp
{
if (role == null)
throw new ArgumentNullException ("role");
uint roleIndex = role.Index;
for (var cur = firstChild; cur != null; cur = cur.nextSibling) {
if (cur.role == role)
if ((cur.flags & roleIndexMask) == roleIndex)
return (T)cur;
}
return role.NullObject;
@ -285,10 +327,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -285,10 +327,11 @@ namespace ICSharpCode.NRefactory.CSharp
throw new ArgumentNullException ("role");
if (child == null || child.IsNull)
return;
if (this.IsNull)
throw new InvalidOperationException ("Cannot add children to null nodes");
ThrowIfFrozen();
if (child.parent != null)
throw new ArgumentException ("Node is already used in another tree.", "child");
if (child.IsFrozen)
throw new ArgumentException ("Cannot add a frozen node.", "child");
AddChildUnsafe (child, role);
}
@ -298,7 +341,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -298,7 +341,7 @@ namespace ICSharpCode.NRefactory.CSharp
void AddChildUnsafe (AstNode child, Role role)
{
child.parent = this;
child.role = role;
child.SetRole(role);
if (firstChild == null) {
lastChild = firstChild = child;
} else {
@ -319,8 +362,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -319,8 +362,11 @@ namespace ICSharpCode.NRefactory.CSharp
if (child == null || child.IsNull)
return;
ThrowIfFrozen();
if (child.parent != null)
throw new ArgumentException ("Node is already used in another tree.", "child");
if (child.IsFrozen)
throw new ArgumentException ("Cannot add a frozen node.", "child");
if (nextSibling.parent != this)
throw new ArgumentException ("NextSibling is not a child of this node.", "nextSibling");
// No need to test for "Cannot add children to null nodes",
@ -331,7 +377,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -331,7 +377,7 @@ namespace ICSharpCode.NRefactory.CSharp
void InsertChildBeforeUnsafe (AstNode nextSibling, AstNode child, Role role)
{
child.parent = this;
child.role = role;
child.SetRole(role);
child.nextSibling = nextSibling;
child.prevSibling = nextSibling.prevSibling;
@ -356,6 +402,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -356,6 +402,7 @@ namespace ICSharpCode.NRefactory.CSharp
public void Remove ()
{
if (parent != null) {
ThrowIfFrozen();
if (prevSibling != null) {
Debug.Assert (prevSibling.nextSibling == this);
prevSibling.nextSibling = nextSibling;
@ -390,10 +437,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -390,10 +437,11 @@ namespace ICSharpCode.NRefactory.CSharp
if (parent == null) {
throw new InvalidOperationException (this.IsNull ? "Cannot replace the null nodes" : "Cannot replace the root node");
}
ThrowIfFrozen();
// Because this method doesn't statically check the new node's type with the role,
// we perform a runtime test:
if (!role.IsValid (newNode)) {
throw new ArgumentException (string.Format ("The new node '{0}' is not valid in the role {1}", newNode.GetType ().Name, role.ToString ()), "newNode");
if (!this.Role.IsValid (newNode)) {
throw new ArgumentException (string.Format ("The new node '{0}' is not valid in the role {1}", newNode.GetType ().Name, this.Role.ToString ()), "newNode");
}
if (newNode.parent != null) {
// newNode is used within this tree?
@ -405,9 +453,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -405,9 +453,11 @@ namespace ICSharpCode.NRefactory.CSharp
throw new ArgumentException ("Node is already used in another tree.", "newNode");
}
}
if (newNode.IsFrozen)
throw new ArgumentException ("Cannot add a frozen node.", "newNode");
newNode.parent = parent;
newNode.role = role;
newNode.SetRole(this.Role);
newNode.prevSibling = prevSibling;
newNode.nextSibling = nextSibling;
if (parent != null) {
@ -440,7 +490,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -440,7 +490,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
AstNode oldParent = parent;
AstNode oldSuccessor = nextSibling;
Role oldRole = role;
Role oldRole = this.Role;
Remove ();
AstNode replacement = replaceFunction (this);
if (oldSuccessor != null && oldSuccessor.parent != oldParent)
@ -473,10 +523,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -473,10 +523,11 @@ namespace ICSharpCode.NRefactory.CSharp
copy.lastChild = null;
copy.prevSibling = null;
copy.nextSibling = null;
copy.flags &= ~frozenBit; // unfreeze the copy
// Then perform a deep copy:
for (AstNode cur = firstChild; cur != null; cur = cur.nextSibling) {
copy.AddChildUnsafe (cur.Clone (), cur.role);
copy.AddChildUnsafe (cur.Clone (), cur.Role);
}
// Finally, clone the annotation, if necessary

6
ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs

@ -29,14 +29,16 @@ using System.Linq; @@ -29,14 +29,16 @@ using System.Linq;
namespace ICSharpCode.NRefactory.CSharp
{
public class CSharpModifierToken : CSharpTokenNode
{
Modifiers modifier;
public Modifiers Modifier {
get { return modifier; }
set { this.modifier = value; }
set {
ThrowIfFrozen();
this.modifier = value;
}
}
protected override int TokenLength {

1
ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs

@ -103,6 +103,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -103,6 +103,7 @@ namespace ICSharpCode.NRefactory.CSharp
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
ThrowIfFrozen();
this.startLocation = startLocation;
}
#endregion

16
ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// CompilationUnit.cs
//
// Author:
@ -45,10 +45,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -45,10 +45,18 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
string fileName;
/// <summary>
/// Gets/Sets the file name of this compilation unit.
/// </summary>
public string FileName { get; set; }
public string FileName {
get { return fileName; }
set {
ThrowIfFrozen();
fileName = value;
}
}
List<Error> errors = new List<Error> ();
@ -83,7 +91,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -83,7 +91,7 @@ namespace ICSharpCode.NRefactory.CSharp
}
foreach (var child in curNode.Children) {
if (!(child is Statement || child is Expression) &&
(child.Role != Roles.TypeMemberRole || (child is TypeDeclaration && includeInnerTypes)))
(child.Role != Roles.TypeMemberRole || (child is TypeDeclaration && includeInnerTypes)))
nodeStack.Push (child);
}
}
@ -99,7 +107,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -99,7 +107,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitCompilationUnit (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitCompilationUnit (this);

30
ICSharpCode.NRefactory.CSharp/Ast/DocumentationReference.cs

@ -29,6 +29,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -29,6 +29,10 @@ namespace ICSharpCode.NRefactory.CSharp
public static readonly Role<AstType> DeclaringTypeRole = new Role<AstType>("DeclaringType", AstType.Null);
public static readonly Role<AstType> ConversionOperatorReturnTypeRole = new Role<AstType>("ConversionOperatorReturnType", AstType.Null);
EntityType entityType;
OperatorType operatorType;
bool hasParameterList;
/// <summary>
/// Gets/Sets the entity type.
/// Possible values are:
@ -37,18 +41,36 @@ namespace ICSharpCode.NRefactory.CSharp @@ -37,18 +41,36 @@ namespace ICSharpCode.NRefactory.CSharp
/// <c>EntityType.TypeDefinition</c> for references to primitive types,
/// and <c>EntityType.None</c> for everything else.
/// </summary>
public EntityType EntityType { get; set; }
public EntityType EntityType {
get { return entityType; }
set {
ThrowIfFrozen();
entityType = value;
}
}
/// <summary>
/// Gets/Sets the operator type.
/// This property is only used when EntityType==Operator.
/// </summary>
public OperatorType OperatorType { get; set; }
public OperatorType OperatorType {
get { return operatorType; }
set {
ThrowIfFrozen();
operatorType = value;
}
}
/// <summary>
/// Gets/Sets whether a parameter list was provided.
/// </summary>
public bool HasParameterList { get; set; }
public bool HasParameterList {
get { return hasParameterList; }
set {
ThrowIfFrozen();
hasParameterList = value;
}
}
public override NodeType NodeType {
get { return NodeType.Unknown; }
@ -113,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -113,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitDocumentationReference (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitDocumentationReference (this);

12
ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs

@ -37,11 +37,19 @@ namespace ICSharpCode.NRefactory.CSharp @@ -37,11 +37,19 @@ namespace ICSharpCode.NRefactory.CSharp
public readonly static TokenRole DelegateKeywordRole = new TokenRole ("delegate");
public readonly static TokenRole AsyncModifierRole = LambdaExpression.AsyncModifierRole;
public bool IsAsync { get; set; }
bool isAsync;
public bool IsAsync {
get { return isAsync; }
set { ThrowIfFrozen(); isAsync = value; }
}
// used to tell the difference between delegate {} and delegate () {}
bool hasParameterList;
public bool HasParameterList {
get; set;
get { return hasParameterList; }
set { ThrowIfFrozen(); hasParameterList = value; }
}
public CSharpTokenNode DelegateToken {

1
ICSharpCode.NRefactory.CSharp/Ast/Expressions/EmptyExpression.cs

@ -58,6 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -58,6 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
ThrowIfFrozen();
this.location = startLocation;
}
#endregion

7
ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs

@ -37,7 +37,12 @@ namespace ICSharpCode.NRefactory.CSharp @@ -37,7 +37,12 @@ namespace ICSharpCode.NRefactory.CSharp
public readonly static TokenRole ArrowRole = new TokenRole ("=>");
public static readonly Role<AstNode> BodyRole = new Role<AstNode>("Body", AstNode.Null);
public bool IsAsync { get; set; }
bool isAsync;
public bool IsAsync {
get { return isAsync; }
set { ThrowIfFrozen(); isAsync = value; }
}
public AstNodeCollection<ParameterDeclaration> Parameters {
get { return GetChildrenByRole (Roles.Parameter); }

15
ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs

@ -47,14 +47,21 @@ namespace ICSharpCode.NRefactory.CSharp @@ -47,14 +47,21 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
object value;
public object Value {
get;
set;
get { return this.value; }
set {
ThrowIfFrozen();
this.value = value;
}
}
public string LiteralValue {
get {
return literalValue;
get { return literalValue; }
set {
ThrowIfFrozen();
literalValue = value;
}
}

19
ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs

@ -58,19 +58,25 @@ namespace ICSharpCode.NRefactory.CSharp @@ -58,19 +58,25 @@ namespace ICSharpCode.NRefactory.CSharp
}
}
CommentType commentType;
public CommentType CommentType {
get;
set;
get { return commentType; }
set { ThrowIfFrozen(); commentType = value; }
}
bool startsLine;
public bool StartsLine {
get;
set;
get { return startsLine; }
set { ThrowIfFrozen(); startsLine = value; }
}
string content;
public string Content {
get;
set;
get { return content; }
set { ThrowIfFrozen(); content = value; }
}
TextLocation startLocation;
@ -103,6 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -103,6 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
ThrowIfFrozen();
int lineDelta = startLocation.Line - this.startLocation.Line;
endLocation = new TextLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column);
this.startLocation = startLocation;

1
ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/PreProcessorDirective.cs

@ -96,6 +96,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -96,6 +96,7 @@ namespace ICSharpCode.NRefactory.CSharp
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
ThrowIfFrozen();
int lineDelta = startLocation.Line - this.startLocation.Line;
endLocation = new TextLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column);
this.startLocation = startLocation;

14
ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeDeclaration.cs

@ -114,17 +114,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -114,17 +114,17 @@ namespace ICSharpCode.NRefactory.CSharp
public static TypeDeclaration Create(ClassType type)
{
switch (type) {
case ICSharpCode.NRefactory.CSharp.ClassType.Class:
switch (type) {
case ICSharpCode.NRefactory.CSharp.ClassType.Class:
return new Class ();
case ICSharpCode.NRefactory.CSharp.ClassType.Struct:
case ICSharpCode.NRefactory.CSharp.ClassType.Struct:
return new Struct ();
case ICSharpCode.NRefactory.CSharp.ClassType.Interface:
case ICSharpCode.NRefactory.CSharp.ClassType.Interface:
return new Interface ();
case ICSharpCode.NRefactory.CSharp.ClassType.Enum:
case ICSharpCode.NRefactory.CSharp.ClassType.Enum:
return new Enum ();
default:
throw new System.ArgumentOutOfRangeException();
default:
throw new System.ArgumentOutOfRangeException();
}
}

5
ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs

@ -42,8 +42,11 @@ namespace ICSharpCode.NRefactory.CSharp @@ -42,8 +42,11 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildrenByRole (AttributeRole); }
}
VarianceModifier variance;
public VarianceModifier Variance {
get; set;
get { return variance; }
set { ThrowIfFrozen(); variance = value; }
}
public CSharpTokenNode VarianceToken {

49
ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
//
// Identifier.cs
//
//
// Author:
// Mike Krüger <mkrueger@novell.com>
//
@ -42,7 +42,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -42,7 +42,7 @@ namespace ICSharpCode.NRefactory.CSharp
public override void AcceptVisitor (IAstVisitor visitor)
{
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return default (T);
@ -68,9 +68,10 @@ namespace ICSharpCode.NRefactory.CSharp @@ -68,9 +68,10 @@ namespace ICSharpCode.NRefactory.CSharp
string name;
public string Name {
get { return this.name; }
set {
set {
if (value == null)
throw new ArgumentNullException("value");
ThrowIfFrozen();
this.name = value;
}
}
@ -80,25 +81,34 @@ namespace ICSharpCode.NRefactory.CSharp @@ -80,25 +81,34 @@ namespace ICSharpCode.NRefactory.CSharp
get {
return startLocation;
}
}
public virtual bool IsVerbatim {
const uint verbatimBit = 1u << AstNodeFlagsUsedBits;
public bool IsVerbatim {
get {
return false;
return (flags & verbatimBit) != 0;
}
set {
ThrowIfFrozen();
if (value)
flags |= verbatimBit;
else
flags &= ~verbatimBit;
}
}
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
ThrowIfFrozen();
this.startLocation = startLocation;
}
#endregion
public override TextLocation EndLocation {
get {
return new TextLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length);
return new TextLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + (IsVerbatim ? 1 : 0));
}
}
@ -125,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -125,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp
if (string.IsNullOrEmpty(name))
return Identifier.Null;
if (name[0] == '@')
return new VerbatimIdentifier(name.Substring (1), location);
return new Identifier (name.Substring (1), location) { IsVerbatim = true };
else
return new Identifier (name, location);
}
@ -136,7 +146,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -136,7 +146,7 @@ namespace ICSharpCode.NRefactory.CSharp
return Identifier.Null;
if (isVerbatim)
return new VerbatimIdentifier (name, location);
return new Identifier (name, location) { IsVerbatim = true };
return new Identifier (name, location);
}
@ -144,7 +154,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -144,7 +154,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitIdentifier (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitIdentifier (this);
@ -160,24 +170,5 @@ namespace ICSharpCode.NRefactory.CSharp @@ -160,24 +170,5 @@ namespace ICSharpCode.NRefactory.CSharp
Identifier o = other as Identifier;
return o != null && !o.IsNull && MatchString(this.Name, o.Name);
}
class VerbatimIdentifier : Identifier
{
public override TextLocation EndLocation {
get {
return new TextLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + 1); // @"..."
}
}
public override bool IsVerbatim {
get {
return true;
}
}
public VerbatimIdentifier(string name, TextLocation location) : base (name, location)
{
}
}
}
}

12
ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs

@ -37,7 +37,15 @@ namespace ICSharpCode.NRefactory.CSharp @@ -37,7 +37,15 @@ namespace ICSharpCode.NRefactory.CSharp
{
public static readonly Role<AstType> TargetRole = new Role<AstType>("Target", AstType.Null);
public bool IsDoubleColon { get; set; }
bool isDoubleColon;
public bool IsDoubleColon {
get { return isDoubleColon; }
set {
ThrowIfFrozen();
isDoubleColon = value;
}
}
public AstType Target {
get { return GetChildByRole(TargetRole); }
@ -93,7 +101,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -93,7 +101,7 @@ namespace ICSharpCode.NRefactory.CSharp
{
visitor.VisitMemberType (this);
}
public override T AcceptVisitor<T> (IAstVisitor<T> visitor)
{
return visitor.VisitMemberType (this);

25
ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs

@ -34,8 +34,18 @@ namespace ICSharpCode.NRefactory.CSharp @@ -34,8 +34,18 @@ namespace ICSharpCode.NRefactory.CSharp
{
public class PrimitiveType : AstType, IRelocatable
{
public string Keyword { get; set; }
public TextLocation Location { get; set; }
TextLocation location;
string keyword = string.Empty;
public string Keyword {
get { return keyword; }
set {
if (value == null)
throw new ArgumentNullException();
ThrowIfFrozen();
keyword = value;
}
}
public KnownTypeCode KnownTypeCode {
get { return GetTypeCodeForPrimitiveType(this.Keyword); }
@ -53,17 +63,17 @@ namespace ICSharpCode.NRefactory.CSharp @@ -53,17 +63,17 @@ namespace ICSharpCode.NRefactory.CSharp
public PrimitiveType(string keyword, TextLocation location)
{
this.Keyword = keyword;
this.Location = location;
this.location = location;
}
public override TextLocation StartLocation {
get {
return Location;
return location;
}
}
public override TextLocation EndLocation {
get {
return new TextLocation (Location.Line, Location.Column + (Keyword != null ? Keyword.Length : 0));
return new TextLocation (location.Line, location.Column + keyword.Length);
}
}
@ -71,7 +81,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -71,7 +81,8 @@ namespace ICSharpCode.NRefactory.CSharp
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
this.Location = startLocation;
ThrowIfFrozen();
this.location = startLocation;
}
#endregion
@ -98,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -98,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp
public override string ToString()
{
return Keyword ?? base.ToString();
return Keyword;
}
public override ITypeReference ToTypeReference(SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type)

5
ICSharpCode.NRefactory.CSharp/Ast/Roles.cs

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
//
//
// Roles.cs
//
// Author:
@ -30,7 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp @@ -30,7 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp
{
public static class Roles
{
public static readonly Role<AstNode> Root = AstNode.RootRole;
// some pre defined constants for common roles
public static readonly Role<Identifier> Identifier = new Role<Identifier> ("Identifier", CSharp.Identifier.Null);
public static readonly Role<BlockStatement> Body = new Role<BlockStatement> ("Body", CSharp.BlockStatement.Null);

1
ICSharpCode.NRefactory.CSharp/Ast/Statements/EmptyStatement.cs

@ -51,6 +51,7 @@ namespace ICSharpCode.NRefactory.CSharp @@ -51,6 +51,7 @@ namespace ICSharpCode.NRefactory.CSharp
#region IRelocationable implementation
void IRelocatable.SetStartLocation (TextLocation startLocation)
{
ThrowIfFrozen();
this.Location = startLocation;
}
#endregion

9
ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/OperatorDeclaration.cs

@ -109,9 +109,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -109,9 +109,14 @@ namespace ICSharpCode.NRefactory.CSharp
get { return EntityType.Operator; }
}
OperatorType operatorType;
public OperatorType OperatorType {
get;
set;
get { return operatorType; }
set {
ThrowIfFrozen();
operatorType = value;
}
}
public CSharpTokenNode OperatorToken {

9
ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs

@ -56,9 +56,14 @@ namespace ICSharpCode.NRefactory.CSharp @@ -56,9 +56,14 @@ namespace ICSharpCode.NRefactory.CSharp
get { return GetChildrenByRole (AttributeRole); }
}
ParameterModifier parameterModifier;
public ParameterModifier ParameterModifier {
get;
set;
get { return parameterModifier; }
set {
ThrowIfFrozen();
parameterModifier = value;
}
}
public AstType Type {

1
ICSharpCode.NRefactory.Tests/CSharp/ContextAction/TestRefactoringContext.cs

@ -137,6 +137,7 @@ namespace ICSharpCode.NRefactory.CSharp.ContextActions @@ -137,6 +137,7 @@ namespace ICSharpCode.NRefactory.CSharp.ContextActions
if (parser.HasErrors)
parser.ErrorPrinter.Errors.ForEach (e => Console.WriteLine (e.Message));
Assert.IsFalse (parser.HasErrors, "File contains parsing errors.");
unit.Freeze();
var parsedFile = unit.ToTypeSystem();
IProjectContent pc = new CSharpProjectContent();

18
ICSharpCode.NRefactory.Tests/CSharp/Resolver/FindReferencesTest.cs

@ -129,5 +129,23 @@ class Test { @@ -129,5 +129,23 @@ class Test {
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 3 && r is MethodDeclaration));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 8 && r is ForeachStatement));
}
[Test]
public void FindReferencesForOpImplicitInLocalVariableInitialization()
{
Init(@"using System;
class Test {
static void T() {
int x = new Test();
}
public static implicit operator int(Test x) { return 0; }
}");
var test = compilation.MainAssembly.TopLevelTypeDefinitions.Single(t => t.Name == "Test");
var opImplicit = test.Methods.Single(m => m.Name == "op_Implicit");
var actual = FindReferences(opImplicit).ToList();
Assert.AreEqual(2, actual.Count);
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 4 && r is ObjectCreateExpression));
Assert.IsTrue(actual.Any(r => r.StartLocation.Line == 6 && r is OperatorDeclaration));
}
}
}

31
ICSharpCode.NRefactory/Role.cs

@ -17,6 +17,7 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Threading;
namespace ICSharpCode.NRefactory
{
@ -25,12 +26,40 @@ namespace ICSharpCode.NRefactory @@ -25,12 +26,40 @@ namespace ICSharpCode.NRefactory
/// </summary>
public abstract class Role
{
internal Role() {} // don't allow NRefactory consumers to derive from Role
public const int RoleIndexBits = 9;
static readonly Role[] roles = new Role[1 << RoleIndexBits];
static int nextRoleIndex = 0;
readonly uint index;
[CLSCompliant(false)]
public uint Index {
get { return index; }
}
// don't allow NRefactory consumers to derive from Role
internal Role()
{
this.index = (uint)Interlocked.Increment(ref nextRoleIndex);
if (this.index >= roles.Length)
throw new InvalidOperationException("");
roles[this.index] = this;
}
/// <summary>
/// Gets whether the specified node is valid in this role.
/// </summary>
public abstract bool IsValid(object node);
/// <summary>
/// Gets the role with the specified index.
/// </summary>
[CLSCompliant(false)]
public static Role GetByIndex(uint index)
{
return roles[index];
}
}
/// <summary>

Loading…
Cancel
Save