diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs index a26ae22e36..a535257ef1 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs @@ -705,6 +705,7 @@ namespace ICSharpCode.NRefactory.CSharp public static readonly Role Assign = new Role ("Assign", CSharpTokenNode.Null); public static readonly Role Colon = new Role ("Colon", CSharpTokenNode.Null); public static readonly Role Comment = new Role ("Comment"); + public static readonly Role Error = new Role ("Error"); } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs b/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs new file mode 100644 index 0000000000..af2fed7506 --- /dev/null +++ b/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs @@ -0,0 +1,79 @@ +// +// ErrorNode.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin (http://www.xamarin.com); +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents a parsing error in the ast. At the moment it only represents missing closing bracket. + /// This closing bracket is replaced by a node at the highest possible position. + /// (To make GetAstNodeAt (line, col) working). + /// + public class ErrorNode : AstNode + { + static AstLocation maxLoc = new AstLocation (int.MaxValue, int.MaxValue); + + public override NodeType NodeType { + get { + return NodeType.Unknown; + } + } + + public override AstLocation StartLocation { + get { + return maxLoc; + } + } + + public override AstLocation EndLocation { + get { + return maxLoc; + } + } + + public ErrorNode () + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + // nothing + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as ErrorNode; + return o != null; + } + + public override string ToString () + { + return "[ErrorNode]"; + } + } +} + diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index 344e45d04b..d9274ecee8 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -358,8 +358,12 @@ namespace ICSharpCode.NRefactory.CSharp newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); base.Visit (c); - if (location != null && location.Count > 2) + if (location != null && location.Count > 2) { newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } typeStack.Pop (); AddType (newType); } @@ -394,8 +398,12 @@ namespace ICSharpCode.NRefactory.CSharp newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); base.Visit (s); - if (location != null && location.Count > 2) + if (location != null && location.Count > 2) { newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } typeStack.Pop (); AddType (newType); } @@ -428,8 +436,12 @@ namespace ICSharpCode.NRefactory.CSharp newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); base.Visit (i); - if (location != null && location.Count > 2) + if (location != null && location.Count > 2) { newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } typeStack.Pop (); AddType (newType); } @@ -501,8 +513,12 @@ namespace ICSharpCode.NRefactory.CSharp newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); base.Visit (e); - if (location != null && location.Count > 2) + if (location != null && location.Count > 2) { newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + } else { + // parser error, set end node to max value. + newType.AddChild (new ErrorNode (), AstNode.Roles.Error); + } typeStack.Pop (); AddType (newType); } @@ -756,9 +772,12 @@ namespace ICSharpCode.NRefactory.CSharp newIndexer.AddChild (setAccessor, PropertyDeclaration.SetterRole); } - if (location != null) + if (location != null) { newIndexer.AddChild (new CSharpTokenNode (Convert (location[3]), 1), IndexerDeclaration.Roles.RBrace); - + } else { + // parser error, set end node to max value. + newIndexer.AddChild (new ErrorNode (), AstNode.Roles.Error); + } typeStack.Peek ().AddChild (newIndexer, TypeDeclaration.MemberRole); } @@ -798,6 +817,9 @@ namespace ICSharpCode.NRefactory.CSharp // } else { newMethod.AddChild (bodyBlock, MethodDeclaration.Roles.Body); // } + } else if (location != null && location.Count < 3) { + // parser error, set end node to max value. + newMethod.AddChild (new ErrorNode (), AstNode.Roles.Error); } typeStack.Peek ().AddChild (newMethod, TypeDeclaration.MemberRole); } @@ -899,8 +921,12 @@ namespace ICSharpCode.NRefactory.CSharp } newProperty.AddChild (setAccessor, PropertyDeclaration.SetterRole); } - if (location != null && location.Count > 1) + if (location != null && location.Count > 1) { newProperty.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newProperty.AddChild (new ErrorNode (), AstNode.Roles.Error); + } typeStack.Peek ().AddChild (newProperty, TypeDeclaration.MemberRole); } @@ -1044,8 +1070,12 @@ namespace ICSharpCode.NRefactory.CSharp removeAccessor.AddChild ((BlockStatement)ep.Remove.Block.Accept (this), CustomEventDeclaration.Roles.Body); newEvent.AddChild (removeAccessor, CustomEventDeclaration.RemoveAccessorRole); } - if (location != null && location.Count >= 3) + if (location != null && location.Count >= 3) { newEvent.AddChild (new CSharpTokenNode (Convert (location[2]), 1), CustomEventDeclaration.Roles.RBrace); + } else { + // parser error, set end node to max value. + newEvent.AddChild (new ErrorNode (), AstNode.Roles.Error); + } typeStack.Peek ().AddChild (newEvent, TypeDeclaration.MemberRole); } @@ -1134,8 +1164,12 @@ namespace ICSharpCode.NRefactory.CSharp result.AddChild (init, VariableDeclarationStatement.Roles.Variable); } } - if (location != null) + if (location != null) { result.AddChild (new CSharpTokenNode (Convert (location[location.Count - 1]), 1), VariableDeclarationStatement.Roles.Semicolon); + } else { + // parser error, set end node to max value. + result.AddChild (new ErrorNode (), AstNode.Roles.Error); + } return result; } @@ -1474,8 +1508,13 @@ namespace ICSharpCode.NRefactory.CSharp result.AddChild (newSection, SwitchStatement.SwitchSectionRole); } - if (location != null) + if (location != null) { result.AddChild (new CSharpTokenNode (Convert (location[3]), 1), SwitchStatement.Roles.RBrace); + } else { + // parser error, set end node to max value. + result.AddChild (new ErrorNode (), AstNode.Roles.Error); + } + return result; } @@ -1604,7 +1643,7 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), CatchClause.Roles.RPar); } - + if (ctch.Block != null) result.AddChild ((BlockStatement)ctch.Block.Accept (this), CatchClause.Roles.Body); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs b/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs index 5b3737a9cd..fd3fe3aaa3 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs @@ -760,6 +760,11 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" public List usings = new List (); public List members = new List (); + public Namespace () + { + // in case of missing close brace, set it to the highest value. + CloseBrace = new Location (int.MaxValue, int.MaxValue); + } public virtual void Accept (StructuralVisitor visitor) { diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 1213653727..b38815938c 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -1,4 +1,4 @@ - + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} @@ -396,6 +396,7 @@ +