diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs index 2dab5a5ad9..dafcdc2533 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs @@ -157,6 +157,15 @@ namespace ICSharpCode.NRefactory.CSharp } } + /// + /// Gets all descendants of this node (including this node itself). + /// + public IEnumerable DescendantsAndSelf { + get { + return Utils.TreeTraversal.PreOrder(this, n => n.Children); + } + } + /// /// Gets the first child with the specified role. /// Returns the role's null object if the child is not found. diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs index a35204e3cd..5582b9012e 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs @@ -53,6 +53,30 @@ namespace ICSharpCode.NRefactory.CSharp return new TypeReferenceExpression { Type = this }.Member(memberName); } + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, params Expression[] arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable typeArguments, IEnumerable arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, typeArguments, arguments); + } + public static AstType Create(Type type) { switch (Type.GetTypeCode(type)) { diff --git a/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs b/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs index ec0a85705c..3fc7fa2912 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs @@ -72,7 +72,10 @@ namespace ICSharpCode.NRefactory.CSharp new KeyValuePair(Modifiers.Volatile, "volatile".Length), new KeyValuePair(Modifiers.Extern, "extern".Length), new KeyValuePair(Modifiers.Partial, "partial".Length), - new KeyValuePair(Modifiers.Const, "const".Length) + new KeyValuePair(Modifiers.Const, "const".Length), + + // even though it's used for patterns only, it needs to be in this table to be usable in the AST + new KeyValuePair(Modifiers.Any, "any".Length) }; public static IEnumerable AllModifiers { diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs b/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs index a05a817aaf..700a3c04d1 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs @@ -66,4 +66,9 @@ namespace ICSharpCode.NRefactory.CSharp //Final = 0x400000, //Literal = 0x800000, VisibilityMask = Private | Internal | Protected | Public, + + /// + /// Special value used to match any modifiers during pattern matching. + /// + Any = unchecked((int)0x80000000) }} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs index 23f5c2ea58..ed2122d19a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs @@ -34,6 +34,11 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching return p != null ? new TypePlaceholder(p) : null; } + public AstType ToType() + { + return new TypePlaceholder(this); + } + public static implicit operator Expression(Pattern p) { return p != null ? new ExpressionPlaceholder(p) : null; @@ -64,6 +69,11 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching return p != null ? new VariablePlaceholder(p) : null; } + public static implicit operator AttributeSection(Pattern p) + { + return p != null ? new AttributeSectionPlaceholder(p) : null; + } + // Make debugging easier by giving Patterns a ToString() implementation public override string ToString() { diff --git a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs index f68feb443d..67987595f9 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs @@ -152,4 +152,33 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching return child.DoMatchCollection(role, pos, match, backtrackingStack); } } + + sealed class AttributeSectionPlaceholder : AttributeSection + { + readonly AstNode child; + + public AttributeSectionPlaceholder(AstNode child) + { + this.child = child; + } + + public override NodeType NodeType { + get { return NodeType.Placeholder; } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, child, data); + } + + protected internal override bool DoMatch(AstNode other, Match match) + { + return child.DoMatch(other, match); + } + + internal override bool DoMatchCollection(Role role, AstNode pos, Match match, Stack backtrackingStack) + { + return child.DoMatchCollection(role, pos, match, backtrackingStack); + } + } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs index c487032ebc..cc5651d871 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs @@ -56,8 +56,12 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Body); } set { SetChildByRole (Roles.Body, value); } } - - public override S AcceptVisitor (IAstVisitor visitor, T data) + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) { return visitor.VisitAccessor (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs index 41eec380d1..af5e584dc4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs @@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp protected bool MatchAttributesAndModifiers(AttributedNode o, PatternMatching.Match match) { - return this.Modifiers == o.Modifiers && this.Attributes.DoMatch(o.Attributes, match); + return (this.Modifiers == Modifiers.Any || this.Modifiers == o.Modifiers) && this.Attributes.DoMatch(o.Attributes, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index da02c47d5f..bcab463d7a 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -202,8 +202,20 @@ namespace ICSharpCode.NRefactory.CSharp { WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); } + #endif - + + void WriteCommaSeparatedListInBrackets(IEnumerable list, bool spaceWithin) + { + WriteToken("[", AstNode.Roles.LBracket); + if (list.Any()) { + Space(spaceWithin); + WriteCommaSeparatedList(list.SafeCast()); + Space(spaceWithin); + } + WriteToken("]", AstNode.Roles.RBracket); + } + void WriteCommaSeparatedListInBrackets(IEnumerable list) { WriteToken("[", AstNode.Roles.LBracket); @@ -1815,7 +1827,7 @@ namespace ICSharpCode.NRefactory.CSharp WritePrivateImplementationType(indexerDeclaration.PrivateImplementationType); WriteKeyword("this"); Space(policy.BeforeMethodDeclarationParentheses); - WriteCommaSeparatedListInParenthesis(indexerDeclaration.Parameters, policy.WithinMethodDeclarationParentheses); + WriteCommaSeparatedListInBrackets(indexerDeclaration.Parameters, policy.WithinMethodDeclarationParentheses); OpenBrace(policy.PropertyBraceStyle); // output get/set in their original order foreach (AstNode node in indexerDeclaration.Children) {