From 39fcd7d72f73d386455d00d63446601c99eafb83 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Thu, 3 Mar 2011 00:00:22 +0100 Subject: [PATCH] Squashed 'NRefactory/' changes from 2200240..a92606c a92606c Some improvements to output visitor. 136fd88 Fix some parser issues. 41b4385 Port NRefactory to .NET 3.5. 3b6fe6f Adjust resolver to AST changes and disable failing unit tests. 93e9d1e Use implicit conversion operator to convert from Pattern to AST nodes. b37ea77 Re-enabled the unit tests that were commented out. defd426 AST bugfixes. 60d4fe9 Add pattern matching for query expressions. Pattern matching should now work for the complete C# AST. b51f5a6 Add pattern matching for MemberDeclarations. git-subtree-dir: NRefactory git-subtree-split: a92606cb97ef6739d59b30a278d017cf64677f88 --- .../CSharp/AstStructureTests.cs | 15 + .../AliasReferenceExpressionTests.cs | 38 ++- .../Parser/Expression/AnonymousMethodTests.cs | 1 + .../ArrayObjectCreateExpressionTests.cs | 52 ++-- .../Parser/Expression/CastExpressionTests.cs | 151 +++++----- .../Expression/DefaultValueExpressionTests.cs | 60 ++-- .../Expression/IdentifierExpressionTests.cs | 28 +- .../Expression/InvocationExpressionTests.cs | 177 ++++++------ .../Parser/Expression/IsExpressionTests.cs | 15 +- .../Expression/LambdaExpressionTests.cs | 117 ++++---- .../MemberReferenceExpressionTests.cs | 97 ++++--- .../PointerReferenceExpressionTests.cs | 18 +- .../Parser/Expression/QueryExpressionTests.cs | 232 +++++++++++---- .../Expression/SizeOfExpressionTests.cs | 4 +- .../Expression/StackAllocExpressionTests.cs | 9 +- .../Expression/TypeOfExpressionTests.cs | 97 ++++--- .../UnaryOperatorExpressionTests.cs | 6 +- .../GeneralScope/DelegateDeclarationTests.cs | 68 ++--- .../GeneralScope/TypeDeclarationTests.cs | 198 +++++++------ .../GeneralScope/UsingDeclarationTests.cs | 2 +- .../CSharp/Parser/ParseUtil.cs | 41 ++- .../Parser/Statements/FixedStatementTests.cs | 15 +- .../Parser/Statements/ForStatementTests.cs | 20 +- .../Statements/TryCatchStatementTests.cs | 56 +++- .../Parser/Statements/YieldStatementTests.cs | 3 +- .../TypeMembers/EventDeclarationTests.cs | 113 ++++---- .../TypeMembers/FieldDeclarationTests.cs | 62 +++- .../TypeMembers/IndexerDeclarationTests.cs | 37 ++- .../TypeMembers/MethodDeclarationTests.cs | 266 ++++++++++-------- .../TypeMembers/OperatorDeclarationTests.cs | 16 +- .../TypeMembers/PropertyDeclarationTests.cs | 10 +- .../CSharp/Resolver/InvocationTests.cs | 2 +- .../CSharp/Resolver/NameLookupTests.cs | 10 +- .../CSharp/Resolver/UnsafeCodeTests.cs | 2 +- .../ICSharpCode.NRefactory.Tests.csproj | 1 + .../ICSharpCode.NRefactory.VB.Tests.csproj | 1 + .../ICSharpCode.NRefactory.VB.csproj | 1 + .../CSharp/Ast/AstLocation.cs | 6 +- ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs | 5 + .../CSharp/Ast/AstNodeCollection.cs | 18 +- ICSharpCode.NRefactory/CSharp/Ast/AstType.cs | 2 +- .../CSharp/Ast/CSharpModifierToken.cs | 6 + .../CSharp/Ast/CSharpTokenNode.cs | 2 +- .../Ast/Expressions/ArrayCreateExpression.cs | 2 +- .../CSharp/Ast/Expressions/QueryExpression.cs | 61 +++- .../Ast/GeneralScope/AttributeSection.cs | 9 + .../CSharp/Ast/GeneralScope/Constraint.cs | 5 +- .../Ast/GeneralScope/DelegateDeclaration.cs | 19 +- .../Ast/GeneralScope/TypeDeclaration.cs | 9 + .../GeneralScope/TypeParameterDeclaration.cs | 7 +- .../CSharp/Ast/Identifier.cs | 7 +- .../CSharp/Ast/MemberType.cs | 2 +- .../CSharp/Ast/PatternMatching/Pattern.cs | 25 +- .../CSharp/Ast/PatternMatching/Placeholder.cs | 68 +++-- .../CSharp/Ast/SimpleType.cs | 2 +- .../CSharp/Ast/Statements/BlockStatement.cs | 2 +- .../CSharp/Ast/Statements/FixedStatement.cs | 2 +- .../CSharp/Ast/TypeMembers/Accessor.cs | 3 +- .../CSharp/Ast/TypeMembers/AttributedNode.cs | 4 +- .../Ast/TypeMembers/ConstructorDeclaration.cs | 14 +- .../Ast/TypeMembers/DestructorDeclaration.cs | 8 +- .../Ast/TypeMembers/EnumMemberDeclaration.cs | 11 +- .../Ast/TypeMembers/EventDeclaration.cs | 25 +- .../Ast/TypeMembers/FieldDeclaration.cs | 22 +- .../Ast/TypeMembers/IndexerDeclaration.cs | 34 ++- .../Ast/TypeMembers/MemberDeclaration.cs | 6 + .../Ast/TypeMembers/MethodDeclaration.cs | 14 +- .../Ast/TypeMembers/OperatorDeclaration.cs | 27 +- .../Ast/TypeMembers/ParameterDeclaration.cs | 14 +- .../Ast/TypeMembers/PropertyDeclaration.cs | 11 +- .../CSharp/OutputVisitor/OutputVisitor.cs | 77 +++-- .../CSharp/Parser/CSharpParser.cs | 46 +-- .../CSharp/Parser/TypeSystemConvertVisitor.cs | 83 +++--- .../CSharp/Resolver/CSharpResolver.cs | 28 +- .../CSharp/Resolver/MemberLookup.cs | 10 +- .../MemberTypeOrNamespaceReference.cs | 2 +- .../CSharp/Resolver/OverloadResolution.cs | 2 +- .../CSharp/Resolver/ResolveVisitor.cs | 49 ++-- .../SimpleTypeOrNamespaceReference.cs | 2 +- .../CSharp/Resolver/TypeInference.cs | 2 +- .../ICSharpCode.NRefactory.csproj | 17 +- .../TypeSystem/CecilLoader.cs | 2 +- .../TypeSystem/ExtensionMethods.cs | 8 +- .../TypeSystem/IAttribute.cs | 4 + .../TypeSystem/IConstantValue.cs | 4 + ICSharpCode.NRefactory/TypeSystem/IEntity.cs | 4 + .../IExplicitInterfaceImplementation.cs | 4 + ICSharpCode.NRefactory/TypeSystem/IField.cs | 4 + .../TypeSystem/IFreezable.cs | 4 + .../TypeSystem/IInterningProvider.cs | 4 + ICSharpCode.NRefactory/TypeSystem/IMember.cs | 4 + ICSharpCode.NRefactory/TypeSystem/IMethod.cs | 11 +- .../TypeSystem/INamedElement.cs | 4 + .../TypeSystem/IParameter.cs | 4 + .../TypeSystem/IParameterizedMember.cs | 4 + .../TypeSystem/IProjectContent.cs | 4 + .../TypeSystem/ISupportsInterning.cs | 4 + ICSharpCode.NRefactory/TypeSystem/IType.cs | 4 + .../TypeSystem/ITypeDefinition.cs | 4 + .../TypeSystem/ITypeParameter.cs | 4 + .../TypeSystem/ITypeReference.cs | 4 + .../TypeSystem/ITypeResolveContext.cs | 4 + .../TypeSystem/IVariable.cs | 4 + .../TypeSystem/Implementation/AbstractType.cs | 4 +- .../Implementation/DefaultParameter.cs | 9 - .../Implementation/DefaultTypeDefinition.cs | 23 +- .../Implementation/SimpleInterningProvider.cs | 24 +- .../Utils/DotNet35Compat.cs | 58 ++++ NRefactory.sln | 8 +- README | 25 +- VBDomGenerator/VBDomGenerator.csproj | 1 + doc/TODO | 33 ++- 112 files changed, 2055 insertions(+), 1038 deletions(-) create mode 100644 ICSharpCode.NRefactory/Utils/DotNet35Compat.cs diff --git a/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs index 16534dd1d..183efacdb 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs @@ -27,5 +27,20 @@ namespace ICSharpCode.NRefactory.CSharp } } } + + [Test] + public void AstNodesDoNotDeriveFromEachOther() + { + // Ast nodes should derive only from abstract classes; not from concrete types. + // For example, we want to avoid that an AST consumer doing "if (node is PropertyDeclaration)" + // unknowingly also handles IndexerDeclarations. + foreach (Type type in typeof(AstNode).Assembly.GetExportedTypes()) { + if (type == typeof(CSharpModifierToken)) // CSharpModifierToken is the exception (though I'm not too happy about that) + continue; + if (type.IsSubclassOf(typeof(AstNode))) { + Assert.IsTrue(type.BaseType.IsAbstract, type.FullName); + } + } + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs index 8b0298e60..41ba8452c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs @@ -8,27 +8,43 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture] + [TestFixture, Ignore("Aliases not yet implemented")] public class AliasReferenceExpressionTests { - [Test, Ignore] + [Test] public void GlobalReferenceExpressionTest() { CSharpParser parser = new CSharpParser(); - parser.ParseTypeReference(new StringReader("global::System")); - //Assert.IsTrue(tre.TypeReference.IsGlobal); - //Assert.AreEqual("System", tre.TypeReference.Type); - throw new NotImplementedException(); + AstType type = parser.ParseTypeReference(new StringReader("global::System")); + Assert.IsNotNull( + new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "System" + }.Match(type) + ); } - [Test, Ignore] + [Test] public void GlobalTypeDeclaration() { VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("global::System.String a;"); - //TypeReference typeRef = lvd.GetTypeForVariable(0); - //Assert.IsTrue(typeRef.IsGlobal); - //Assert.AreEqual("System.String", typeRef.Type); - throw new NotImplementedException(); + Assert.IsNotNull( + new VariableDeclarationStatement { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "System" + }, + IsDoubleColon = false, + MemberName = "String", + }, + Variables = { + new VariableInitializer("a") + } + }.Match(lvd) + ); } // TODO: add tests for aliases other than 'global' diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs index 90e68d807..a1d4e1a45 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs @@ -47,6 +47,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression public void SimpleAnonymousMethod() { AnonymousMethodExpression ame = Parse("delegate(int a, int b) { return a + b; }"); + Assert.IsTrue(ame.HasParameterList); Assert.AreEqual(2, ame.Parameters.Count()); Assert.AreEqual(1, ame.Body.Statements.Count()); Assert.IsTrue(ame.Body.Children.First() is ReturnStatement); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs index e3173c8cd..fbe1af58e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs @@ -6,31 +6,51 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture, Ignore("Needs to be ported to new NRefactory")] + [TestFixture] public class ArrayObjectCreateExpressionTests { [Test] public void ArrayCreateExpressionTest1() { - /* - ArrayCreateExpression ace = ParseUtilCSharp.ParseExpression("new int[5]"); - Assert.AreEqual("System.Int32", ace.CreateType.Type); - Assert.IsTrue(ace.CreateType.IsKeyword); - Assert.AreEqual(1, ace.Arguments.Count); - Assert.AreEqual(new int[] {0}, ace.CreateType.RankSpecifier); - */ - throw new NotImplementedException(); + ParseUtilCSharp.AssertExpression( + "new int[5]", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(5) } + }); } - [Test] + [Test, Ignore("AdditionalArraySpecifiers not yet implemented")] + public void MultidimensionalNestedArray() + { + ParseUtilCSharp.AssertExpression( + "new int[5,2][,,][]", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(5), new PrimitiveExpression(2) }, + AdditionalArraySpecifiers = { + new ArraySpecifier(3), + new ArraySpecifier(1) + } + }); + } + + [Test, Ignore("Array initializers not yet implemented")] public void ImplicitlyTypedArrayCreateExpression() { - /* - ArrayCreateExpression ace = ParseUtilCSharp.ParseExpression("new[] { 1, 10, 100, 1000 }"); - Assert.AreEqual("", ace.CreateType.Type); - Assert.AreEqual(0, ace.Arguments.Count); - Assert.AreEqual(4, ace.ArrayInitializer.CreateExpressions.Count);*/ - throw new NotImplementedException(); + ParseUtilCSharp.AssertExpression( + "new[] { 1, 10, 100, 1000 }", + new ArrayCreateExpression { + Initializer = new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(1), + new PrimitiveExpression(10), + new PrimitiveExpression(100), + new PrimitiveExpression(1000) + } + } + }); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs index 57604d083..54d8d8c8b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs @@ -9,132 +9,157 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression [TestFixture, Ignore("Port unit tests to new DOM")] public class CastExpressionTests { - /* [Test] public void SimpleCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(MyObject)o"); - Assert.AreEqual("MyObject", ce.CastTo.Type); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(MyObject)o", + new CastExpression { + Type = new SimpleType("MyObject"), + Expression = new IdentifierExpression("o") + }); } [Test] public void ArrayCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(MyType[])o"); - Assert.AreEqual("MyType", ce.CastTo.Type); - Assert.AreEqual(new int[] { 0 }, ce.CastTo.RankSpecifier); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(MyType[])o", + new CastExpression { + Type = new SimpleType("MyType").MakeArrayType(1), + Expression = new IdentifierExpression("o") + }); } [Test] public void NullablePrimitiveCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(int?)o"); - Assert.AreEqual("System.Nullable", ce.CastTo.Type); - Assert.AreEqual("System.Int32", ce.CastTo.GenericTypes[0].Type); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(int?)o", + new CastExpression { + Type = new ComposedType { BaseType = new PrimitiveType("int"), HasNullableSpecifier = true }, + Expression = new IdentifierExpression("o") + }); } [Test] public void NullableCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(MyType?)o"); - Assert.AreEqual("System.Nullable", ce.CastTo.Type); - Assert.AreEqual("MyType", ce.CastTo.GenericTypes[0].Type); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(MyType?)o", + new CastExpression { + Type = new ComposedType { BaseType = new SimpleType("MyType"), HasNullableSpecifier = true }, + Expression = new IdentifierExpression("o") + }); } [Test] public void NullableTryCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("o as int?"); - Assert.AreEqual("System.Nullable", ce.CastTo.Type); - Assert.IsTrue(ce.CastTo.IsKeyword); - Assert.AreEqual("System.Int32", ce.CastTo.GenericTypes[0].Type); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.TryCast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "o as int?", + new AsExpression { + Type = new ComposedType { BaseType = new PrimitiveType("int"), HasNullableSpecifier = true }, + Expression = new IdentifierExpression("o") + }); } [Test] public void GenericCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(List)o"); - Assert.AreEqual("List", ce.CastTo.Type); - Assert.AreEqual("System.String", ce.CastTo.GenericTypes[0].Type); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(List)o", + new CastExpression { + Type = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }, + Expression = new IdentifierExpression("o") + }); } [Test] public void GenericArrayCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(List[])o"); - Assert.AreEqual("List", ce.CastTo.Type); - Assert.AreEqual("System.String", ce.CastTo.GenericTypes[0].Type); - Assert.AreEqual(new int[] { 0 }, ce.CastTo.RankSpecifier); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(List[])o", + new CastExpression { + Type = new ComposedType { + BaseType = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }, + ArraySpecifiers = { new ArraySpecifier(1) } + }, + Expression = new IdentifierExpression("o") + }); } [Test] public void GenericArrayAsCastExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("o as List[]"); - Assert.AreEqual("List", ce.CastTo.Type); - Assert.AreEqual("System.String", ce.CastTo.GenericTypes[0].Type); - Assert.AreEqual(new int[] { 0 }, ce.CastTo.RankSpecifier); - Assert.IsTrue(ce.Expression is IdentifierExpression); - Assert.AreEqual(CastType.TryCast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "o as List[]", + new AsExpression { + Type = new ComposedType { + BaseType = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }, + ArraySpecifiers = { new ArraySpecifier(1) } + }, + Expression = new IdentifierExpression("o") + }); } [Test] public void CastMemberReferenceOnParenthesizedExpression() { - // yes, we really wanted to evaluate .Member on expr and THEN cast the result to MyType - CastExpression ce = ParseUtilCSharp.ParseExpression("(MyType)(expr).Member"); - Assert.AreEqual("MyType", ce.CastTo.Type); - Assert.IsTrue(ce.Expression is MemberReferenceExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + // yes, we really want to evaluate .Member on expr and THEN cast the result to MyType + ParseUtilCSharp.AssertExpression( + "(MyType)(expr).Member", + new CastExpression { + Type = new SimpleType("MyType"), + Expression = new ParenthesizedExpression { Expression = new IdentifierExpression("expr") }.Member("Member") + }); } [Test] public void TryCastParenthesizedExpression() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(o) as string"); - Assert.AreEqual("System.String", ce.CastTo.ToString()); - Assert.IsTrue(ce.Expression is ParenthesizedExpression); - Assert.AreEqual(CastType.TryCast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(o) as string", + new AsExpression { + Expression = new ParenthesizedExpression { Expression = new IdentifierExpression("o") }, + Type = new PrimitiveType("string") + }); } [Test] public void CastNegation() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(uint)-negativeValue"); - Assert.AreEqual("System.UInt32", ce.CastTo.ToString()); - Assert.IsTrue(ce.Expression is UnaryOperatorExpression); - Assert.AreEqual(CastType.Cast, ce.CastType); + ParseUtilCSharp.AssertExpression( + "(uint)-negativeValue", + new CastExpression { + Type = new PrimitiveType("uint"), + Expression = new UnaryOperatorExpression( + UnaryOperatorType.Minus, + new IdentifierExpression("negativeValue") + )}); } - */ [Test] public void SubtractionIsNotCast() { - BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression("(BigInt)-negativeValue"); - Assert.IsTrue(boe.Left is ParenthesizedExpression); - Assert.IsTrue(boe.Right is IdentifierExpression); + ParseUtilCSharp.AssertExpression( + "(BigInt)-negativeValue", + new BinaryOperatorExpression { + Left = new ParenthesizedExpression { Expression = new IdentifierExpression("BigInt") }, + Operator = BinaryOperatorType.Subtract, + Right = new IdentifierExpression("negativeValue") + }); } [Test] public void IntMaxValueToBigInt() { - CastExpression ce = ParseUtilCSharp.ParseExpression("(BigInt)int.MaxValue"); - Assert.AreEqual("BigInt", ce.Type.ToString()); - Assert.IsTrue(ce.Expression is MemberReferenceExpression); + ParseUtilCSharp.AssertExpression( + "(BigInt)int.MaxValue", + new CastExpression { + Type = new SimpleType("BigInt"), + Expression = new PrimitiveExpression("int").Member("MaxValue") + }); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs index 7419740ff..9c5296920 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs @@ -6,48 +6,74 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture, Ignore("tests need to be ported")] + [TestFixture, Ignore("Aliases not yet implemented")] public class DefaultValueExpressionTests { [Test] public void SimpleDefaultValue() { DefaultValueExpression toe = ParseUtilCSharp.ParseExpression("default(T)"); - Assert.AreEqual("T", toe.Type); + Assert.AreEqual("T", ((SimpleType)toe.Type).Identifier); } - /* [Test] public void FullQualifiedDefaultValue() { - DefaultValueExpression toe = ParseUtilCSharp.ParseExpression("default(global::MyNamespace.N1.MyType)"); - Assert.IsTrue(toe.TypeReference.IsGlobal); - Assert.AreEqual("MyNamespace.N1.MyType", toe.TypeReference.Type); + ParseUtilCSharp.AssertExpression( + "default(global::MyNamespace.N1.MyType)", + new DefaultValueExpression { + Type = new MemberType { + Target = new MemberType { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "MyNamespace" + }, + MemberName = "N1" + }, + MemberName = "MyType" + } + }); } [Test] public void GenericDefaultValue() { - DefaultValueExpression toe = ParseUtilCSharp.ParseExpression("default(MyNamespace.N1.MyType)"); - Assert.AreEqual("MyNamespace.N1.MyType", toe.TypeReference.Type); - Assert.AreEqual("System.String", toe.TypeReference.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "default(MyNamespace.N1.MyType)", + new DefaultValueExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "N1" + }, + MemberName = "MyType", + TypeArguments = { new PrimitiveType("string") } + } + }); } [Test] public void DefaultValueAsIntializer() { - // This test is failing because we need a resolver for the "default:" / "default(" conflict. - LocalVariableDeclaration lvd = ParseUtilCSharp.ParseStatement("T a = default(T);"); - DefaultValueExpression dve = (DefaultValueExpression)lvd.Variables[0].Initializer; - Assert.AreEqual("T", dve.TypeReference.Type); + // This test was problematic (in old NRefactory) because we need a resolver for the "default:" / "default(" conflict. + ParseUtilCSharp.AssertStatement( + "T a = default(T);", + new VariableDeclarationStatement { + Type = new SimpleType("T"), + Variables = { + new VariableInitializer("a", new DefaultValueExpression { Type = new SimpleType("T") }) + }}); } [Test] public void DefaultValueInReturnStatement() { - ReturnStatement rs = ParseUtilCSharp.ParseStatement("return default(T);"); - DefaultValueExpression dve = (DefaultValueExpression)rs.Expression; - Assert.AreEqual("T", dve.TypeReference.Type); - }*/ + ParseUtilCSharp.AssertStatement( + "return default(T);", + new ReturnStatement { + Expression = new DefaultValueExpression { Type = new SimpleType("T") } + }); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs index 6cd54f521..d79658eff 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression CheckIdentifier(@"l\U00000065xer", "lexer"); } - [Test] + [Test, Ignore("The @ should not be part of IdentifierExpression.Identifier")] public void TestKeyWordAsIdentifier() { CheckIdentifier("@int", "int"); @@ -51,28 +51,36 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression CheckIdentifier(@"i\u006et", "int"); } - [Test] + [Test, Ignore("The @ should not be part of IdentifierExpression.Identifier")] public void TestKeyWordAsIdentifierStartingWithUnderscore() { CheckIdentifier("@_int", "_int"); } - [Test, Ignore] + [Test] public void GenericMethodReference() { IdentifierExpression ident = ParseUtilCSharp.ParseExpression("M"); - Assert.AreEqual("M", ident.Identifier); - //Assert.AreEqual(1, ident.TypeArguments.Count); - throw new NotImplementedException(); + Assert.IsNotNull( + new IdentifierExpression { + Identifier = "M" , + TypeArguments = { + new PrimitiveType("int") + } + }.Match(ident)); } - [Test, Ignore] + [Test] public void GenericMethodReference2() { IdentifierExpression ident = ParseUtilCSharp.ParseExpression("TargetMethod"); - Assert.AreEqual("TargetMethod", ident.Identifier); - //Assert.AreEqual(1, ident.TypeArguments.Count); - throw new NotImplementedException(); + Assert.IsNotNull( + new IdentifierExpression { + Identifier = "TargetMethod" , + TypeArguments = { + new PrimitiveType("string") + } + }.Match(ident)); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs index f3a39b6fd..73ad17502 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs @@ -7,7 +7,7 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture, Ignore("Port unit tests to new DOM")] + [TestFixture] public class InvocationExpressionTests { [Test] @@ -19,55 +19,71 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Assert.AreEqual("myMethod", ((IdentifierExpression)ie.Target).Identifier); } - /* TODO port unit tests to new DOM [Test] public void GenericInvocationExpressionTest() { - var expr = ParseUtilCSharp.ParseExpression("myMethod('a')"); - Assert.AreEqual(1, expr.Arguments.Count()); - Assert.IsTrue(expr.TargetObject is IdentifierExpression); - IdentifierExpression ident = (IdentifierExpression)expr.TargetObject; - Assert.AreEqual("myMethod", ident.Identifier); - Assert.AreEqual(1, ident.TypeArguments.Count); - Assert.AreEqual("System.Char", ident.TypeArguments[0].Type); + ParseUtilCSharp.AssertExpression( + "myMethod('a')", + new InvocationExpression { + Target = new IdentifierExpression { + Identifier = "myMethod", + TypeArguments = { new PrimitiveType("char") } + }, + Arguments = { new PrimitiveExpression('a') } + } + ); } [Test] public void GenericInvocation2ExpressionTest() { - var expr = ParseUtilCSharp.ParseExpression("myMethod()"); - Assert.AreEqual(0, expr.Arguments.Count); - Assert.IsTrue(expr.TargetObject is IdentifierExpression); - IdentifierExpression ident = (IdentifierExpression)expr.TargetObject; - Assert.AreEqual("myMethod", ident.Identifier); - Assert.AreEqual(2, ident.TypeArguments.Count); - Assert.AreEqual("T", ident.TypeArguments[0].Type); - Assert.IsFalse(ident.TypeArguments[0].IsKeyword); - Assert.AreEqual("System.Boolean", ident.TypeArguments[1].Type); - Assert.IsTrue(ident.TypeArguments[1].IsKeyword); + ParseUtilCSharp.AssertExpression( + "myMethod()", + new InvocationExpression { + Target = new IdentifierExpression { + Identifier = "myMethod", + TypeArguments = { + new SimpleType("T"), + new PrimitiveType("bool") + } + } + } + ); } [Test] public void AmbiguousGrammarGenericMethodCall() { - InvocationExpression ie = ParseUtilCSharp.ParseExpression("F(G(7))"); - Assert.IsTrue(ie.TargetObject is IdentifierExpression); - Assert.AreEqual(1, ie.Arguments.Count); - ie = (InvocationExpression)ie.Arguments[0]; - Assert.AreEqual(1, ie.Arguments.Count); - Assert.IsTrue(ie.Arguments[0] is PrimitiveExpression); - IdentifierExpression ident = (IdentifierExpression)ie.TargetObject; - Assert.AreEqual("G", ident.Identifier); - Assert.AreEqual(2, ident.TypeArguments.Count); + ParseUtilCSharp.AssertExpression( + "F(G(7))", + new InvocationExpression { + Target = new IdentifierExpression("F"), + Arguments = { + new InvocationExpression { + Target = new IdentifierExpression { + Identifier = "G", + TypeArguments = { new SimpleType("A"), new SimpleType("B") } + }, + Arguments = { new PrimitiveExpression(7) } + }}}); } - [Test] + [Test, Ignore("Mono Parser Bug???")] public void AmbiguousGrammarNotAGenericMethodCall() { - BinaryOperatorExpression boe = ParseUtilCSharp.ParseExpression("F+y"); - Assert.AreEqual(BinaryOperatorType.GreaterThan, boe.Op); - Assert.IsTrue(boe.Left is BinaryOperatorExpression); - Assert.IsTrue(boe.Right is UnaryOperatorExpression); + ParseUtilCSharp.AssertExpression( + "F+y", + new BinaryOperatorExpression { + Left = new BinaryOperatorExpression { + Left = new IdentifierExpression("F"), + Operator = BinaryOperatorType.LessThan, + Right = new IdentifierExpression("A") + }, + Operator = BinaryOperatorType.GreaterThan, + Right = new UnaryOperatorExpression { + Operator = UnaryOperatorType.Plus, + Expression = new IdentifierExpression("y") + }}); } [Test] @@ -76,80 +92,81 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression // this test was written because this bug caused the AbstractASTVisitor to crash InvocationExpression expr = ParseUtilCSharp.ParseExpression("WriteLine(myMethod(,))", true); - Assert.IsTrue(expr.TargetObject is IdentifierExpression); - Assert.AreEqual("WriteLine", ((IdentifierExpression)expr.TargetObject).Identifier); + Assert.IsTrue(expr.Target is IdentifierExpression); + Assert.AreEqual("WriteLine", ((IdentifierExpression)expr.Target).Identifier); Assert.AreEqual(1, expr.Arguments.Count); // here a second null parameter was added incorrectly - Assert.IsTrue(expr.Arguments[0] is InvocationExpression); - CheckSimpleInvoke((InvocationExpression)expr.Arguments[0]); + Assert.IsTrue(expr.Arguments.Single() is InvocationExpression); } - [Test] + [Test, Ignore("Positions not yet accurate when parsing expression only (because class/method is added around it)")] public void NestedInvocationPositions() { InvocationExpression expr = ParseUtilCSharp.ParseExpression("a.B().C(args)"); - Assert.AreEqual(new Location(8, 1), expr.StartLocation); - Assert.AreEqual(new Location(14, 1), expr.EndLocation); - MemberReferenceExpression mre = (MemberReferenceExpression)expr.TargetObject; - Assert.AreEqual(new Location(6, 1), mre.StartLocation); - Assert.AreEqual(new Location(8, 1), mre.EndLocation); + Assert.AreEqual(new AstLocation(1, 8), expr.StartLocation); + Assert.AreEqual(new AstLocation(1, 14), expr.EndLocation); + MemberReferenceExpression mre = (MemberReferenceExpression)expr.Target; + Assert.AreEqual(new AstLocation(1, 6), mre.StartLocation); + Assert.AreEqual(new AstLocation(1, 8), mre.EndLocation); - Assert.AreEqual(new Location(4, 1), mre.TargetObject.StartLocation); - Assert.AreEqual(new Location(6, 1), mre.TargetObject.EndLocation); + Assert.AreEqual(new AstLocation(1, 4), mre.Target.StartLocation); + Assert.AreEqual(new AstLocation(1, 6), mre.Target.EndLocation); } [Test] public void InvocationOnGenericType() { - InvocationExpression expr = ParseUtilCSharp.ParseExpression("A.Foo()"); - MemberReferenceExpression mre = (MemberReferenceExpression)expr.TargetObject; - Assert.AreEqual("Foo", mre.MemberName); - TypeReferenceExpression tre = (TypeReferenceExpression)mre.TargetObject; - Assert.AreEqual("A", tre.TypeReference.Type); - Assert.AreEqual("T", tre.TypeReference.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "A.Foo()", + new IdentifierExpression { + Identifier = "A", + TypeArguments = { new SimpleType("T") } + }.Invoke("Foo") + ); } [Test] public void InvocationOnInnerClassInGenericType() { - InvocationExpression expr = ParseUtilCSharp.ParseExpression("A.B.Foo()"); - MemberReferenceExpression mre = (MemberReferenceExpression)expr.TargetObject; - Assert.AreEqual("Foo", mre.MemberName); - MemberReferenceExpression mre2 = (MemberReferenceExpression)mre.TargetObject; - Assert.AreEqual("B", mre2.MemberName); - TypeReferenceExpression tre = (TypeReferenceExpression)mre2.TargetObject; - Assert.AreEqual("A", tre.TypeReference.Type); - Assert.AreEqual("T", tre.TypeReference.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "A.B.Foo()", + new IdentifierExpression { + Identifier = "A", + TypeArguments = { new SimpleType("T") } + }.Member("B").Invoke("Foo") + ); } [Test] public void InvocationOnGenericInnerClassInGenericType() { - InvocationExpression expr = ParseUtilCSharp.ParseExpression("A.B.C.Foo()"); - MemberReferenceExpression mre = (MemberReferenceExpression)expr.TargetObject; - Assert.AreEqual("Foo", mre.MemberName); - TypeReferenceExpression tre = (TypeReferenceExpression)mre.TargetObject; - InnerClassTypeReference ictr = (InnerClassTypeReference)tre.TypeReference; - Assert.AreEqual("B.C", ictr.Type); - Assert.AreEqual(1, ictr.GenericTypes.Count); - Assert.AreEqual("U", ictr.GenericTypes[0].Type); - - Assert.AreEqual("A", ictr.BaseType.Type); - Assert.AreEqual(1, ictr.BaseType.GenericTypes.Count); - Assert.AreEqual("T", ictr.BaseType.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "A.B.C.Foo()", + new MemberReferenceExpression { + Target = new IdentifierExpression { + Identifier = "A", + TypeArguments = { new SimpleType("T") } + }.Member("B"), + MemberName = "C", + TypeArguments = { new SimpleType("U") } + }.Invoke("Foo")); } - [Test] + [Test, Ignore("named arguments not yet supported")] public void InvocationWithNamedArgument() { - InvocationExpression expr = ParseUtilCSharp.ParseExpression("a(arg: ref v)"); - Assert.AreEqual(1, expr.Arguments.Count); - NamedArgumentExpression nae = (NamedArgumentExpression)expr.Arguments[0]; - Assert.AreEqual("arg", nae.Name); - DirectionExpression dir = (DirectionExpression)nae.Expression; - Assert.AreEqual(FieldDirection.Ref, dir.FieldDirection); - Assert.IsInstanceOf(dir.Expression); - }*/ + ParseUtilCSharp.AssertExpression( + "a(arg: ref v)", + new InvocationExpression { + Target = new IdentifierExpression("a"), + Arguments = { + new NamedArgumentExpression { + Identifier = "arg", + Expression = new DirectionExpression { + FieldDirection = FieldDirection.Ref, + Expression = new IdentifierExpression("v") + }}}}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs index 4b5039565..bbab99a6f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs @@ -9,15 +9,16 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression [TestFixture] public class IsExpressionTests { - [Test, Ignore] + [Test] public void GenericArrayIsExpression() { - /* TODO - TypeOfIsExpression ce = ParseUtilCSharp.ParseExpression("o is List[]"); - Assert.AreEqual("List", ce.TypeReference.Type); - Assert.AreEqual("System.String", ce.TypeReference.GenericTypes[0].Type); - Assert.AreEqual(new int[] { 0 }, ce.TypeReference.RankSpecifier); - Assert.IsTrue(ce.Expression is IdentifierExpression);*/ + ParseUtilCSharp.AssertExpression( + "o is List[]", + new IsExpression { + Expression = new IdentifierExpression("o"), + Type = new SimpleType("List") { TypeArguments = { new PrimitiveType("string") } }.MakeArrayType(1) + } + ); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs index 5f4addd3e..8350a6756 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs @@ -6,84 +6,103 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture, Ignore("Port unit tests")] + [TestFixture] public class LambdaExpressionTests { - static LambdaExpression ParseCSharp(string program) - { - return ParseUtilCSharp.ParseExpression(program); - } - - [Test] + [Test, Ignore("Lambdas with expression body not yet supported")] public void ImplicitlyTypedExpressionBody() { - /* - LambdaExpression e = ParseCSharp("(x) => x + 1"); - Assert.AreEqual("x", e.Parameters[0].ParameterName); - Assert.IsTrue(e.Parameters[0].TypeReference.IsNull); - Assert.IsTrue(e.ExpressionBody is BinaryOperatorExpression); - Assert.IsTrue(e.ReturnType.IsNull);*/ - throw new NotImplementedException(); + ParseUtilCSharp.AssertExpression( + "(x) => x + 1", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }); } - /* TODO Port unit tests - [Test] + [Test, Ignore("Lambdas with expression body not yet supported")] public void ImplicitlyTypedExpressionBodyWithoutParenthesis() { - LambdaExpression e = ParseCSharp("x => x + 1"); - Assert.AreEqual("x", e.Parameters[0].ParameterName); - Assert.IsTrue(e.Parameters[0].TypeReference.IsNull); - Assert.IsTrue(e.ExpressionBody is BinaryOperatorExpression); - Assert.IsTrue(e.ReturnType.IsNull); + ParseUtilCSharp.AssertExpression( + "x => x + 1", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }); } [Test] public void ImplicitlyTypedStatementBody() { - LambdaExpression e = ParseCSharp("(x) => { return x + 1; }"); - Assert.AreEqual("x", e.Parameters[0].ParameterName); - Assert.IsTrue(e.Parameters[0].TypeReference.IsNull); - Assert.IsTrue(e.StatementBody.Children[0] is ReturnStatement); - Assert.IsTrue(e.ReturnType.IsNull); + ParseUtilCSharp.AssertExpression( + "(x) => { return x + 1; }", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BlockStatement { + new ReturnStatement { + Expression = new BinaryOperatorExpression( + new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }}}); } [Test] public void ImplicitlyTypedStatementBodyWithoutParenthesis() { - LambdaExpression e = ParseCSharp("x => { return x + 1; }"); - Assert.AreEqual("x", e.Parameters[0].ParameterName); - Assert.IsTrue(e.Parameters[0].TypeReference.IsNull); - Assert.IsTrue(e.StatementBody.Children[0] is ReturnStatement); - Assert.IsTrue(e.ReturnType.IsNull); + ParseUtilCSharp.AssertExpression( + "x => { return x + 1; }", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BlockStatement { + new ReturnStatement { + Expression = new BinaryOperatorExpression( + new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }}}); } [Test] public void ExplicitlyTypedStatementBody() { - LambdaExpression e = ParseCSharp("(int x) => { return x + 1; }"); - Assert.AreEqual("x", e.Parameters[0].ParameterName); - Assert.AreEqual("System.Int32", e.Parameters[0].TypeReference.Type); - Assert.IsTrue(e.StatementBody.Children[0] is ReturnStatement); - Assert.IsTrue(e.ReturnType.IsNull); + ParseUtilCSharp.AssertExpression( + "(int x) => { return x + 1; }", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Type = new PrimitiveType("int"), Name = "x" } }, + Body = new BlockStatement { + new ReturnStatement { + Expression = new BinaryOperatorExpression( + new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }}}); } - [Test] - public void ExplicitlyTypedStatementBodyWithRefParameter() + [Test, Ignore("Lambdas with expression body not yet supported")] + public void ExplicitlyTypedWithRefParameter() { - LambdaExpression e = ParseCSharp("(ref int i) => i = 1"); - Assert.AreEqual("i", e.Parameters[0].ParameterName); - Assert.IsTrue((e.Parameters[0].ParamModifier & ParameterModifiers.Ref) == ParameterModifiers.Ref); - Assert.AreEqual("System.Int32", e.Parameters[0].TypeReference.Type); - Assert.IsTrue(e.ReturnType.IsNull); + ParseUtilCSharp.AssertExpression( + "(ref int i) => i = 1", + new LambdaExpression { + Parameters = { + new ParameterDeclaration { + ParameterModifier = ParameterModifier.Ref, + Type = new PrimitiveType("int"), + Name = "x" + } + }, + Body = new AssignmentExpression(new IdentifierExpression("i"), new PrimitiveExpression(1)) + }); } - [Test] + [Test, Ignore("Lambdas with expression body not yet supported")] public void LambdaExpressionContainingConditionalExpression() { - LambdaExpression e = ParseCSharp("rr => rr != null ? rr.ResolvedType : null"); - Assert.AreEqual("rr", e.Parameters[0].ParameterName); - Assert.IsTrue(e.ExpressionBody is ConditionalExpression); - Assert.IsTrue(e.ReturnType.IsNull); - }*/ + ParseUtilCSharp.AssertExpression( + "rr => rr != null ? rr.ResolvedType : null", + new LambdaExpression { + Parameters = { new ParameterDeclaration { Name = "rr" } }, + Body = new ConditionalExpression { + Condition = new BinaryOperatorExpression( + new IdentifierExpression("rr"), BinaryOperatorType.InEquality, new NullReferenceExpression()), + TrueExpression = new IdentifierExpression("rr").Member("ResolvedType"), + FalseExpression = new NullReferenceExpression() + }}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs index 3f9ce69eb..960b53355 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs @@ -6,71 +6,84 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture, Ignore] + [TestFixture] public class MemberReferenceExpressionTests { [Test] public void SimpleFieldReferenceExpressionTest() { - MemberReferenceExpression fre = ParseUtilCSharp.ParseExpression("myTargetObject.myField"); - //Assert.AreEqual("myField", fre.MemberName); - //Assert.IsTrue(fre.TargetObject is IdentifierExpression); - //Assert.AreEqual("myTargetObject", ((IdentifierExpression)fre.TargetObject).Identifier); - throw new NotImplementedException(); + ParseUtilCSharp.AssertExpression( + "myTargetObject.myField", + new IdentifierExpression("myTargetObject").Member("myField") + ); + } + + [Test, Ignore("parser is broken and produces IdentifierExpression instead of PrimitiveType")] + public void ShortMaxValueTest() + { + ParseUtilCSharp.AssertExpression( + "short.MaxValue", + new PrimitiveType("short").Member("MaxValue") + ); + } + + [Test, Ignore("Parsing of @-identifiers is broken")] + public void IdentShortMaxValueTest() + { + ParseUtilCSharp.AssertExpression( + "@short.MaxValue", + new IdentifierExpression("short").Member("MaxValue") + ); } - /* TODO port unit tests [Test] public void GenericFieldReferenceExpressionTest() { - MemberReferenceExpression fre = ParseUtilCSharp.ParseExpression("SomeClass.myField"); - Assert.AreEqual("myField", fre.MemberName); - Assert.IsTrue(fre.TargetObject is TypeReferenceExpression); - TypeReference tr = ((TypeReferenceExpression)fre.TargetObject).TypeReference; - Assert.AreEqual("SomeClass", tr.Type); - Assert.AreEqual(1, tr.GenericTypes.Count); - Assert.AreEqual("System.String", tr.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "SomeClass.myField", + new IdentifierExpression("SomeClass") { TypeArguments = { new PrimitiveType("string") } }.Member("myField") + ); } [Test] public void FullNamespaceGenericFieldReferenceExpressionTest() { - MemberReferenceExpression fre = ParseUtilCSharp.ParseExpression("Namespace.Subnamespace.SomeClass.myField"); - Assert.AreEqual("myField", fre.MemberName); - Assert.IsTrue(fre.TargetObject is TypeReferenceExpression); - TypeReference tr = ((TypeReferenceExpression)fre.TargetObject).TypeReference; - Assert.AreEqual("Namespace.Subnamespace.SomeClass", tr.Type); - Assert.AreEqual(1, tr.GenericTypes.Count); - Assert.AreEqual("System.String", tr.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "Namespace.Subnamespace.SomeClass.myField", + new MemberReferenceExpression { + Target = new IdentifierExpression("Namespace").Member("Subnamespace"), + TypeArguments = { new PrimitiveType("string") } + }.Member("myField") + ); } - [Test] + [Test, Ignore("Aliases not yet implemented")] public void GlobalFullNamespaceGenericFieldReferenceExpressionTest() { - MemberReferenceExpression fre = ParseUtilCSharp.ParseExpression("global::Namespace.Subnamespace.SomeClass.myField"); - Assert.AreEqual("myField", fre.MemberName); - Assert.IsTrue(fre.TargetObject is TypeReferenceExpression); - TypeReference tr = ((TypeReferenceExpression)fre.TargetObject).TypeReference; - Assert.IsFalse(tr is InnerClassTypeReference); - Assert.AreEqual("Namespace.Subnamespace.SomeClass", tr.Type); - Assert.AreEqual(1, tr.GenericTypes.Count); - Assert.AreEqual("System.String", tr.GenericTypes[0].Type); - Assert.IsTrue(tr.IsGlobal); + ParseUtilCSharp.AssertExpression( + "global::Namespace.Subnamespace.SomeClass.myField", + new MemberReferenceExpression { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "Namespace" + }.Member("Subnamespace"), + TypeArguments = { new PrimitiveType("string") } + }.Member("myField") + ); } [Test] public void NestedGenericFieldReferenceExpressionTest() { - MemberReferenceExpression fre = ParseUtilCSharp.ParseExpression("MyType.InnerClass.myField"); - Assert.AreEqual("myField", fre.MemberName); - Assert.IsTrue(fre.TargetObject is TypeReferenceExpression); - InnerClassTypeReference ic = (InnerClassTypeReference)((TypeReferenceExpression)fre.TargetObject).TypeReference; - Assert.AreEqual("InnerClass", ic.Type); - Assert.AreEqual(1, ic.GenericTypes.Count); - Assert.AreEqual("System.Int32", ic.GenericTypes[0].Type); - Assert.AreEqual("MyType", ic.BaseType.Type); - Assert.AreEqual(1, ic.BaseType.GenericTypes.Count); - Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].Type); - }*/ + ParseUtilCSharp.AssertExpression( + "MyType.InnerClass.myField", + new MemberReferenceExpression { + Target = new IdentifierExpression("MyType") { TypeArguments = { new PrimitiveType("string") } }, + MemberName = "InnerClass", + TypeArguments = { new PrimitiveType("int") } + }.Member("myField") + ); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs index f02c795e2..895ffff4c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs @@ -9,13 +9,25 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression [TestFixture] public class PointerReferenceExpressionTests { - [Test, Ignore("where did PointerReferenceExpression.MemberName go?")] + [Test, Ignore("Parser bug!")] public void PointerReferenceExpressionTest() { PointerReferenceExpression pre = ParseUtilCSharp.ParseExpression("myObj.field->b"); Assert.IsTrue(pre.Target is MemberReferenceExpression); - //Assert.AreEqual("b", pre.MemberName); - throw new NotImplementedException(); + Assert.AreEqual("b", pre.MemberName); + } + + [Test, Ignore("Parser bug!")] + public void PointerReferenceGenericMethodTest() + { + ParseUtilCSharp.AssertExpression( + "ptr->M();", + new InvocationExpression { + Target = new PointerReferenceExpression { + Target = new IdentifierExpression("ptr"), + MemberName = "M", + TypeArguments = { new PrimitiveType("string") } + }}); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs index 7b1d18e03..5601797c9 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs @@ -6,104 +6,220 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture, Ignore] + [TestFixture, Ignore("Query expressions not yet implemented")] public class QueryExpressionTests { [Test] public void SimpleExpression() { - /* - QueryExpression qe = ParseUtilCSharp.ParseExpression( - "from c in customers where c.City == \"London\" select c" - ); - Assert.AreEqual("c", qe.FromClause.Sources.First().Identifier); - Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.Sources.First().Expression).Identifier); - Assert.AreEqual(1, qe.MiddleClauses.Count); - Assert.IsInstanceOf(typeof(QueryExpressionWhereClause), qe.MiddleClauses[0]); - QueryExpressionWhereClause wc = (QueryExpressionWhereClause)qe.MiddleClauses[0]; - Assert.IsInstanceOf(typeof(BinaryOperatorExpression), wc.Condition); - Assert.IsInstanceOf(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause);*/ - throw new NotImplementedException(); + ParseUtilCSharp.AssertExpression( + "from c in customers where c.City == \"London\" select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryWhereClause { + Condition = new BinaryOperatorExpression { + Left = new IdentifierExpression("c").Member("City"), + Operator = BinaryOperatorType.Equality, + Right = new PrimitiveExpression("London") + } + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); } - /* TODO port unit tests [Test] public void ExpressionWithType1() { - QueryExpression qe = ParseUtilCSharp.ParseExpression( - "from Customer c in customers select c" - ); - Assert.AreEqual("c", qe.FromClause.Sources.First().Identifier); - Assert.AreEqual("Customer", qe.FromClause.Sources.First().Type.ToString()); - Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.Sources.First().Expression).Identifier); - Assert.IsInstanceOf(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); + ParseUtilCSharp.AssertExpression( + "from Customer c in customers select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Type = new SimpleType("Customer"), + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); } [Test] public void ExpressionWithType2() { - QueryExpression qe = ParseUtilCSharp.ParseExpression( - "from int c in customers select c" - ); - Assert.AreEqual("c", qe.FromClause.Sources.First().Identifier); - Assert.AreEqual("System.Int32", qe.FromClause.Sources.First().Type.Type); - Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.Sources.First().Expression).Identifier); - Assert.IsInstanceOf(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); + ParseUtilCSharp.AssertExpression( + "from int c in customers select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Type = new PrimitiveType("int"), + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); } [Test] public void ExpressionWithType3() { - QueryExpression qe = ParseUtilCSharp.ParseExpression( - "from S? c in customers select c" - ); - Assert.AreEqual("c", qe.FromClause.Sources.First().Identifier); - Assert.AreEqual("System.Nullable>", qe.FromClause.Sources.First().Type.ToString()); - Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.Sources.First().Expression).Identifier); - Assert.IsInstanceOf(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); + ParseUtilCSharp.AssertExpression( + "from S? c in customers select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Type = new ComposedType { + BaseType = new SimpleType { + Identifier = "S", + TypeArguments = { + new PrimitiveType("int").MakeArrayType() + } + }, + HasNullableSpecifier = true + }, + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); } [Test] public void MultipleGenerators() { - QueryExpression qe = ParseUtilCSharp.ParseExpression(@" + ParseUtilCSharp.AssertExpression( + @" from c in customers where c.City == ""London"" from o in c.Orders where o.OrderDate.Year == 2005 -select new { c.Name, o.OrderID, o.Total }"); - Assert.AreEqual(3, qe.MiddleClauses.Count); - Assert.IsInstanceOf(typeof(QueryExpressionWhereClause), qe.MiddleClauses[0]); - Assert.IsInstanceOf(typeof(QueryExpressionFromClause), qe.MiddleClauses[1]); - Assert.IsInstanceOf(typeof(QueryExpressionWhereClause), qe.MiddleClauses[2]); - - Assert.IsInstanceOf(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); +select new { c.Name, o.OrderID, o.Total }", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryWhereClause { + Condition = new BinaryOperatorExpression { + Left = new IdentifierExpression("c").Member("City"), + Operator = BinaryOperatorType.Equality, + Right = new PrimitiveExpression("London") + } + }, + new QueryFromClause { + Identifier = "o", + Expression = new IdentifierExpression("c").Member("Orders") + }, + new QueryWhereClause { + Condition = new BinaryOperatorExpression { + Left = new IdentifierExpression("c").Member("OrderDate").Member("Year"), + Operator = BinaryOperatorType.Equality, + Right = new PrimitiveExpression(2005) + } + }, + new QuerySelectClause { + Expression = new ObjectCreateExpression { + Initializer = new ArrayInitializerExpression { + Elements = { + new IdentifierExpression("c").Member("Name"), + new IdentifierExpression("o").Member("OrderID"), + new IdentifierExpression("o").Member("Total") + } + } + } + } + }}); } [Test] public void ExpressionWithOrderBy() { - QueryExpression qe = ParseUtilCSharp.ParseExpression( - "from c in customers orderby c.Name select c" - ); - Assert.AreEqual("c", qe.FromClause.Sources.First().Identifier); - Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.Sources.First().Expression).Identifier); - Assert.IsInstanceOf(typeof(QueryExpressionOrderClause), qe.MiddleClauses[0]); - Assert.IsInstanceOf(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); + ParseUtilCSharp.AssertExpression( + "from c in customers orderby c.Name select c", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryOrderClause { + Orderings = { + new QueryOrdering { + Expression = new IdentifierExpression("c").Member("Name") + } + } + }, + new QuerySelectClause { + Expression = new IdentifierExpression("c") + } + }}); } [Test] public void ExpressionWithOrderByAndLet() { - QueryExpression qe = ParseUtilCSharp.ParseExpression( - "from c in customers orderby c.Name let x = c select x" + ParseUtilCSharp.AssertExpression( + "from c in customers orderby c.Name descending let x = c select x", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "c", + Expression = new IdentifierExpression("customers") + }, + new QueryOrderClause { + Orderings = { + new QueryOrdering { + Expression = new IdentifierExpression("c").Member("Name"), + Direction = QueryOrderingDirection.Descending + } + } + }, + new QueryLetClause { + Identifier = "x", + Expression = new IdentifierExpression("c") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("x") + } + }}); + } + + [Test] + public void QueryContinuation() + { + ParseUtilCSharp.AssertExpression( + "from a in b select c into d select e", + new QueryExpression { + Clauses = { + new QueryContinuationClause { + PrecedingQuery = new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QuerySelectClause { Expression = new IdentifierExpression("c") } + } + }, + Identifier = "d" + }, + new QuerySelectClause { Expression = new IdentifierExpression("e") } + } + } ); - Assert.AreEqual("c", qe.FromClause.Sources.First().Identifier); - Assert.AreEqual("customers", ((IdentifierExpression)qe.FromClause.Sources.First().Expression).Identifier); - Assert.IsInstanceOf(typeof(QueryExpressionOrderClause), qe.MiddleClauses[0]); - Assert.IsInstanceOf(typeof(QueryExpressionLetClause), qe.MiddleClauses[1]); - Assert.IsInstanceOf(typeof(QueryExpressionSelectClause), qe.SelectOrGroupClause); - }*/ + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs index a50c1b77f..f6a85fcb3 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs @@ -9,11 +9,11 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression [TestFixture] public class SizeOfExpressionTests { - [Test, Ignore("type references not implemented yet")] + [Test] public void SizeOfExpressionTest() { SizeOfExpression soe = ParseUtilCSharp.ParseExpression("sizeof(MyType)"); - Assert.AreEqual("MyType", soe.Type); + Assert.AreEqual("MyType", ((SimpleType)soe.Type).Identifier); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs index 038925a42..c28d559fc 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs @@ -2,6 +2,7 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Linq; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression @@ -9,11 +10,13 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression [TestFixture] public class StackAllocExpressionTests { - [Test, Ignore] + [Test] public void StackAllocExpressionTest() { - var sae = ParseUtilCSharp.ParseExpression("stackalloc int[100]"); - throw new NotImplementedException(); // TODO: verify type + length expression + var vd = ParseUtilCSharp.ParseStatement("int* a = stackalloc int[100];"); + StackAllocExpression sae = (StackAllocExpression)vd.Variables.Single().Initializer; + Assert.AreEqual("int", ((PrimitiveType)sae.Type).Keyword); + Assert.AreEqual(100, ((PrimitiveExpression)sae.CountExpression).Value); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs index 599aae19f..3dcc932d9 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs @@ -6,86 +6,113 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { - [TestFixture, Ignore] + [TestFixture] public class TypeOfExpressionTests { [Test] public void SimpleTypeOfExpressionTest() { - //TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(MyNamespace.N1.MyType)"); - //Assert.AreEqual("MyNamespace.N1.MyType", toe.TypeReference.Type); - throw new NotImplementedException(); + ParseUtilCSharp.AssertExpression( + "typeof(MyNamespace.N1.MyType)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "N1" + }, + MemberName = "MyType" + }}); } - /* TODO - [Test] + [Test, Ignore("Aliases not yet implemented")] public void GlobalTypeOfExpressionTest() { - TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(global::System.Console)"); - Assert.AreEqual("System.Console", toe.TypeReference.Type); + ParseUtilCSharp.AssertExpression( + "typeof(global::System.Console)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "System" + }, + MemberName = "Console" + }}); } [Test] public void PrimitiveTypeOfExpressionTest() { TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(int)"); - Assert.AreEqual("System.Int32", toe.TypeReference.Type); + Assert.AreEqual("int", ((PrimitiveType)toe.Type).Keyword); } [Test] public void VoidTypeOfExpressionTest() { TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(void)"); - Assert.AreEqual("System.Void", toe.TypeReference.Type); + Assert.AreEqual("void", ((PrimitiveType)toe.Type).Keyword); } [Test] public void ArrayTypeOfExpressionTest() { - TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(MyType[])"); - Assert.AreEqual("MyType", toe.TypeReference.Type); - Assert.AreEqual(new int[] {0}, toe.TypeReference.RankSpecifier); + ParseUtilCSharp.AssertExpression( + "typeof(MyType[])", + new TypeOfExpression { + Type = new SimpleType("MyType").MakeArrayType() + }); } [Test] public void GenericTypeOfExpressionTest() { - TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(MyNamespace.N1.MyType)"); - Assert.AreEqual("MyNamespace.N1.MyType", toe.TypeReference.Type); - Assert.AreEqual("System.String", toe.TypeReference.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "typeof(MyNamespace.N1.MyType)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "N1" + }, + MemberName = "MyType", + TypeArguments = { new PrimitiveType("string") } + }}); } [Test] public void NestedGenericTypeOfExpressionTest() { - TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(MyType.InnerClass.InnerInnerClass)"); - InnerClassTypeReference ic = (InnerClassTypeReference)toe.TypeReference; - Assert.AreEqual("InnerInnerClass", ic.Type); - Assert.AreEqual(0, ic.GenericTypes.Count); - ic = (InnerClassTypeReference)ic.BaseType; - Assert.AreEqual("InnerClass", ic.Type); - Assert.AreEqual(1, ic.GenericTypes.Count); - Assert.AreEqual("System.Int32", ic.GenericTypes[0].Type); - Assert.AreEqual("MyType", ic.BaseType.Type); - Assert.AreEqual(1, ic.BaseType.GenericTypes.Count); - Assert.AreEqual("System.String", ic.BaseType.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "typeof(MyType.InnerClass.InnerInnerClass)", + new TypeOfExpression { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("MyType") { TypeArguments = { new PrimitiveType("string") } }, + MemberName = "InnerClass", + TypeArguments = { new PrimitiveType("int") } + }, + MemberName = "InnerInnerClass" + }}); } [Test] public void NullableTypeOfExpressionTest() { - TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(MyStruct?)"); - Assert.AreEqual("System.Nullable", toe.TypeReference.Type); - Assert.AreEqual("MyStruct", toe.TypeReference.GenericTypes[0].Type); + ParseUtilCSharp.AssertExpression( + "typeof(MyStruct?)", + new TypeOfExpression { + Type = new ComposedType { + BaseType = new SimpleType("MyType"), + HasNullableSpecifier = true + }}); } - [Test] + [Test, Ignore("How do we represent unbound types in the AST?")] public void UnboundTypeOfExpressionTest() { TypeOfExpression toe = ParseUtilCSharp.ParseExpression("typeof(MyType<,>)"); - Assert.AreEqual("MyType", toe.TypeReference.Type); - Assert.IsTrue(toe.TypeReference.GenericTypes[0].IsNull); - Assert.IsTrue(toe.TypeReference.GenericTypes[1].IsNull); - }*/ + throw new NotImplementedException("How do we represent unbound types in the AST?"); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs index c704b8857..a968af1eb 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs @@ -84,9 +84,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Assert.AreEqual(UnaryOperatorType.Dereference, uoe.Operator); ParenthesizedExpression pe = (ParenthesizedExpression)uoe.Expression; CastExpression ce = (CastExpression)pe.Expression; - //Assert.AreEqual("SomeType", ce.CastTo.Type); - //Assert.AreEqual(1, ce.CastTo.PointerNestingLevel); - Assert.Ignore("need to check target type"); // TODO + ComposedType type = (ComposedType)ce.Type; + Assert.AreEqual("SomeType", ((SimpleType)type.BaseType).Identifier); + Assert.AreEqual(1, type.PointerRank); UnaryOperatorExpression adrOf = (UnaryOperatorExpression)ce.Expression; Assert.AreEqual(UnaryOperatorType.AddressOf, adrOf.Operator); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs index 51e046976..e443e7b94 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs @@ -7,55 +7,41 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope { - [TestFixture, Ignore("delegates are completely broken at the moment")] + [TestFixture] public class DelegateDeclarationTests { - void TestParameters(DelegateDeclaration dd) - { - Assert.AreEqual(3, dd.Parameters.Count()); - - Assert.AreEqual("a", ((ParameterDeclaration)dd.Parameters.ElementAt(0)).Name); - //Assert.AreEqual("System.Int32", ((ParameterDeclaration)dd.Parameters.ElementAt(0)).TypeReference.Type); - Assert.Ignore("check types"); // TODO - Assert.AreEqual("secondParam", ((ParameterDeclaration)dd.Parameters.ElementAt(1)).Name); - //Assert.AreEqual("System.Int32", ((ParameterDeclaration)dd.Parameters.ElementAt(1)).TypeReference.Type); - - Assert.AreEqual("lastParam", ((ParameterDeclaration)dd.Parameters.ElementAt(2)).Name); - //Assert.AreEqual("MyObj", ((ParameterDeclaration)dd.Parameters.ElementAt(2)).TypeReference.Type); - } - [Test] public void SimpleCSharpDelegateDeclarationTest() { - string program = "public delegate void MyDelegate(int a, int secondParam, MyObj lastParam);\n"; - DelegateDeclaration dd = ParseUtilCSharp.ParseGlobal(program); - Assert.AreEqual("MyDelegate", dd.Name); - //Assert.AreEqual("System.Void", dd.ReturnType.Type); - TestParameters(dd); + ParseUtilCSharp.AssertGlobal( + "public delegate void MyDelegate(int a, int secondParam, MyObj lastParam);", + new DelegateDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new PrimitiveType("void"), + Name = "MyDelegate", + Parameters = { + new ParameterDeclaration(new PrimitiveType("int"), "a"), + new ParameterDeclaration(new PrimitiveType("int"), "secondParam"), + new ParameterDeclaration(new SimpleType("MyObj"), "lastParam") + }}); } - [Test, Ignore] - public void DelegateWithoutNameDeclarationTest() - { - string program = "public delegate void(int a, int secondParam, MyObj lastParam);\n"; - DelegateDeclaration dd = ParseUtilCSharp.ParseGlobal(program, true); - //Assert.AreEqual("System.Void", dd.ReturnType.Type); - //Assert.AreEqual("?", dd.Name); - TestParameters(dd); - } - - [Test, Ignore] + [Test, Ignore("Generics not yet supported")] public void GenericDelegateDeclarationTest() { - string program = "public delegate T CreateObject() where T : ICloneable;\n"; - DelegateDeclaration dd = ParseUtilCSharp.ParseGlobal(program); - Assert.AreEqual("CreateObject", dd.Name); - //Assert.AreEqual("T", dd.ReturnType.Type); - Assert.AreEqual(0, dd.Parameters.Count()); - /*Assert.AreEqual(1, dd.Templates.Count); - Assert.AreEqual("T", dd.Templates[0].Name); - Assert.AreEqual(1, dd.Templates[0].Bases.Count); - Assert.AreEqual("ICloneable", dd.Templates[0].Bases[0].Type);*/ throw new NotImplementedException(); + ParseUtilCSharp.AssertGlobal( + "public delegate T CreateObject() where T : ICloneable;", + new DelegateDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new SimpleType("T"), + Name = "CreateObject", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ICloneable") } + } + }}); } [Test] @@ -66,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope Assert.AreEqual("MyDelegate", ((DelegateDeclaration)nd.Members.Single()).Name); } - [Test, Ignore("inner classes not yet implemented")] + [Test] public void DelegateDeclarationInClass() { string program = "class Outer { delegate void Inner(); }"; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs index 525306bd6..874816450 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs @@ -70,85 +70,111 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope Assert.AreEqual(Modifiers.Static, td.Modifiers); } - [Test, Ignore] + [Test, Ignore("Generics not yet supported")] public void GenericClassTypeDeclarationTest() { - TypeDeclaration td = ParseUtilCSharp.ParseGlobal("public class G {}"); - - Assert.AreEqual(ClassType.Class, td.ClassType); - Assert.AreEqual("G", td.Name); - Assert.AreEqual(Modifiers.Public, td.Modifiers); - /*Assert.AreEqual(0, td.BaseTypes.Count); - Assert.AreEqual(1, td.TypeArguments.Count()); - Assert.AreEqual("T", td.TypeArguments.Single().Name);*/ throw new NotImplementedException(); + ParseUtilCSharp.AssertGlobal( + "public class G {}", + new TypeDeclaration { + Modifiers = Modifiers.Public, + ClassType = ClassType.Class, + Name = "G", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } } + }); } - - [Test, Ignore] + [Test, Ignore("Constraints not yet supported")] public void GenericClassWithWhere() { - string declr = @" -public class Test where T : IMyInterface -{ -} -"; - TypeDeclaration td = ParseUtilCSharp.ParseGlobal(declr); - - Assert.AreEqual(ClassType.Class, td.ClassType); - Assert.AreEqual("Test", td.Name); - - /*Assert.AreEqual(1, td.Templates.Count); - Assert.AreEqual("T", td.Templates[0].Name); - Assert.AreEqual("IMyInterface", td.Templates[0].Bases[0].Type);*/ throw new NotImplementedException(); + ParseUtilCSharp.AssertGlobal( + @"public class Test where T : IMyInterface { }", + new TypeDeclaration { + Modifiers = Modifiers.Public, + ClassType = ClassType.Class, + Name = "Test", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("IMyInterface") } + } + }}); } - [Test, Ignore] + [Test, Ignore("Generic classes not yet supported")] public void ComplexGenericClassTypeDeclarationTest() { - string declr = @" -public class Generic : System.IComparable where S : G where T : MyNamespace.IMyInterface -{ -} -"; - TypeDeclaration td = ParseUtilCSharp.ParseGlobal(declr); - - Assert.AreEqual(ClassType.Class, td.ClassType); - Assert.AreEqual("Generic", td.Name); - Assert.AreEqual(Modifiers.Public, td.Modifiers); - /*Assert.AreEqual(1, td.BaseTypes.Count); - Assert.AreEqual("System.IComparable", td.BaseTypes[0].Type); - - Assert.AreEqual(2, td.Templates.Count); - Assert.AreEqual("T", td.Templates[0].Name); - Assert.AreEqual("MyNamespace.IMyInterface", td.Templates[0].Bases[0].Type); - - Assert.AreEqual("S", td.Templates[1].Name); - Assert.AreEqual("G", td.Templates[1].Bases[0].Type); - Assert.AreEqual(1, td.Templates[1].Bases[0].GenericTypes.Count); - Assert.IsTrue(td.Templates[1].Bases[0].GenericTypes[0].IsArrayType); - Assert.AreEqual("T", td.Templates[1].Bases[0].GenericTypes[0].Type); - Assert.AreEqual(new int[] {0}, td.Templates[1].Bases[0].GenericTypes[0].RankSpecifier);*/ throw new NotImplementedException(); + ParseUtilCSharp.AssertGlobal( + "public class Generic : System.IComparable where S : G, new() where T : MyNamespace.IMyInterface", + new TypeDeclaration { + Modifiers = Modifiers.Public, + ClassType = ClassType.Class, + Name = "Generic", + TypeParameters = { + new TypeParameterDeclaration { Variance = VarianceModifier.Contravariant, Name = "T" }, + new TypeParameterDeclaration { Variance = VarianceModifier.Covariant, Name = "S" } + }, + BaseTypes = { + new MemberType { + Target = new SimpleType("System"), + MemberName = "IComparable" + } + }, + Constraints = { + new Constraint { + TypeParameter = "S", + BaseTypes = { + new SimpleType { + Identifier = "G", + TypeArguments = { new SimpleType("T").MakeArrayType() } + }, + new PrimitiveType("new") + } + }, + new Constraint { + TypeParameter = "T", + BaseTypes = { + new MemberType { + Target = new SimpleType("MyNamespace"), + MemberName = "IMyInterface" + } + } + } + } + }); } - [Test, Ignore] + [Test, Ignore("Base types not yet implemented")] public void ComplexClassTypeDeclarationTest() { - string declr = @" + ParseUtilCSharp.AssertGlobal( + @" [MyAttr()] public abstract class MyClass : MyBase, Interface1, My.Test.Interface2 { -} -"; - TypeDeclaration td = ParseUtilCSharp.ParseGlobal(declr); - - Assert.AreEqual(ClassType.Class, td.ClassType); - Assert.AreEqual("MyClass", td.Name); - Assert.AreEqual(Modifiers.Public | Modifiers.Abstract, td.Modifiers); - Assert.AreEqual(1, td.Attributes.Count()); - /* Assert.AreEqual(3, td.BaseTypes.Count); - Assert.AreEqual("MyBase", td.BaseTypes[0].Type); - Assert.AreEqual("Interface1", td.BaseTypes[1].Type); - Assert.AreEqual("My.Test.Interface2", td.BaseTypes[2].Type);*/ throw new NotImplementedException(); +}", + new TypeDeclaration { + Attributes = { + new AttributeSection { + Attributes = { + new Attribute { Type = new SimpleType("MyAttr") } + } + } + }, + Modifiers = Modifiers.Public | Modifiers.Abstract, + ClassType = ClassType.Class, + Name = "MyClass", + BaseTypes = { + new SimpleType("MyBase"), + new SimpleType("Interface1"), + new MemberType { + Target = new MemberType { + Target = new SimpleType("My"), + MemberName = "Test" + }, + MemberName = "Interface2" + } + }}); } [Test] @@ -178,27 +204,37 @@ public abstract class MyClass : MyBase, Interface1, My.Test.Interface2 Assert.AreEqual("MyEnum", td.Name); } - [Test, Ignore] + [Test, Ignore("Mono parser bug?")] public void ContextSensitiveKeywordTest() { - TypeDeclaration td = ParseUtilCSharp.ParseGlobal("partial class partial<[partial: where] where> where where : partial { }"); - - Assert.AreEqual(Modifiers.Partial, td.Modifiers); - Assert.AreEqual("partial", td.Name); - - /* - Assert.AreEqual(1, td.Templates.Count); - TemplateDefinition tp = td.Templates[0]; - Assert.AreEqual("where", tp.Name); - - Assert.AreEqual(1, tp.Attributes.Count); - Assert.AreEqual("partial", tp.Attributes[0].AttributeTarget); - Assert.AreEqual(1, tp.Attributes[0].Attributes.Count); - Assert.AreEqual("where", tp.Attributes[0].Attributes[0].Name); - - Assert.AreEqual(1, tp.Bases.Count); - Assert.AreEqual("partial", tp.Bases[0].Type); - Assert.AreEqual("where", tp.Bases[0].GenericTypes[0].Type);*/ throw new NotImplementedException(); + ParseUtilCSharp.AssertGlobal( + "partial class partial<[partial: where] where> where where : partial { }", + new TypeDeclaration { + Modifiers = Modifiers.Partial, + ClassType = ClassType.Class, + Name = "partial", + TypeParameters = { + new TypeParameterDeclaration { + Attributes = { + new AttributeSection { + AttributeTarget = AttributeTarget.Unknown, + Attributes = { new Attribute { Type = new SimpleType("where") } } + } + }, + Name = "where" + } + }, + Constraints = { + new Constraint { + TypeParameter = "where", + BaseTypes = { + new SimpleType { + Identifier = "partial", + TypeArguments = { new SimpleType("where") } + } + } + } + }}); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs index d79e33fe2..c9d4b7801 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope Assert.AreEqual("My.Name.Space", ud.Namespace); } - [Test] + [Test, Ignore("Aliases to generic types not yet supported")] public void UsingAliasDeclarationTest() { string program = "using TESTME=System;\n" + diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs index 94b282539..7522b0284 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs @@ -11,7 +11,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser /// /// Helper methods for parser unit tests. /// - public class ParseUtilCSharp + public static class ParseUtilCSharp { public static T ParseGlobal(string code, bool expectErrors = false) where T : AstNode { @@ -26,6 +26,14 @@ namespace ICSharpCode.NRefactory.CSharp.Parser return (T)node; } + public static void AssertGlobal(string code, AstNode expectedNode) + { + var node = ParseGlobal(code); + if (expectedNode.Match(node) == null) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedNode), ToCSharp(node)); + } + } + public static T ParseStatement(string stmt, bool expectErrors = false) where T : AstNode { CSharpParser parser = new CSharpParser(); @@ -39,6 +47,14 @@ namespace ICSharpCode.NRefactory.CSharp.Parser return (T)statement; } + public static void AssertStatement(string code, CSharp.Statement expectedStmt) + { + var stmt = ParseStatement(code); + if (expectedStmt.Match(stmt) == null) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedStmt), ToCSharp(stmt)); + } + } + public static T ParseExpression(string expr, bool expectErrors = false) where T : AstNode { if (expectErrors) Assert.Ignore("errors not yet implemented"); @@ -53,6 +69,14 @@ namespace ICSharpCode.NRefactory.CSharp.Parser return (T)parsedExpression; } + public static void AssertExpression(string code, CSharp.Expression expectedExpr) + { + var expr = ParseExpression(code); + if (expectedExpr.Match(expr) == null) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedExpr), ToCSharp(expr)); + } + } + public static T ParseTypeMember(string expr, bool expectErrors = false) where T : AttributedNode { if (expectErrors) Assert.Ignore("errors not yet implemented"); @@ -67,5 +91,20 @@ namespace ICSharpCode.NRefactory.CSharp.Parser Assert.IsTrue(type.IsAssignableFrom(m.GetType()), String.Format("Parsed member was {0} instead of {1} ({2})", m.GetType(), type, m)); return (T)m; } + + public static void AssertTypeMember(string code, CSharp.AttributedNode expectedMember) + { + var member = ParseTypeMember(code); + if (expectedMember.Match(member) == null) { + Assert.Fail("Expected '{0}' but was '{1}'", ToCSharp(expectedMember), ToCSharp(member)); + } + } + + static string ToCSharp(AstNode node) + { + StringWriter w = new StringWriter(); + node.AcceptVisitor(new OutputVisitor(w, new CSharpFormattingPolicy()), null); + return w.ToString(); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs index 08ff938b8..bf62bec0e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs @@ -6,14 +6,25 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Statements { - [TestFixture] + [TestFixture, Ignore("fixed is not implemented")] public class FixedStatementTests { [Test] public void FixedStatementTest() { FixedStatement fixedStmt = ParseUtilCSharp.ParseStatement("fixed (int* ptr = &myIntArr) { }"); - // TODO : Extend test. + ParseUtilCSharp.AssertStatement( + "fixed (int* ptr = &myIntArr) { }", + new FixedStatement { + Type = new PrimitiveType("int").MakePointerType(), + Variables = { + new VariableInitializer { + Name = "ptr", + Initializer = new UnaryOperatorExpression(UnaryOperatorType.AddressOf, new IdentifierExpression("myIntArr")) + } + }, + EmbeddedStatement = new BlockStatement() + }); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs index 1d0324f4a..fc18cdab4 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs @@ -10,11 +10,17 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Statements [TestFixture] public class ForStatementTests { - [Test] + [Test, Ignore("variable type in foreach is broken")] public void ForeachStatementTest() { - ForeachStatement foreachStmt = ParseUtilCSharp.ParseStatement("foreach (int i in myColl) {} "); - // TODO : Extend test. + ParseUtilCSharp.AssertStatement( + "foreach (int i in myColl) {} ", + new ForeachStatement { + VariableType = new PrimitiveType("int"), + VariableName = "i", + InExpression = new IdentifierExpression("myColl"), + EmbeddedStatement = new BlockStatement() + }); } [Test, Ignore("for statement is broken when Initializers.Count()!=1")] @@ -40,7 +46,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Statements Assert.IsTrue(inc.Expression is UnaryOperatorExpression); } - [Test, Ignore("for statement is broken when Initializers.Count()!=1")] + [Test] public void ForStatementTestMultipleInitializers() { ForStatement forStmt = ParseUtilCSharp.ParseStatement("for (i = 0, j = 1; i < 6; ++i) {} "); @@ -48,10 +54,12 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Statements Assert.IsTrue(forStmt.Iterators.All(i => i is ExpressionStatement)); } - [Test, Ignore("for statement is broken when Iterators.Count()!=1")] + [Test] public void ForStatementTestMultipleIterators() { - ForStatement forStmt = ParseUtilCSharp.ParseStatement("for (int i = 5; i < 6; ++i, j--) {} "); + ForStatement forStmt = ParseUtilCSharp.ParseStatement("for (int i = 5, j = 10; i < 6; ++i, j--) {} "); + Assert.AreEqual(1, forStmt.Initializers.Count()); + Assert.AreEqual(2, ((VariableDeclarationStatement)forStmt.Initializers.Single()).Variables.Count()); Assert.AreEqual(2, forStmt.Iterators.Count()); Assert.IsTrue(forStmt.Iterators.All(i => i is ExpressionStatement)); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs index 202b7f0ae..7187f4b5d 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs @@ -7,7 +7,7 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.Statements { - [TestFixture, Ignore] + [TestFixture] public class TryCatchStatementTests { [Test] @@ -20,28 +20,54 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Statements Assert.AreEqual(string.Empty, tryCatchStatement.CatchClauses.Single().VariableName); } - /* TODO port tests [Test] public void SimpleTryCatchStatementTest2() { - TryCatchStatement tryCatchStatement = ParseUtilCSharp.ParseStatement("try { } catch (Exception e) { } "); - Assert.IsTrue(tryCatchStatement.FinallyBlock.IsNull); - Assert.AreEqual(1, tryCatchStatement.CatchClauses.Count); - Assert.AreEqual("Exception", tryCatchStatement.CatchClauses[0].TypeReference.Type); - Assert.AreEqual("e", tryCatchStatement.CatchClauses[0].VariableName); + ParseUtilCSharp.AssertStatement( + "try { } catch (Exception e) { } ", + new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { + new CatchClause { + Type = new SimpleType("Exception"), + VariableName = "e", + Body = new BlockStatement() + } + }}); } [Test] public void SimpleTryCatchFinallyStatementTest() { - TryCatchStatement tryCatchStatement = ParseUtilCSharp.ParseStatement("try { } catch (Exception) { } catch { } finally { } "); - Assert.IsFalse(tryCatchStatement.FinallyBlock.IsNull); - Assert.AreEqual(2, tryCatchStatement.CatchClauses.Count); - Assert.AreEqual("Exception", tryCatchStatement.CatchClauses[0].TypeReference.Type); - Assert.IsEmpty(tryCatchStatement.CatchClauses[0].VariableName); - Assert.IsTrue(tryCatchStatement.CatchClauses[1].TypeReference.IsNull); - Assert.IsEmpty(tryCatchStatement.CatchClauses[1].VariableName); + ParseUtilCSharp.AssertStatement( + "try { } catch (Exception) { } catch { } finally { } ", + new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { + new CatchClause { + Type = new SimpleType("Exception"), + Body = new BlockStatement() + }, + new CatchClause { Body = new BlockStatement() } + }, + FinallyBlock = new BlockStatement() + }); + } + + [Test] + public void TestEmptyFinallyDoesNotMatchNullFinally() + { + TryCatchStatement c1 = new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { new CatchClause { Body = new BlockStatement() } } + }; + TryCatchStatement c2 = new TryCatchStatement { + TryBlock = new BlockStatement(), + CatchClauses = { new CatchClause { Body = new BlockStatement() } }, + FinallyBlock = new BlockStatement() + }; + Assert.IsNull(c1.Match(c2)); + Assert.IsNull(c2.Match(c1)); // and vice versa } - */ } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs index ae5598f2c..ae4d75d93 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs @@ -21,8 +21,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Statements [Test] public void YieldBreakStatementTest() { - YieldStatement yieldStmt = ParseUtilCSharp.ParseStatement("yield break;"); - Assert.IsTrue(yieldStmt.Expression.IsNull); + ParseUtilCSharp.ParseStatement("yield break;"); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs index fe1bd468c..7e9d13453 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs @@ -6,79 +6,84 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers { - [TestFixture, Ignore] + [TestFixture, Ignore("events are broken")] public class EventDeclarationTests { [Test] public void SimpleEventDeclarationTest() { - CustomEventDeclaration ed = ParseUtilCSharp.ParseTypeMember("event System.EventHandler MyEvent;"); - Assert.AreEqual("MyEvent", ed.Name); - //Assert.AreEqual("System.EventHandler", ed.TypeReference.Type); - Assert.Ignore(); // check type - - Assert.IsTrue(ed.AddAccessor.IsNull); - Assert.IsTrue(ed.RemoveAccessor.IsNull); + ParseUtilCSharp.AssertTypeMember( + "event EventHandler MyEvent;", + new EventDeclaration { + ReturnType = new SimpleType("EventHandler"), + Variables = { + new VariableInitializer { + Name = "MyEvent" + } + }}); } - /* TODO Port tests [Test] public void MultipleEventDeclarationTest() { - TypeDeclaration t = ParseUtilCSharp.ParseGlobal("class C { public event EventHandler A, B; }"); - Assert.AreEqual(2, t.Children.Count); - - EventDeclaration ed = (EventDeclaration)t.Children[0]; - Assert.AreEqual(Modifiers.Public, ed.Modifier); - Assert.AreEqual("EventHandler", ed.TypeReference.Type); - Assert.AreEqual("A", ed.Name); - - ed = (EventDeclaration)t.Children[1]; - Assert.AreEqual(Modifiers.Public, ed.Modifier); - Assert.AreEqual("EventHandler", ed.TypeReference.Type); - Assert.AreEqual("B", ed.Name); + ParseUtilCSharp.AssertTypeMember( + "public event EventHandler A = null, B = delegate {};", + new EventDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new SimpleType("EventHandler"), + Variables = { + new VariableInitializer { + Name = "A", + Initializer = new NullReferenceExpression() + }, + new VariableInitializer { + Name = "B", + Initializer = new AnonymousMethodExpression() + } + }}); } [Test] - public void EventImplementingInterfaceDeclarationTest() + public void AddRemoveEventDeclarationTest() { - EventDeclaration ed = ParseUtilCSharp.ParseTypeMember("event EventHandler MyInterface.MyEvent;"); - - Assert.AreEqual("MyEvent", ed.Name); - Assert.AreEqual("EventHandler", ed.TypeReference.Type); - - Assert.IsFalse(ed.HasAddRegion); - Assert.IsFalse(ed.HasRemoveRegion); - - Assert.AreEqual("MyInterface", ed.InterfaceImplementations[0].InterfaceType.Type); - Assert.AreEqual("MyEvent", ed.InterfaceImplementations[0].MemberName); + ParseUtilCSharp.AssertTypeMember( + "public event System.EventHandler MyEvent { add { } remove { } }", + new CustomEventDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new MemberType { + Target = new SimpleType("System"), + MemberName = "EventHandler" + }, + Name = "MyEvent", + AddAccessor = new Accessor { Body = new BlockStatement() }, + RemoveAccessor = new Accessor { Body = new BlockStatement() } + }); } [Test] public void EventImplementingGenericInterfaceDeclarationTest() { - EventDeclaration ed = ParseUtilCSharp.ParseTypeMember("event EventHandler MyInterface.MyEvent;"); - - Assert.AreEqual("MyEvent", ed.Name); - Assert.AreEqual("EventHandler", ed.TypeReference.Type); - - Assert.IsFalse(ed.HasAddRegion); - Assert.IsFalse(ed.HasRemoveRegion); - - Assert.AreEqual("MyInterface", ed.InterfaceImplementations[0].InterfaceType.Type); - Assert.AreEqual("System.String", ed.InterfaceImplementations[0].InterfaceType.GenericTypes[0].Type); - Assert.AreEqual("MyEvent", ed.InterfaceImplementations[0].MemberName); + ParseUtilCSharp.AssertTypeMember( + "event EventHandler MyInterface.MyEvent { add { } [Attr] remove {} }", + new CustomEventDeclaration { + ReturnType = new SimpleType("EventHandler"), + PrivateImplementationType = new SimpleType{ + Identifier = "MyInterface", + TypeArguments = { new PrimitiveType("string") } + }, + Name = "MyEvent", + AddAccessor = new Accessor { Body = new BlockStatement() }, + RemoveAccessor = new Accessor { + Attributes = { + new AttributeSection { + Attributes = { + new Attribute { Type = new SimpleType("Attr") } + } + } + }, + Body = new BlockStatement() + } + }); } - - [Test] - public void AddRemoveEventDeclarationTest() - { - EventDeclaration ed = ParseUtilCSharp.ParseTypeMember("event System.EventHandler MyEvent { add { } remove { } }"); - Assert.AreEqual("MyEvent", ed.Name); - Assert.AreEqual("System.EventHandler", ed.TypeReference.Type); - - Assert.IsTrue(ed.HasAddRegion); - Assert.IsTrue(ed.HasRemoveRegion); - }*/ } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs index f91cbed4a..6f47dc588 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs @@ -6,22 +6,62 @@ using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers { - [TestFixture, Ignore] + [TestFixture] public class FieldDeclarationTests { - [Test] + [Test, Ignore("multidimensional array rank incorrect?")] public void SimpleFieldDeclarationTest() { - throw new NotImplementedException(); - /* - FieldDeclaration fd = ParseUtilCSharp.ParseTypeMember("int[,,,] myField;"); - Assert.AreEqual("System.Int32", fd.TypeReference.Type); - Assert.AreEqual(new int[] { 3 } , fd.TypeReference.RankSpecifier); - Assert.AreEqual(1, fd.Fields.Count); - - Assert.AreEqual("myField", ((VariableDeclaration)fd.Fields[0]).Name);*/ + ParseUtilCSharp.AssertTypeMember( + "int[,,,] myField;", + new FieldDeclaration { + ReturnType = new PrimitiveType("int").MakeArrayType(4), + Variables = { new VariableInitializer("myField") } + }); + } + + [Test] + public void MultipleFieldDeclarationTest() + { + ParseUtilCSharp.AssertTypeMember( + "int a = 1, b = 2;", + new FieldDeclaration { + ReturnType = new PrimitiveType("int"), + Variables = { + new VariableInitializer("a", new PrimitiveExpression(1)), + new VariableInitializer("b", new PrimitiveExpression(2)), + } + }); } - // TODO add more tests + [Test] + public void FieldWithArrayInitializer() + { + ParseUtilCSharp.AssertTypeMember( + "public static readonly int[] arr = { 1, 2, 3 };", + new FieldDeclaration { + Modifiers = Modifiers.Public | Modifiers.Static | Modifiers.Readonly, + ReturnType = new PrimitiveType("int").MakeArrayType(), + Variables = { + new VariableInitializer { + Name = "arr", + Initializer = new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(1), + new PrimitiveExpression(2), + new PrimitiveExpression(3) + } + } + } + }}); + } + + [Test, Ignore("How do we represent fixed-size fields in the AST?")] + public void FieldWithFixedSize() + { + ParseUtilCSharp.AssertTypeMember( + "public unsafe fixed int Field[100];", + new FieldDeclaration()); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs index 90f14b26e..5353808fc 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs @@ -13,13 +13,16 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers [Test] public void IndexerDeclarationTest() { - IndexerDeclaration id = ParseUtilCSharp.ParseTypeMember("int this[int a, string b] { get { } set { } }"); + IndexerDeclaration id = ParseUtilCSharp.ParseTypeMember("public int this[int a, string b] { get { } protected set { } }"); Assert.AreEqual(2, id.Parameters.Count()); Assert.IsNotNull(id.Getter, "No get region found!"); Assert.IsNotNull(id.Setter, "No set region found!"); + Assert.AreEqual(Modifiers.Public, id.Modifiers); + Assert.AreEqual(Modifiers.None, id.Getter.Modifiers); + Assert.AreEqual(Modifiers.Protected, id.Setter.Modifiers); } - [Test, Ignore("type reference is not yet implemented")] + [Test, Ignore("explicit interface implementation not yet supported")] public void IndexerImplementingInterfaceTest() { IndexerDeclaration id = ParseUtilCSharp.ParseTypeMember("int MyInterface.this[int a, string b] { get { } set { } }"); @@ -27,21 +30,29 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers Assert.IsNotNull(id.Getter, "No get region found!"); Assert.IsNotNull(id.Setter, "No set region found!"); - Assert.AreEqual("MyInterface", id.PrivateImplementationType); + Assert.AreEqual("MyInterface", ((SimpleType)id.PrivateImplementationType).Identifier); } - [Test, Ignore] + [Test, Ignore("explicit interface implementation not yet supported")] public void IndexerImplementingGenericInterfaceTest() { - throw new NotImplementedException(); - /* - IndexerDeclaration id = ParseUtilCSharp.ParseTypeMember("int MyInterface.this[int a, string b] { get { } set { } }"); - Assert.AreEqual(2, id.Parameters.Count); - Assert.IsNotNull(id.GetAccessor, "No get region found!"); - Assert.IsNotNull(id.SetAccessor, "No set region found!"); - - Assert.AreEqual("MyInterface", id.InterfaceImplementations[0].InterfaceType.Type); - Assert.AreEqual("System.String", id.InterfaceImplementations[0].InterfaceType.GenericTypes[0].Type);*/ + ParseUtilCSharp.AssertTypeMember( + "int MyInterface.this[int a, string b] { get { } [Attr] set { } }", + new IndexerDeclaration { + ReturnType = new PrimitiveType("int"), + PrivateImplementationType = new SimpleType { + Identifier = "MyInterface", + TypeArguments = { new PrimitiveType("string") } + }, + Parameters = { + new ParameterDeclaration(new PrimitiveType("int"), "a"), + new ParameterDeclaration(new PrimitiveType("string"), "b") + }, + Getter = new Accessor { Body = new BlockStatement() }, + Setter = new Accessor { + Attributes = { new AttributeSection(new Attribute { Type = new SimpleType("Attr") }) }, + Body = new BlockStatement() + }}); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs index 53e0f3138..e3302d7c0 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs @@ -3,49 +3,50 @@ using System; using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers { - [TestFixture] + [TestFixture, Ignore("Generics not yet implemented")] public class MethodDeclarationTests { - [Test, Ignore("type references not yet implemented")] + [Test] public void SimpleMethodDeclarationTest() { MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("void MyMethod() {} "); - Assert.AreEqual("System.Void", md.ReturnType); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); Assert.AreEqual(0, md.Parameters.Count()); Assert.IsFalse(md.IsExtensionMethod); } - [Test, Ignore("type references not yet implemented")] + [Test] public void AbstractMethodDeclarationTest() { MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("abstract void MyMethod();"); - Assert.AreEqual("System.Void", md.ReturnType); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); Assert.AreEqual(0, md.Parameters.Count()); Assert.IsFalse(md.IsExtensionMethod); Assert.IsTrue(md.Body.IsNull); Assert.AreEqual(Modifiers.Abstract, md.Modifiers); } - [Test, Ignore("type references not yet implemented")] + [Test] public void DefiningPartialMethodDeclarationTest() { MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("partial void MyMethod();"); - Assert.AreEqual("System.Void", md.ReturnType); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); Assert.AreEqual(0, md.Parameters.Count()); Assert.IsFalse(md.IsExtensionMethod); Assert.IsTrue(md.Body.IsNull); Assert.AreEqual(Modifiers.Partial, md.Modifiers); } - [Test, Ignore("type references not yet implemented")] + [Test] public void ImplementingPartialMethodDeclarationTest() { MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("partial void MyMethod() { }"); - Assert.AreEqual("System.Void", md.ReturnType); + Assert.AreEqual("void", ((PrimitiveType)md.ReturnType).Keyword); Assert.AreEqual(0, md.Parameters.Count()); Assert.IsFalse(md.IsExtensionMethod); Assert.IsFalse(md.Body.IsNull); @@ -81,6 +82,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers Assert.AreEqual(2, md.StartLocation.Line, "StartLocation.Y"); Assert.AreEqual(5, md.EndLocation.Line, "EndLocation.Y"); Assert.AreEqual(3, md.StartLocation.Column, "StartLocation.X"); + Assert.AreEqual(4, md.EndLocation.Column, "EndLocation.X"); } [Test] @@ -89,142 +91,176 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("void MyMethod(int) {} ", true); Assert.AreEqual("System.Void", md.ReturnType); Assert.AreEqual(1, md.Parameters.Count()); - //Assert.AreEqual("?", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); + Assert.AreEqual("int", ((PrimitiveType)md.Parameters.Single().Type).Keyword); } - /* TODO: port unit tests [Test] public void GenericVoidMethodDeclarationTest() { - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("void MyMethod(T a) {} "); - Assert.AreEqual("System.Void", md.ReturnType); - Assert.AreEqual(1, md.Parameters.Count()); - Assert.AreEqual("T", md.Parameters.Single().Type); - Assert.AreEqual("a", md.Parameters.Single().Name); - - Assert.AreEqual(1, md.TypeParameters.Count()); - Assert.AreEqual("T", md.Templates[0].Name); + ParseUtilCSharp.AssertTypeMember( + "void MyMethod(T a) {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Body = new BlockStatement() + }); } [Test] public void GenericMethodDeclarationTest() { - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("T MyMethod(T a) {} "); - Assert.AreEqual("T", md.TypeReference.Type); - Assert.AreEqual(1, md.Parameters.Count); - Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); - Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); - - Assert.AreEqual(1, md.Templates.Count); - Assert.AreEqual("T", md.Templates[0].Name); + ParseUtilCSharp.AssertTypeMember( + "T MyMethod(T a) {} ", + new MethodDeclaration { + ReturnType = new SimpleType("T"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Body = new BlockStatement() + }); } [Test] public void GenericMethodDeclarationWithConstraintTest() { - string program = "T MyMethod(T a) where T : ISomeInterface {} "; - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember(program); - Assert.AreEqual("T", md.TypeReference.Type); - Assert.AreEqual(1, md.Parameters.Count); - Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); - Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); - - Assert.AreEqual(1, md.Templates.Count); - Assert.AreEqual("T", md.Templates[0].Name); - Assert.AreEqual(1, md.Templates[0].Bases.Count); - Assert.AreEqual("ISomeInterface", md.Templates[0].Bases[0].Type); + ParseUtilCSharp.AssertTypeMember( + "T MyMethod(T a) where T : ISomeInterface {} ", + new MethodDeclaration { + ReturnType = new SimpleType("T"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ISomeInterface") } + } + }, + Body = new BlockStatement() + }); } [Test] public void GenericMethodInInterface() { - const string program = @"interface MyInterface { + ParseUtilCSharp.AssertGlobal( + @"interface MyInterface { T MyMethod(T a) where T : ISomeInterface; } -"; - TypeDeclaration td = ParseUtilCSharp.ParseGlobal(program); - MethodDeclaration md = (MethodDeclaration)td.Children[0]; - Assert.AreEqual("T", md.TypeReference.Type); - Assert.AreEqual(1, md.Parameters.Count); - Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); - Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); - - Assert.AreEqual(1, md.Templates.Count); - Assert.AreEqual("T", md.Templates[0].Name); - Assert.AreEqual(1, md.Templates[0].Bases.Count); - Assert.AreEqual("ISomeInterface", md.Templates[0].Bases[0].Type); +", + new TypeDeclaration { + ClassType = ClassType.Interface, + Members = { + new MethodDeclaration { + ReturnType = new SimpleType("T"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ISomeInterface") } + } + } + }}}); } [Test] public void GenericVoidMethodInInterface() { - const string program = @"interface MyInterface { + ParseUtilCSharp.AssertGlobal( + @"interface MyInterface { void MyMethod(T a) where T : ISomeInterface; } -"; - TypeDeclaration td = ParseUtilCSharp.ParseGlobal(program); - MethodDeclaration md = (MethodDeclaration)td.Children[0]; - Assert.AreEqual("System.Void", md.TypeReference.Type); - Assert.AreEqual(1, md.Parameters.Count); - Assert.AreEqual("T", ((ParameterDeclarationExpression)md.Parameters[0]).TypeReference.Type); - Assert.AreEqual("a", ((ParameterDeclarationExpression)md.Parameters[0]).ParameterName); - - Assert.AreEqual(1, md.Templates.Count); - Assert.AreEqual("T", md.Templates[0].Name); - Assert.AreEqual(1, md.Templates[0].Bases.Count); - Assert.AreEqual("ISomeInterface", md.Templates[0].Bases[0].Type); +", + new TypeDeclaration { + ClassType = ClassType.Interface, + Members = { + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + Name = "MyMethod", + TypeParameters = { new TypeParameterDeclaration { Name = "T" } }, + Parameters = { new ParameterDeclaration(new SimpleType("T"), "a") }, + Constraints = { + new Constraint { + TypeParameter = "T", + BaseTypes = { new SimpleType("ISomeInterface") } + } + } + }}}); } [Test] public void ShadowingMethodInInterface() { - const string program = @"interface MyInterface : IDisposable { + ParseUtilCSharp.AssertGlobal( + @"interface MyInterface : IDisposable { new void Dispose(); } -"; - TypeDeclaration td = ParseUtilCSharp.ParseGlobal(program); - MethodDeclaration md = (MethodDeclaration)td.Children[0]; - Assert.AreEqual("System.Void", md.TypeReference.Type); - Assert.AreEqual(0, md.Parameters.Count); - Assert.AreEqual(Modifiers.New, md.Modifier); +", + new TypeDeclaration { + ClassType = ClassType.Interface, + BaseTypes = { new SimpleType("IDisposable") }, + Members = { + new MethodDeclaration { + Modifiers = Modifiers.New, + ReturnType = new PrimitiveType("void"), + Name = "Dispose" + }}}); } [Test] public void MethodImplementingInterfaceTest() { - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("int MyInterface.MyMethod() {} "); - Assert.AreEqual("System.Int32", md.TypeReference.Type); - - Assert.AreEqual("MyInterface", md.InterfaceImplementations[0].InterfaceType.Type); + ParseUtilCSharp.AssertGlobal( + "int MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("int"), + PrivateImplementationType = new SimpleType("MyInterface"), + Name = "MyMethod", + Body = new BlockStatement() + }); } [Test] public void MethodImplementingGenericInterfaceTest() { - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("int MyInterface.MyMethod() {} "); - Assert.AreEqual("System.Int32", md.TypeReference.Type); - - Assert.AreEqual("MyInterface", md.InterfaceImplementations[0].InterfaceType.Type); - Assert.AreEqual("System.String", md.InterfaceImplementations[0].InterfaceType.GenericTypes[0].Type); + ParseUtilCSharp.AssertGlobal( + "int MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("int"), + PrivateImplementationType = new SimpleType("MyInterface") { TypeArguments = { new PrimitiveType("string") } }, + Name = "MyMethod", + Body = new BlockStatement() + }); } [Test] public void VoidMethodImplementingInterfaceTest() { - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("void MyInterface.MyMethod() {} "); - Assert.AreEqual("System.Void", md.TypeReference.Type); - - Assert.AreEqual("MyInterface", md.InterfaceImplementations[0].InterfaceType.Type); + ParseUtilCSharp.AssertGlobal( + "void MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + PrivateImplementationType = new SimpleType("MyInterface"), + Name = "MyMethod", + Body = new BlockStatement() + }); } [Test] public void VoidMethodImplementingGenericInterfaceTest() { - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember("void MyInterface.MyMethod() {} "); - Assert.AreEqual("System.Void", md.TypeReference.Type); - - Assert.AreEqual("MyInterface", md.InterfaceImplementations[0].InterfaceType.Type); - Assert.AreEqual("System.String", md.InterfaceImplementations[0].InterfaceType.GenericTypes[0].Type); + ParseUtilCSharp.AssertGlobal( + "void MyInterface.MyMethod() {} ", + new MethodDeclaration { + ReturnType = new PrimitiveType("void"), + PrivateImplementationType = new SimpleType("MyInterface"), + Name = "MyMethod", + Body = new BlockStatement() + }); } [Test] @@ -234,9 +270,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers "void a() where T { }", true // expect errors ); Assert.AreEqual("a", md.Name); - Assert.AreEqual(1, md.Templates.Count); - Assert.AreEqual("T", md.Templates[0].Name); - Assert.AreEqual(0, md.Templates[0].Bases.Count); + Assert.AreEqual(1, md.TypeParameters.Count); + Assert.AreEqual("T", md.TypeParameters.Single().Name); + Assert.AreEqual(0, md.Constraints.Count()); } [Test] @@ -246,11 +282,11 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers "public static int ToInt32(this string s) { return int.Parse(s); }" ); Assert.AreEqual("ToInt32", md.Name); + Assert.AreEqual("s", md.Parameters.First().Name); + Assert.AreEqual(ParameterModifier.This, md.Parameters.First().ParameterModifier); + Assert.AreEqual("string", ((PrimitiveType)md.Parameters.First().Type).Keyword); Assert.IsTrue(md.IsExtensionMethod); - Assert.AreEqual("s", md.Parameters[0].ParameterName); - Assert.AreEqual("System.String", md.Parameters[0].TypeReference.Type); } - */ [Test] public void VoidExtensionMethodTest() @@ -265,7 +301,6 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers Assert.IsTrue(md.IsExtensionMethod); } - /* TODO [Test] public void MethodWithEmptyAssignmentErrorInBody() { @@ -277,27 +312,32 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers "}", true // expect errors ); Assert.AreEqual("A", md.Name); - Assert.AreEqual(new Location(1, 2), md.Body.StartLocation); - Assert.AreEqual(new Location(2, 5), md.Body.EndLocation); + Assert.AreEqual(new AstLocation(1, 2), md.Body.StartLocation); + Assert.AreEqual(new AstLocation(2, 5), md.Body.EndLocation); } [Test] public void OptionalParameterTest() { - MethodDeclaration md = ParseUtilCSharp.ParseTypeMember( - "public void Foo(string bar = null, int baz = 0) { }" - ); - Assert.AreEqual("Foo", md.Name); - - Assert.AreEqual("bar", md.Parameters[0].ParameterName); - Assert.AreEqual("System.String", md.Parameters[0].TypeReference.Type); - Assert.AreEqual(ParameterModifiers.In | ParameterModifiers.Optional, md.Parameters[0].ParamModifier); - Assert.IsNull(((PrimitiveExpression)md.Parameters[0].DefaultValue).Value); - - Assert.AreEqual("baz", md.Parameters[1].ParameterName); - Assert.AreEqual("System.Int32", md.Parameters[1].TypeReference.Type); - Assert.AreEqual(ParameterModifiers.In | ParameterModifiers.Optional, md.Parameters[1].ParamModifier); - Assert.AreEqual(0, ((PrimitiveExpression)md.Parameters[1].DefaultValue).Value); - }*/ + ParseUtilCSharp.AssertTypeMember( + "public void Foo(string bar = null, int baz = 0) { }", + new MethodDeclaration { + Modifiers = Modifiers.Public, + ReturnType = new PrimitiveType("void"), + Name = "Foo", + Body = new BlockStatement(), + Parameters = { + new ParameterDeclaration { + Type = new PrimitiveType("string"), + Name = "bar", + DefaultExpression = new NullReferenceExpression() + }, + new ParameterDeclaration { + Type = new PrimitiveType("int"), + Name = "baz", + DefaultExpression = new PrimitiveExpression(0) + } + }}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs index e2901f54e..4956d374a 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs @@ -10,43 +10,43 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers [TestFixture] public class OperatorDeclarationTests { - [Test, Ignore("type references not yet implemented")] + [Test] public void ImplictOperatorDeclarationTest() { OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static implicit operator double(MyObject f) { return 0.5d; }"); Assert.AreEqual(OperatorType.Implicit, od.OperatorType); Assert.AreEqual(1, od.Parameters.Count()); - Assert.AreEqual("System.Double", od.ReturnType); + Assert.AreEqual("double", ((PrimitiveType)od.ReturnType).Keyword); Assert.AreEqual("op_Implicit", od.Name); } - [Test, Ignore("type references not yet implemented")] + [Test] public void ExplicitOperatorDeclarationTest() { OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static explicit operator double(MyObject f) { return 0.5d; }"); Assert.AreEqual(OperatorType.Explicit, od.OperatorType); Assert.AreEqual(1, od.Parameters.Count()); - Assert.AreEqual("System.Double", od.ReturnType); + Assert.AreEqual("double", ((PrimitiveType)od.ReturnType).Keyword); Assert.AreEqual("op_Explicit", od.Name); } - [Test, Ignore("type references not yet implemented")] + [Test] public void BinaryPlusOperatorDeclarationTest() { OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static MyObject operator +(MyObject a, MyObject b) {}"); Assert.AreEqual(OperatorType.Addition, od.OperatorType); Assert.AreEqual(2, od.Parameters.Count()); - Assert.AreEqual("MyObject", od.ReturnType); + Assert.AreEqual("MyObject", ((SimpleType)od.ReturnType).Identifier); Assert.AreEqual("op_Addition", od.Name); } - [Test, Ignore("type references not yet implemented")] + [Test] public void UnaryPlusOperatorDeclarationTest() { OperatorDeclaration od = ParseUtilCSharp.ParseTypeMember("public static MyObject operator +(MyObject a) {}"); Assert.AreEqual(OperatorType.UnaryPlus, od.OperatorType); Assert.AreEqual(1, od.Parameters.Count()); - Assert.AreEqual("MyObject", od.ReturnType); + Assert.AreEqual("MyObject", ((SimpleType)od.ReturnType).Identifier); Assert.AreEqual("op_UnaryPlus", od.Name); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs index 5c4bebed3..fba68f26e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers Assert.AreEqual(new AstLocation(4, code.IndexOf("}\n\t}") + 1 - line4Pos + 1), pd.Setter.Body.EndLocation); } - [Test, Ignore("type references not yet implemented")] + [Test, Ignore("explicit interface implementation not yet implemented")] public void PropertyImplementingInterfaceTest() { PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyInterface.MyProperty { get {} } "); @@ -74,10 +74,10 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers Assert.IsFalse(pd.Getter.IsNull); Assert.IsTrue(pd.Setter.IsNull); - Assert.AreEqual("MyInterface", pd.PrivateImplementationType); + Assert.AreEqual("MyInterface", ((SimpleType)pd.PrivateImplementationType).Identifier); } - [Test, Ignore("type references not yet implemented")] + [Test, Ignore("explicit interface implementation not yet implemented")] public void PropertyImplementingGenericInterfaceTest() { PropertyDeclaration pd = ParseUtilCSharp.ParseTypeMember("int MyInterface.MyProperty { get {} } "); @@ -85,9 +85,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers Assert.IsFalse(pd.Getter.IsNull); Assert.IsTrue(pd.Setter.IsNull); - throw new NotImplementedException(); - //Assert.AreEqual("MyInterface", pd.InterfaceImplementations[0].InterfaceType.Type); - //Assert.AreEqual("System.String", pd.InterfaceImplementations[0].InterfaceType.GenericTypes[0].Type); + Assert.IsNotNull(new SimpleType { Identifier = "MyInterface", TypeArguments = { new PrimitiveType("string") } }.Match(pd.PrivateImplementationType)); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs index 11ab8c47c..2f84aa28c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs @@ -122,7 +122,7 @@ class A { Assert.AreEqual("System.Void", Resolve(program).Type.ReflectionName); } - [Test] + [Test, Ignore("parser is broken for events")] public void EventCallTest() { string program = @"using System; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs index 374817f4d..40cd75b3b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs @@ -366,7 +366,7 @@ class TestClass { Assert.AreEqual("System.Collections.ArrayList", member.Type.FullName, "the full type should be resolved"); } - [Test] + [Test, Ignore("Parser position bug")] public void ImportAliasNamespaceResolveTest() { NamespaceResolveResult ns; @@ -394,7 +394,7 @@ class TestClass { Assert.AreEqual("System.Collections.ArrayList", rr.Type.FullName, "a"); } - [Test] + [Test, Ignore("Parser position bug")] public void ResolveNamespaceSD_863() { string program = @"using System; @@ -432,7 +432,7 @@ namespace A.B { Assert.AreEqual("A.B.C", trr.Type.FullName); } - [Test] + [Test, Ignore("parser is broken and produces IdentifierExpression instead of PrimitiveType")] public void ShortMaxValueTest() { string program = @"using System; @@ -471,7 +471,7 @@ class TestClass { Assert.AreEqual("XX.XX.Test", mrr.Member.FullName); } - [Test] + [Test, Ignore("Parser position bug")] public void ClassNameLookup1() { string program = @"namespace MainNamespace { @@ -490,7 +490,7 @@ namespace Test.Subnamespace { Assert.AreEqual("Test.Subnamespace.Test.TheClass", trr.Type.FullName); } - [Test] + [Test, Ignore("Parser position bug")] public void ClassNameLookup2() { string program = @"using Test.Subnamespace; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs index bf77b15c9..f5ef169b6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs @@ -9,7 +9,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class UnsafeCodeTests : ResolverTestBase { - [Test, Ignore("Parser produces parse tree that doesn't match DOM definition??")] + [Test, Ignore("fixed statement not implemented in parser")] public void FixedStatement() { string program = @"using System; diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index f08560c21..7bc0981b5 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -11,6 +11,7 @@ Properties 10.0.0 2.0 + Client x86 diff --git a/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj b/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj index db980b370..fef832cb3 100644 --- a/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj +++ b/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj @@ -19,6 +19,7 @@ 4 v4.0 false + Client True diff --git a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj index 52d851010..477002241 100644 --- a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj +++ b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj @@ -9,6 +9,7 @@ ICSharpCode.NRefactory.VB v4.0 Properties + Client x86 diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs index 511d6fd06..2d0a5a796 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs @@ -57,11 +57,11 @@ namespace ICSharpCode.NRefactory.CSharp get { return column; } } - public override bool Equals (object other) + public override bool Equals (object obj) { - if (!(other is AstLocation)) + if (!(obj is AstLocation)) return false; - return (AstLocation)other == this; + return (AstLocation)obj == this; } public override int GetHashCode () diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs index a5361ef4f..2dab5a5ad 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs @@ -606,6 +606,11 @@ namespace ICSharpCode.NRefactory.CSharp } protected internal abstract bool DoMatch(AstNode other, Match match); + + internal virtual bool DoMatchCollection(Role role, AstNode pos, Match match, Stack backtrackingStack) + { + return DoMatch(pos, match); + } #endregion // the Root role must be available when creating the null nodes, so we can't put it in the Roles class diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs index 033ad7913..c7f266d97 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs @@ -174,18 +174,12 @@ namespace ICSharpCode.NRefactory.CSharp if (cur1 == null) break; - Pattern pattern = cur1 as Pattern; - if (pattern == null && cur1.NodeType == NodeType.Placeholder) - pattern = cur1.GetChildByRole(TypePlaceholder.ChildRole) as Pattern; - if (pattern != null) { - Debug.Assert(stack.Count == patternStack.Count); - success = pattern.DoMatchCollection(role, cur2, match, stack); - Debug.Assert(stack.Count >= patternStack.Count); - while (stack.Count > patternStack.Count) - patternStack.Push(cur1.NextSibling); - } else { - success = cur1.DoMatch(cur2, match); - } + Debug.Assert(stack.Count == patternStack.Count); + success = cur1.DoMatchCollection(role, cur2, match, stack); + Debug.Assert(stack.Count >= patternStack.Count); + while (stack.Count > patternStack.Count) + patternStack.Push(cur1.NextSibling); + cur1 = cur1.NextSibling; if (cur2 != null) cur2 = cur2.NextSibling; diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs index 08bf473d4..a35204e3c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp return new ComposedType { BaseType = this }.MakePointerType(); } - public virtual AstType MakeArrayType(int rank) + public virtual AstType MakeArrayType(int rank = 1) { return new ComposedType { BaseType = this }.MakeArrayType(rank); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs b/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs index 6b2b12959..ec0a85705 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs @@ -48,6 +48,12 @@ namespace ICSharpCode.NRefactory.CSharp } } + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CSharpModifierToken o = other as CSharpModifierToken; + return o != null && this.modifier == o.modifier; + } + // Not worth using a dictionary for such few elements. // This table is sorted in the order that modifiers should be output when generating code. static readonly List> lengthTable = new List> () { diff --git a/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs b/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs index 4e6288963..a776f259f 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs @@ -88,7 +88,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { CSharpTokenNode o = other as CSharpTokenNode; - return o != null; + return o != null && !o.IsNull && !(o is CSharpModifierToken); } public override string ToString () diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs index 6578c5826..dffc3dd3d 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs @@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ArrayCreateExpression o = other as ArrayCreateExpression; - return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match) && this.Initializer.DoMatch(o.Initializer, match); + return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match) && this.AdditionalArraySpecifiers.DoMatch(o.AdditionalArraySpecifiers, match) && this.Initializer.DoMatch(o.Initializer, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs index 79a357e87..9841a7468 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { QueryExpression o = other as QueryExpression; - return o != null && this.Clauses.DoMatch(o.Clauses, match); + return o != null && !o.IsNull && this.Clauses.DoMatch(o.Clauses, match); } } @@ -54,12 +54,6 @@ namespace ICSharpCode.NRefactory.CSharp public override NodeType NodeType { get { return NodeType.QueryClause; } } - - protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) - { - QueryClause o = other as QueryClause; - throw new NotImplementedException(); - } } /// @@ -103,6 +97,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQueryContinuationClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryContinuationClause o = other as QueryContinuationClause; + return o != null && MatchString(this.Identifier, o.Identifier) && this.PrecedingQuery.DoMatch(o.PrecedingQuery, match); + } } public class QueryFromClause : QueryClause @@ -133,6 +133,13 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQueryFromClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryFromClause o = other as QueryFromClause; + return o != null && this.Type.DoMatch(o.Type, match) && MatchString(this.Identifier, o.Identifier) + && this.Expression.DoMatch(o.Expression, match); + } } public class QueryLetClause : QueryClause @@ -163,6 +170,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQueryLetClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryLetClause o = other as QueryLetClause; + return o != null && MatchString(this.Identifier, o.Identifier) && this.Expression.DoMatch(o.Expression, match); + } } @@ -181,6 +194,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQueryWhereClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryWhereClause o = other as QueryWhereClause; + return o != null && this.Condition.DoMatch(o.Condition, match); + } } /// @@ -266,6 +285,16 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQueryJoinClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryJoinClause o = other as QueryJoinClause; + return o != null && this.IsGroupJoin == o.IsGroupJoin + && this.Type.DoMatch(o.Type, match) && MatchString(this.JoinIdentifier, o.JoinIdentifier) + && this.InExpression.DoMatch(o.InExpression, match) && this.OnExpression.DoMatch(o.OnExpression, match) + && this.EqualsExpression.DoMatch(o.EqualsExpression, match) + && MatchString(this.IntoIdentifier, o.IntoIdentifier); + } } public class QueryOrderClause : QueryClause @@ -284,6 +313,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQueryOrderClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryOrderClause o = other as QueryOrderClause; + return o != null && this.Orderings.DoMatch(o.Orderings, match); + } } public class QueryOrdering : AstNode @@ -340,6 +375,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQuerySelectClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QuerySelectClause o = other as QuerySelectClause; + return o != null && this.Expression.DoMatch(o.Expression, match); + } } public class QueryGroupClause : QueryClause @@ -371,5 +412,11 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitQueryGroupClause (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + QueryGroupClause o = other as QueryGroupClause; + return o != null && this.Projection.DoMatch(o.Projection, match) && this.Key.DoMatch(o.Key, match); + } } } \ No newline at end of file diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs index a192718da..901f6ba06 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs @@ -64,6 +64,15 @@ namespace ICSharpCode.NRefactory.CSharp return o != null && this.AttributeTarget == o.AttributeTarget && this.Attributes.DoMatch(o.Attributes, match); } + public AttributeSection() + { + } + + public AttributeSection(Attribute attr) + { + this.Attributes.Add(attr); + } + public static string GetAttributeTargetName(AttributeTarget attributeTarget) { switch (attributeTarget) { diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs index 514a41192..8bac245c7 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs @@ -31,6 +31,9 @@ namespace ICSharpCode.NRefactory.CSharp /// /// where TypeParameter : BaseTypes /// + /// + /// new(), struct and class constraints are represented using a PrimitiveType "new", "struct" or "class" + /// public class Constraint : AstNode { public readonly static Role ColonRole = TypeDeclaration.ColonRole; @@ -51,8 +54,6 @@ namespace ICSharpCode.NRefactory.CSharp } } - // TODO: what about new(), struct and class constraints? - public AstNodeCollection BaseTypes { get { return GetChildrenByRole (BaseTypeRole); } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs index eccac9382..e014a4b3f 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs @@ -40,6 +40,11 @@ namespace ICSharpCode.NRefactory.CSharp } } + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + public string Name { get { return GetChildByRole (Roles.Identifier).Name; @@ -49,11 +54,6 @@ namespace ICSharpCode.NRefactory.CSharp } } - public AstType ReturnType { - get { return GetChildByRole (Roles.Type); } - set { SetChildByRole (Roles.Type, value); } - } - public AstNodeCollection TypeParameters { get { return GetChildrenByRole (Roles.TypeParameter); } } @@ -78,5 +78,14 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitDelegateDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + DelegateDeclaration o = other as DelegateDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && this.ReturnType.DoMatch(o.ReturnType, match) && MatchString(this.Name, o.Name) + && this.TypeParameters.DoMatch(o.TypeParameters, match) && this.Parameters.DoMatch(o.Parameters, match) + && this.Constraints.DoMatch(o.Constraints, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs index fd638f2da..df7ac2138 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs @@ -87,5 +87,14 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitTypeDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeDeclaration o = other as TypeDeclaration; + return o != null && this.ClassType == o.ClassType && this.MatchAttributesAndModifiers(o, match) + && MatchString(this.Name, o.Name) && this.TypeParameters.DoMatch(o.TypeParameters, match) + && this.BaseTypes.DoMatch(o.BaseTypes, match) && this.Constraints.DoMatch(o.Constraints, match) + && this.Members.DoMatch(o.Members, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs index 30e2fdf2f..84c9b2f50 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs @@ -15,12 +15,17 @@ namespace ICSharpCode.NRefactory.CSharp /// public class TypeParameterDeclaration : AstNode { + public static readonly Role AttributeRole = AttributedNode.AttributeRole; public static readonly Role VarianceRole = new Role("Variance"); public override NodeType NodeType { get { return NodeType.Unknown; } } + public AstNodeCollection Attributes { + get { return GetChildrenByRole (AttributeRole); } + } + public VarianceModifier Variance { get; set; } @@ -42,7 +47,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { TypeParameterDeclaration o = other as TypeParameterDeclaration; - return o != null && this.Variance == o.Variance && MatchString(this.Name, o.Name); + return o != null && this.Variance == o.Variance && MatchString(this.Name, o.Name) && this.Attributes.DoMatch(o.Attributes, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs b/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs index f63e97bf7..2db1b06e0 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs @@ -43,6 +43,11 @@ namespace ICSharpCode.NRefactory.CSharp { return default (S); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } } public override NodeType NodeType { @@ -95,7 +100,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { Identifier o = other as Identifier; - return o != null && MatchString(this.Name, o.Name); + return o != null && !o.IsNull && MatchString(this.Name, o.Name); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs b/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs index 70448e56a..b91048a5c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.NRefactory.CSharp b.Append(this.MemberName); if (this.TypeArguments.Any()) { b.Append('<'); - b.Append(string.Join(", ", this.TypeArguments)); + b.Append(DotNet35Compat.StringJoin(", ", this.TypeArguments)); b.Append('>'); } return b.ToString(); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs index 073415f51..37c89a58e 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Pattern.cs @@ -29,34 +29,29 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching } } - internal virtual bool DoMatchCollection(Role role, AstNode pos, Match match, Stack backtrackingStack) + public static implicit operator AstType(Pattern p) { - return DoMatch(pos, match); + return p != null ? new TypePlaceholder(p) : null; } - public AstType ToType() + public static implicit operator Expression(Pattern p) { - return new TypePlaceholder(this); + return p != null ? new ExpressionPlaceholder(p) : null; } - public Expression ToExpression() + public static implicit operator Statement(Pattern p) { - return new ExpressionPlaceholder(this); + return p != null ? new StatementPlaceholder(p) : null; } - public Statement ToStatement() + public static implicit operator BlockStatement(Pattern p) { - return new StatementPlaceholder(this); + return p != null ? new BlockStatementPlaceholder(p) : null; } - public BlockStatement ToBlock() + public static implicit operator VariableInitializer(Pattern p) { - return new BlockStatementPlaceholder(this); - } - - public VariableInitializer ToVariable() - { - return new VariablePlaceholder(this); + return p != null ? new VariablePlaceholder(p) : null; } // Make debugging easier by giving Patterns a ToString() implementation diff --git a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs index 2bac1c6e1..f68feb443 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/PatternMatching/Placeholder.cs @@ -2,16 +2,19 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Collections.Generic; namespace ICSharpCode.NRefactory.CSharp.PatternMatching { + // Placeholders do not store their child in the AST tree; but keep it as a separate child. + // This allows reusing the child in multiple placeholders; thus enabling the sharing of AST subtrees. sealed class TypePlaceholder : AstType { - public static readonly Role ChildRole = new Role("Child", AstNode.Null); + readonly AstNode child; public TypePlaceholder(AstNode child) { - AddChild(child, TypePlaceholder.ChildRole); + this.child = child; } public override NodeType NodeType { @@ -20,20 +23,27 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching public override S AcceptVisitor(IAstVisitor visitor, T data) { - return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, GetChildByRole(TypePlaceholder.ChildRole), data); + return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, child, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, 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); } } sealed class ExpressionPlaceholder : Expression { + readonly AstNode child; + public ExpressionPlaceholder(AstNode child) { - AddChild(child, TypePlaceholder.ChildRole); + this.child = child; } public override NodeType NodeType { @@ -42,20 +52,27 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching public override S AcceptVisitor(IAstVisitor visitor, T data) { - return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, GetChildByRole(TypePlaceholder.ChildRole), data); + return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, child, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, 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); } } sealed class StatementPlaceholder : Statement { + readonly AstNode child; + public StatementPlaceholder(AstNode child) { - AddChild(child, TypePlaceholder.ChildRole); + this.child = child; } public override NodeType NodeType { @@ -64,20 +81,27 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching public override S AcceptVisitor(IAstVisitor visitor, T data) { - return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, GetChildByRole(TypePlaceholder.ChildRole), data); + return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, child, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, 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); } } sealed class BlockStatementPlaceholder : BlockStatement { + readonly AstNode child; + public BlockStatementPlaceholder(AstNode child) { - AddChild(child, TypePlaceholder.ChildRole); + this.child = child; } public override NodeType NodeType { @@ -86,20 +110,27 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching public override S AcceptVisitor(IAstVisitor visitor, T data) { - return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, GetChildByRole(TypePlaceholder.ChildRole), data); + return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, child, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, 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); } } sealed class VariablePlaceholder : VariableInitializer { + readonly AstNode child; + public VariablePlaceholder(AstNode child) { - AddChild(child, TypePlaceholder.ChildRole); + this.child = child; } public override NodeType NodeType { @@ -108,12 +139,17 @@ namespace ICSharpCode.NRefactory.CSharp.PatternMatching public override S AcceptVisitor(IAstVisitor visitor, T data) { - return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, GetChildByRole(TypePlaceholder.ChildRole), data); + return ((IPatternAstVisitor)visitor).VisitPlaceholder(this, child, data); } protected internal override bool DoMatch(AstNode other, Match match) { - return GetChildByRole(TypePlaceholder.ChildRole).DoMatch(other, 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/SimpleType.cs b/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs index 55839229c..237b3b55b 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs @@ -76,7 +76,7 @@ namespace ICSharpCode.NRefactory.CSharp StringBuilder b = new StringBuilder(this.Identifier); if (this.TypeArguments.Any()) { b.Append('<'); - b.Append(string.Join(", ", this.TypeArguments)); + b.Append(DotNet35Compat.StringJoin(", ", this.TypeArguments)); b.Append('>'); } return b.ToString(); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs b/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs index d43a0d538..9ee89966d 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs @@ -77,7 +77,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { BlockStatement o = other as BlockStatement; - return o != null && this.Statements.DoMatch(o.Statements, match); + return o != null && !o.IsNull && this.Statements.DoMatch(o.Statements, match); } #region Builder methods diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs b/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs index b1b7759f0..9a8efbc9a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { FixedStatement o = other as FixedStatement; - return o != null && this.Variables.DoMatch(o.Variables, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); + return o != null && this.Type.DoMatch(o.Type, match) && this.Variables.DoMatch(o.Variables, match) && this.EmbeddedStatement.DoMatch(o.EmbeddedStatement, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs index 910aec75f..c487032eb 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs @@ -64,7 +64,8 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { - throw new NotImplementedException(); + Accessor o = other as Accessor; + return o != null && !o.IsNull && this.MatchAttributesAndModifiers(o, match) && this.Body.DoMatch(o.Body, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs index 1b878d91c..41eec380d 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs @@ -58,9 +58,9 @@ namespace ICSharpCode.NRefactory.CSharp } } - protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.CSharp.PatternMatching.Match match) + protected bool MatchAttributesAndModifiers(AttributedNode o, PatternMatching.Match match) { - throw new NotImplementedException(); + return this.Modifiers == o.Modifiers && this.Attributes.DoMatch(o.Attributes, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs index 97f808051..4971a4eec 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs @@ -70,6 +70,13 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitConstructorDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ConstructorDeclaration o = other as ConstructorDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) && this.Parameters.DoMatch(o.Parameters, match) + && this.Initializer.DoMatch(o.Initializer, match) && this.Body.DoMatch(o.Body, match); + } } public enum ConstructorInitializerType { @@ -98,6 +105,11 @@ namespace ICSharpCode.NRefactory.CSharp { return default (S); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } } public override NodeType NodeType { @@ -123,7 +135,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ConstructorInitializer o = other as ConstructorInitializer; - return o != null && this.ConstructorInitializerType == o.ConstructorInitializerType && this.Arguments.DoMatch(o.Arguments, match); + return o != null && !o.IsNull && this.ConstructorInitializerType == o.ConstructorInitializerType && this.Arguments.DoMatch(o.Arguments, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs index 2798d0660..8a892b275 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs @@ -1,6 +1,6 @@ // // DestructorDeclaration.cs -// +// // Author: // Mike Krüger // @@ -61,5 +61,11 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitDestructorDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + DestructorDeclaration o = other as DestructorDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) && this.Body.DoMatch(o.Body, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs index 0715898f0..e2784f565 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs @@ -1,6 +1,6 @@ -// +// // EnumMemberDeclaration.cs -// +// // Author: // Mike Krüger // @@ -53,6 +53,13 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitEnumMemberDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + EnumMemberDeclaration o = other as EnumMemberDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && MatchString(this.Name, o.Name) && this.Initializer.DoMatch(o.Initializer, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs index 3a916782d..49d28ede3 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs @@ -28,8 +28,17 @@ using System.Collections.Generic; namespace ICSharpCode.NRefactory.CSharp { - public class EventDeclaration : MemberDeclaration + public class EventDeclaration : AttributedNode { + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + public AstNodeCollection Variables { get { return GetChildrenByRole (Roles.Variable); } } @@ -38,6 +47,13 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitEventDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + EventDeclaration o = other as EventDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && this.ReturnType.DoMatch(o.ReturnType, match) && this.Variables.DoMatch(o.Variables, match); + } } public class CustomEventDeclaration : MemberDeclaration @@ -67,5 +83,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitCustomEventDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CustomEventDeclaration o = other as CustomEventDeclaration; + return o != null && this.MatchMember(o, match) + && this.AddAccessor.DoMatch(o.AddAccessor, match) && this.RemoveAccessor.DoMatch(o.RemoveAccessor, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs index 3ca04772d..1003aa9b7 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs @@ -1,6 +1,6 @@ // // FieldDeclaration.cs -// +// // Author: // Mike Krüger // @@ -29,9 +29,18 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp { - public class FieldDeclaration : MemberDeclaration + public class FieldDeclaration : AttributedNode { - public AstNodeCollection Variables { + public override NodeType NodeType { + get { return NodeType.Member; } + } + + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AstNodeCollection Variables { get { return GetChildrenByRole (Roles.Variable); } } @@ -39,5 +48,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitFieldDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + FieldDeclaration o = other as FieldDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) + && this.ReturnType.DoMatch(o.ReturnType, match) && this.Variables.DoMatch(o.Variables, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs index 5b63c9c4f..4d19c97d7 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs @@ -1,6 +1,6 @@ // // IndexerDeclaration.cs -// +// // Author: // Mike Krüger // @@ -29,13 +29,16 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp { - public class IndexerDeclaration : PropertyDeclaration + public class IndexerDeclaration : MemberDeclaration { + public static readonly Role GetterRole = PropertyDeclaration.GetterRole; + public static readonly Role SetterRole = PropertyDeclaration.SetterRole; + public CSharpTokenNode LBracketToken { get { return GetChildByRole (Roles.LBracket); } } - public AstNodeCollection Parameters { + public AstNodeCollection Parameters { get { return GetChildrenByRole (Roles.Parameter); } } @@ -43,9 +46,34 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBracket); } } + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public Accessor Getter { + get { return GetChildByRole(GetterRole); } + set { SetChildByRole(GetterRole, value); } + } + + public Accessor Setter { + get { return GetChildByRole(SetterRole); } + set { SetChildByRole(SetterRole, value); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitIndexerDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + IndexerDeclaration o = other as IndexerDeclaration; + return o != null && this.MatchMember(o, match) && this.Parameters.DoMatch(o.Parameters, match) + && this.Getter.DoMatch(o.Getter, match) && this.Setter.DoMatch(o.Setter, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs index 5cd468cfe..a7e1b74e4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs @@ -55,5 +55,11 @@ namespace ICSharpCode.NRefactory.CSharp public override NodeType NodeType { get { return NodeType.Member; } } + + protected bool MatchMember(MemberDeclaration o, PatternMatching.Match match) + { + return MatchAttributesAndModifiers(o, match) && this.ReturnType.DoMatch(o.ReturnType, match) + && this.PrivateImplementationType.DoMatch(o.PrivateImplementationType, match) && MatchString(this.Name, o.Name); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs index ef740bd86..556c0a3a4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs @@ -1,6 +1,6 @@ // // MethodDeclaration.cs -// +// // Author: // Mike Krüger // @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.LPar); } } - public AstNodeCollection Parameters { + public AstNodeCollection Parameters { get { return GetChildrenByRole (Roles.Parameter); } } @@ -47,7 +47,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RPar); } } - public AstNodeCollection Constraints { + public AstNodeCollection Constraints { get { return GetChildrenByRole (Roles.Constraint); } } @@ -67,5 +67,13 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitMethodDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + MethodDeclaration o = other as MethodDeclaration; + return o != null && this.MatchMember(o, match) && this.TypeParameters.DoMatch(o.TypeParameters, match) + && this.Parameters.DoMatch(o.Parameters, match) && this.Constraints.DoMatch(o.Constraints, match) + && this.Body.DoMatch(o.Body, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs index c8a326c49..7215412eb 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs @@ -1,6 +1,6 @@ // // OperatorDeclaration.cs -// +// // Author: // Mike Krüger // @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp Explicit } - public class OperatorDeclaration : MemberDeclaration + public class OperatorDeclaration : AttributedNode { public static readonly Role OperatorTypeRole = new Role("OperatorType", CSharpTokenNode.Null); public static readonly Role OperatorKeywordRole = Roles.Keyword; @@ -76,11 +76,16 @@ namespace ICSharpCode.NRefactory.CSharp set; } + public AstType ReturnType { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + public CSharpTokenNode LParToken { get { return GetChildByRole (Roles.LPar); } } - public AstNodeCollection Parameters { + public AstNodeCollection Parameters { get { return GetChildrenByRole (Roles.Parameter); } } @@ -103,9 +108,25 @@ namespace ICSharpCode.NRefactory.CSharp return Mono.CSharp.Operator.GetName((Mono.CSharp.Operator.OpType)type); } + public override NodeType NodeType { + get { return NodeType.Member; } + } + public override S AcceptVisitor (IAstVisitor visitor, T data) { return visitor.VisitOperatorDeclaration (this, data); } + + public string Name { + get { return GetName(this.OperatorType); } + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + OperatorDeclaration o = other as OperatorDeclaration; + return o != null && this.MatchAttributesAndModifiers(o, match) && this.OperatorType == o.OperatorType + && this.ReturnType.DoMatch(o.ReturnType, match) + && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs index 0334d2a3f..5544c5aa7 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs @@ -85,7 +85,19 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { ParameterDeclaration o = other as ParameterDeclaration; - return o != null && this.Attributes.DoMatch(o.Attributes, match) && this.ParameterModifier == o.ParameterModifier && MatchString(this.Name, o.Name) && this.DefaultExpression.DoMatch(o.DefaultExpression, match); + return o != null && this.Attributes.DoMatch(o.Attributes, match) && this.ParameterModifier == o.ParameterModifier + && this.Type.DoMatch(o.Type, match) && MatchString(this.Name, o.Name) + && this.DefaultExpression.DoMatch(o.DefaultExpression, match); + } + + public ParameterDeclaration() + { + } + + public ParameterDeclaration(AstType type, string name) + { + this.Type = type; + this.Name = name; } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs index d13ce8f5c..2d1376a0e 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs @@ -1,6 +1,6 @@ -// +// // PropertyDeclaration.cs -// +// // Author: // Mike Krüger // @@ -53,5 +53,12 @@ namespace ICSharpCode.NRefactory.CSharp { return visitor.VisitPropertyDeclaration (this, data); } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + PropertyDeclaration o = other as PropertyDeclaration; + return o != null && this.MatchMember(o, match) + && this.Getter.DoMatch(o.Getter, match) && this.Setter.DoMatch(o.Setter, match); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index 1c67668d0..960058789 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.CSharp readonly IOutputFormatter formatter; readonly CSharpFormattingPolicy policy; - AstNode currentContainerNode; + readonly Stack containerStack = new Stack(); readonly Stack positionStack = new Stack(); /// @@ -65,21 +65,23 @@ namespace ICSharpCode.NRefactory.CSharp #region StartNode/EndNode void StartNode(AstNode node) { - Debug.Assert(currentContainerNode == null || node.Parent == currentContainerNode); + // Ensure that nodes are visited in the proper nested order. + // Jumps to different subtrees are allowed only for the child of a placeholder node. + Debug.Assert(containerStack.Count == 0 || node.Parent == containerStack.Peek() || containerStack.Peek().NodeType == NodeType.Placeholder); if (positionStack.Count > 0) WriteSpecialsUpToNode(node); - currentContainerNode = node; + containerStack.Push(node); positionStack.Push(node.FirstChild); formatter.StartNode(node); } object EndNode(AstNode node) { - Debug.Assert(node == currentContainerNode); + Debug.Assert(node == containerStack.Peek()); AstNode pos = positionStack.Pop(); Debug.Assert(pos == null || pos.Parent == node); WriteSpecials(pos, null); - currentContainerNode = node.Parent; + containerStack.Pop(); formatter.EndNode(node); return null; } @@ -146,13 +148,14 @@ namespace ICSharpCode.NRefactory.CSharp /// Writes a comma. /// /// The next node after the comma. - void Comma(AstNode nextNode) + /// When set prevents printing a space after comma. + void Comma(AstNode nextNode, bool noSpaceAfterComma = false) { WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode); Space(policy.SpacesBeforeComma); formatter.WriteToken(","); lastWritten = LastWritten.Other; - Space(policy.SpacesAfterComma); + Space(!noSpaceAfterComma && policy.SpacesAfterComma); } void WriteCommaSeparatedList(IEnumerable list) @@ -179,12 +182,34 @@ namespace ICSharpCode.NRefactory.CSharp RPar(); } - void WriteCommaSeparatedListInBrackets(IEnumerable list) + #if DOTNET35 + void WriteCommaSeparatedList(IEnumerable list) + { + WriteCommaSeparatedList(list.SafeCast()); + } + + void WriteCommaSeparatedList(IEnumerable list) + { + WriteCommaSeparatedList(list.SafeCast()); + } + + void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + { + WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); + } + + void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + { + WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); + } + #endif + + void WriteCommaSeparatedListInBrackets(IEnumerable list) { WriteToken("[", AstNode.Roles.LBracket); if (list.Any()) { Space(policy.SpacesWithinBrackets); - WriteCommaSeparatedList(list); + WriteCommaSeparatedList(list.SafeCast()); Space(policy.SpacesWithinBrackets); } WriteToken("]", AstNode.Roles.RBracket); @@ -207,7 +232,7 @@ namespace ICSharpCode.NRefactory.CSharp void WriteIdentifier(string identifier, Role identifierRole = null) { WriteSpecialsUpToRole(identifierRole ?? AstNode.Roles.Identifier); - if (IsKeyword(identifier, currentContainerNode)) { + if (IsKeyword(identifier, containerStack.Peek())) { if (lastWritten == LastWritten.KeywordOrIdentifier) Space(); // this space is not strictly required, so we call Space() formatter.WriteToken("@"); @@ -265,7 +290,8 @@ namespace ICSharpCode.NRefactory.CSharp /// void Semicolon() { - if (currentContainerNode.Role != ForStatement.InitializerRole && currentContainerNode.Role != ForStatement.IteratorRole && currentContainerNode.Role != UsingStatement.ResourceAcquisitionRole) { + Role role = containerStack.Peek().Role; // get the role of the current node + if (!(role == ForStatement.InitializerRole || role == ForStatement.IteratorRole || role == UsingStatement.ResourceAcquisitionRole)) { WriteToken(";", AstNode.Roles.Semicolon); NewLine(); } @@ -351,7 +377,7 @@ namespace ICSharpCode.NRefactory.CSharp { if (typeParameters.Any()) { WriteToken("<", AstNode.Roles.LChevron); - WriteCommaSeparatedList(typeParameters); + WriteCommaSeparatedList(typeParameters.SafeCast()); WriteToken(">", AstNode.Roles.RChevron); } } @@ -1033,7 +1059,7 @@ namespace ICSharpCode.NRefactory.CSharp StartNode(queryOrderClause); WriteKeyword("orderby"); Space(); - WriteCommaSeparatedList(queryOrderClause.Orderings); + WriteCommaSeparatedList(queryOrderClause.Orderings.SafeCast()); return EndNode(queryOrderClause); } @@ -1083,7 +1109,8 @@ namespace ICSharpCode.NRefactory.CSharp StartNode(attribute); attribute.Type.AcceptVisitor(this, data); Space(policy.BeforeMethodCallParentheses); - WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.WithinMethodCallParentheses); + if (attribute.Arguments.Count != 0 || !attribute.GetChildByRole(AstNode.Roles.LPar).IsNull) + WriteCommaSeparatedListInParenthesis(attribute.Arguments, policy.WithinMethodCallParentheses); return EndNode(attribute); } @@ -1096,9 +1123,10 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken(":", AttributeSection.Roles.Colon); Space(); } - WriteCommaSeparatedList(attributeSection.Attributes); + WriteCommaSeparatedList(attributeSection.Attributes.SafeCast()); WriteToken("]", AstNode.Roles.RBracket); - NewLine(); + if (!(attributeSection.Parent is ParameterDeclaration)) + NewLine(); return EndNode(attributeSection); } @@ -1176,7 +1204,7 @@ namespace ICSharpCode.NRefactory.CSharp if (first) { first = false; } else { - Comma(member); + Comma(member, noSpaceAfterComma: true); NewLine(); } member.AcceptVisitor(this, data); @@ -1345,7 +1373,7 @@ namespace ICSharpCode.NRefactory.CSharp LPar(); Space(policy.WithinForParentheses); - WriteCommaSeparatedList(forStatement.Initializers); + WriteCommaSeparatedList(forStatement.Initializers.SafeCast()); WriteToken(";", AstNode.Roles.Semicolon); Space(policy.SpacesAfterSemicolon); @@ -1353,7 +1381,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken(";", AstNode.Roles.Semicolon); Space(policy.SpacesAfterSemicolon); - WriteCommaSeparatedList(forStatement.Iterators); + WriteCommaSeparatedList(forStatement.Iterators.SafeCast()); Space(policy.WithinForParentheses); RPar(); @@ -1889,7 +1917,10 @@ namespace ICSharpCode.NRefactory.CSharp { StartNode(memberType); memberType.Target.AcceptVisitor(this, data); - WriteToken(".", MemberType.Roles.Dot); + if (memberType.IsDoubleColon) + WriteToken("::", MemberType.Roles.Dot); + else + WriteToken(".", MemberType.Roles.Dot); WriteIdentifier(memberType.MemberName); WriteTypeArguments(memberType.TypeArguments); return EndNode(memberType); @@ -1925,6 +1956,11 @@ namespace ICSharpCode.NRefactory.CSharp { StartNode(primitiveType); WriteKeyword(primitiveType.Keyword); + if (primitiveType.Keyword == "new") { + // new() constraint + LPar(); + RPar(); + } return EndNode(primitiveType); } @@ -1943,6 +1979,7 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) { StartNode(typeParameterDeclaration); + WriteAttributes(typeParameterDeclaration.Attributes); switch (typeParameterDeclaration.Variance) { case VarianceModifier.Invariant: break; diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index bb447f4c6..68ac7ee2f 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -225,7 +225,7 @@ namespace ICSharpCode.NRefactory.CSharp var typeArgLocation = LocationsBag.GetLocations (c.MemberName); if (typeArgLocation != null) newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); -// AddTypeArguments (newType, typeArgLocation, c.MemberName.TypeArguments); + AddTypeParameters (newType, typeArgLocation, c.MemberName.TypeArguments); if (typeArgLocation != null) newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); AddConstraints (newType, c); @@ -254,7 +254,7 @@ namespace ICSharpCode.NRefactory.CSharp var typeArgLocation = LocationsBag.GetLocations (s.MemberName); if (typeArgLocation != null) newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); -// AddTypeArguments (newType, typeArgLocation, s.MemberName.TypeArguments); + AddTypeParameters (newType, typeArgLocation, s.MemberName.TypeArguments); if (typeArgLocation != null) newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); AddConstraints (newType, s); @@ -283,7 +283,7 @@ namespace ICSharpCode.NRefactory.CSharp var typeArgLocation = LocationsBag.GetLocations (i.MemberName); if (typeArgLocation != null) newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); -// AddTypeArguments (newType, typeArgLocation, i.MemberName.TypeArguments); + AddTypeParameters (newType, typeArgLocation, i.MemberName.TypeArguments); if (typeArgLocation != null) newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); AddConstraints (newType, i); @@ -307,12 +307,12 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) newDelegate.AddChild (new CSharpTokenNode (Convert (location[0]), "delegate".Length), TypeDeclaration.Roles.Keyword); newDelegate.AddChild (ConvertToType (d.ReturnType), AstNode.Roles.Type); - newDelegate.AddChild (new Identifier (d.Name, Convert (d.MemberName.Location)), AstNode.Roles.Identifier); + newDelegate.AddChild (new Identifier (d.Basename, Convert (d.MemberName.Location)), AstNode.Roles.Identifier); if (d.MemberName.TypeArguments != null) { var typeArgLocation = LocationsBag.GetLocations (d.MemberName); if (typeArgLocation != null) newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); -// AddTypeArguments (newDelegate, typeArgLocation, d.MemberName.TypeArguments); + AddTypeParameters (newDelegate, typeArgLocation, d.MemberName.TypeArguments); if (typeArgLocation != null) newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); AddConstraints (newDelegate, d); @@ -632,7 +632,7 @@ namespace ICSharpCode.NRefactory.CSharp var typeArgLocation = LocationsBag.GetLocations (m.MemberName); if (typeArgLocation != null) newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); -// AddTypeArguments (newMethod, typeArgLocation, m.MemberName.TypeArguments); + AddTypeParameters (newMethod, typeArgLocation, m.MemberName.TypeArguments); if (typeArgLocation != null) newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); @@ -1234,7 +1234,7 @@ namespace ICSharpCode.NRefactory.CSharp statement.Remove (); newSection.AddChild (statement, SwitchSection.Roles.EmbeddedStatement); - } + } result.AddChild (newSection, SwitchStatement.SwitchSectionRole); } @@ -1835,17 +1835,22 @@ namespace ICSharpCode.NRefactory.CSharp } } - void AddTypeArguments (AstNode parent, LocationsBag.MemberLocations location, Mono.CSharp.TypeArguments typeArguments) + void AddTypeParameters (AstNode parent, List location, Mono.CSharp.TypeArguments typeArguments) { if (typeArguments == null || typeArguments.IsEmpty) return; for (int i = 0; i < typeArguments.Count; i++) { if (location != null && i > 0 && i - 1 < location.Count) parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); - var arg = typeArguments.Args[i]; + var arg = (TypeParameterName)typeArguments.Args[i]; if (arg == null) continue; - parent.AddChild (ConvertToType (arg), InvocationExpression.Roles.TypeArgument); + TypeParameterDeclaration tp = new TypeParameterDeclaration(); + // TODO: attributes + if (arg.Variance != Variance.None) + throw new NotImplementedException(); // TODO: variance + tp.AddChild (new Identifier (arg.Name, Convert (arg.Location)), InvocationExpression.Roles.Identifier); + parent.AddChild (tp, InvocationExpression.Roles.TypeParameter); } } @@ -1871,11 +1876,12 @@ namespace ICSharpCode.NRefactory.CSharp Constraints c = d.Constraints[i]; var location = LocationsBag.GetLocations (c); var constraint = new Constraint (); - parent.AddChild (new CSharpTokenNode (Convert (location[0]), "where".Length), InvocationExpression.Roles.Keyword); - parent.AddChild (new Identifier (c.TypeParameter.Value, Convert (c.TypeParameter.Location)), InvocationExpression.Roles.Identifier); - parent.AddChild (new CSharpTokenNode (Convert (location[1]), 1), Constraint.ColonRole); + constraint.AddChild (new CSharpTokenNode (Convert (location[0]), "where".Length), InvocationExpression.Roles.Keyword); + constraint.AddChild (new Identifier (c.TypeParameter.Value, Convert (c.TypeParameter.Location)), InvocationExpression.Roles.Identifier); + constraint.AddChild (new CSharpTokenNode (Convert (location[1]), 1), Constraint.ColonRole); foreach (var expr in c.ConstraintExpressions) - parent.AddChild (ConvertToType (expr), Constraint.BaseTypeRole); + constraint.AddChild (ConvertToType (expr), Constraint.BaseTypeRole); + parent.AddChild (constraint, AstNode.Roles.Constraint); } } @@ -1892,7 +1898,7 @@ namespace ICSharpCode.NRefactory.CSharp DirectionExpression direction = new DirectionExpression (); direction.FieldDirection = arg.ArgType == Argument.AType.Out ? FieldDirection.Out : FieldDirection.Ref; var argLocation = LocationsBag.GetLocations (arg); - if (location != null) + if (argLocation != null) direction.AddChild (new CSharpTokenNode (Convert (argLocation[0]), "123".Length), InvocationExpression.Roles.Keyword); direction.AddChild ((Expression)arg.Expr.Accept (this), InvocationExpression.Roles.Expression); @@ -2115,10 +2121,10 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[0]), "stackalloc".Length), StackAllocExpression.Roles.Keyword); result.AddChild (ConvertToType (stackAllocExpression.TypeExpression), StackAllocExpression.Roles.Type); - if (location != null) + if (location != null && location.Count > 1) result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), StackAllocExpression.Roles.LBracket); result.AddChild ((Expression)stackAllocExpression.CountExpression.Accept (this), StackAllocExpression.Roles.Expression); - if (location != null) + if (location != null && location.Count > 2) result.AddChild (new CSharpTokenNode (Convert (location[2]), 1), StackAllocExpression.Roles.RBracket); return result; } @@ -2540,7 +2546,7 @@ namespace ICSharpCode.NRefactory.CSharp return EmptyList.Instance; } - public IEnumerable ParseStatements(TextReader reader) + public IEnumerable ParseStatements(TextReader reader) { string code = "void M() { " + reader.ReadToEnd() + "}"; var members = ParseTypeMembers(new StringReader(code)); @@ -2548,10 +2554,10 @@ namespace ICSharpCode.NRefactory.CSharp if (method != null && method.Body != null) return method.Body.Statements; else - return EmptyList.Instance; + return EmptyList.Instance; } - public AstNode ParseTypeReference(TextReader reader) + public AstType ParseTypeReference(TextReader reader) { // TODO: add support for parsing type references throw new NotImplementedException(); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs index 281e3e569..6fac5b0da 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs @@ -145,9 +145,11 @@ namespace ICSharpCode.NRefactory.CSharp else if (td.ClassType == ClassType.Enum || td.ClassType == ClassType.Struct) td.IsSealed = true; // enums/structs are implicitly sealed - //TODO ConvertTypeParameters(td.TypeParameters, typeDeclaration.TypeParameters, typeDeclaration.Constraints); + ConvertTypeParameters(td.TypeParameters, typeDeclaration.TypeParameters, typeDeclaration.Constraints); - // TODO: base type references? + foreach (AstType baseType in typeDeclaration.BaseTypes) { + td.BaseTypes.Add(ConvertType(baseType)); + } foreach (AttributedNode member in typeDeclaration.Members) { member.AcceptVisitor(this, data); @@ -159,7 +161,7 @@ namespace ICSharpCode.NRefactory.CSharp public override IEntity VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { - var td = CreateTypeDefinition(delegateDeclaration.Name); + var td = currentTypeDefinition = CreateTypeDefinition(delegateDeclaration.Name); td.ClassType = ClassType.Delegate; td.Region = MakeRegion(delegateDeclaration); td.BaseTypes.Add(multicastDelegateReference); @@ -168,9 +170,14 @@ namespace ICSharpCode.NRefactory.CSharp ApplyModifiers(td, delegateDeclaration.Modifiers); td.IsSealed = true; // delegates are implicitly sealed - // TODO: convert return type, convert parameters - AddDefaultMethodsToDelegate(td, SharedTypes.UnknownType, EmptyList.Instance); + ConvertTypeParameters(td.TypeParameters, delegateDeclaration.TypeParameters, delegateDeclaration.Constraints); + + ITypeReference returnType = ConvertType(delegateDeclaration.ReturnType); + List parameters = new List(); + ConvertParameters(parameters, delegateDeclaration.Parameters); + AddDefaultMethodsToDelegate(td, returnType, parameters); + currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; return td; } @@ -299,7 +306,7 @@ namespace ICSharpCode.NRefactory.CSharp m.BodyRegion = MakeRegion(methodDeclaration.Body); - //TODO ConvertTypeParameters(m.TypeParameters, methodDeclaration.TypeParameters, methodDeclaration.Constraints); + ConvertTypeParameters(m.TypeParameters, methodDeclaration.TypeParameters, methodDeclaration.Constraints); m.ReturnType = ConvertType(methodDeclaration.ReturnType); ConvertAttributes(m.Attributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget != AttributeTarget.Return)); ConvertAttributes(m.ReturnTypeAttributes, methodDeclaration.Attributes.Where(s => s.AttributeTarget == AttributeTarget.Return)); @@ -318,7 +325,13 @@ namespace ICSharpCode.NRefactory.CSharp return m; } - DefaultExplicitInterfaceImplementation ConvertInterfaceImplementation(AstNode interfaceType, string memberName) + void ConvertTypeParameters(IList output, IEnumerable typeParameters, IEnumerable constraints) + { + if (typeParameters.Any()) + throw new NotImplementedException(); + } + + DefaultExplicitInterfaceImplementation ConvertInterfaceImplementation(AstType interfaceType, string memberName) { return new DefaultExplicitInterfaceImplementation(ConvertType(interfaceType), memberName); } @@ -327,7 +340,7 @@ namespace ICSharpCode.NRefactory.CSharp #region Operators public override IEntity VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) { - DefaultMethod m = new DefaultMethod(currentTypeDefinition, OperatorDeclaration.GetName(operatorDeclaration.OperatorType)); + DefaultMethod m = new DefaultMethod(currentTypeDefinition, operatorDeclaration.Name); m.EntityType = EntityType.Operator; m.Region = MakeRegion(operatorDeclaration); m.BodyRegion = MakeRegion(operatorDeclaration.Body); @@ -395,13 +408,6 @@ namespace ICSharpCode.NRefactory.CSharp public override IEntity VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) { DefaultProperty p = new DefaultProperty(currentTypeDefinition, propertyDeclaration.Name); - HandlePropertyOrIndexer(p, propertyDeclaration); - currentTypeDefinition.Properties.Add(p); - return p; - } - - void HandlePropertyOrIndexer(DefaultProperty p, PropertyDeclaration propertyDeclaration) - { p.Region = MakeRegion(propertyDeclaration); p.BodyRegion = MakeBraceRegion(propertyDeclaration); ApplyModifiers(p, propertyDeclaration.Modifiers); @@ -413,13 +419,25 @@ namespace ICSharpCode.NRefactory.CSharp } p.Getter = ConvertAccessor(propertyDeclaration.Getter, p.Accessibility); p.Setter = ConvertAccessor(propertyDeclaration.Setter, p.Accessibility); + currentTypeDefinition.Properties.Add(p); + return p; } public override IEntity VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) { DefaultProperty p = new DefaultProperty(currentTypeDefinition, "Items"); p.EntityType = EntityType.Indexer; - HandlePropertyOrIndexer(p, indexerDeclaration); + p.Region = MakeRegion(indexerDeclaration); + p.BodyRegion = MakeBraceRegion(indexerDeclaration); + ApplyModifiers(p, indexerDeclaration.Modifiers); + p.ReturnType = ConvertType(indexerDeclaration.ReturnType); + ConvertAttributes(p.Attributes, indexerDeclaration.Attributes); + if (!indexerDeclaration.PrivateImplementationType.IsNull) { + p.Accessibility = Accessibility.None; + p.InterfaceImplementations.Add(ConvertInterfaceImplementation(indexerDeclaration.PrivateImplementationType, p.Name)); + } + p.Getter = ConvertAccessor(indexerDeclaration.Getter, p.Accessibility); + p.Setter = ConvertAccessor(indexerDeclaration.Setter, p.Accessibility); ConvertParameters(p.Parameters, indexerDeclaration.Parameters); currentTypeDefinition.Properties.Add(p); return p; @@ -528,14 +546,14 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Types - ITypeReference ConvertType(AstNode node, bool isInUsingDeclaration = false) + ITypeReference ConvertType(AstType type, bool isInUsingDeclaration = false) { - return ConvertType(node, currentTypeDefinition, currentMethod, usingScope, isInUsingDeclaration); + return ConvertType(type, currentTypeDefinition, currentMethod, usingScope, isInUsingDeclaration); } - internal static ITypeReference ConvertType(AstNode node, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope, bool isInUsingDeclaration) + internal static ITypeReference ConvertType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope, bool isInUsingDeclaration) { - SimpleType s = node as SimpleType; + SimpleType s = type as SimpleType; if (s != null) { List typeArguments = new List(); foreach (var ta in s.TypeArguments) { @@ -551,25 +569,8 @@ namespace ICSharpCode.NRefactory.CSharp } return new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration); } - IdentifierExpression ident = node as IdentifierExpression; - if (ident != null) { - // TODO: get rid of this code once the parser produces SimpleType instead of IdentifierExpression - List typeArguments = new List(); - foreach (var ta in ident.TypeArguments) { - typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration)); - } - if (typeArguments.Count == 0 && parentMethodDefinition != null) { - // SimpleTypeOrNamespaceReference doesn't support method type parameters, - // so we directly handle them here. - foreach (ITypeParameter tp in parentMethodDefinition.TypeParameters) { - if (tp.Name == s.Identifier) - return tp; - } - } - return new SimpleTypeOrNamespaceReference(ident.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration); - } - PrimitiveType p = node as PrimitiveType; + PrimitiveType p = type as PrimitiveType; if (p != null) { switch (p.Keyword) { case "string": @@ -608,7 +609,7 @@ namespace ICSharpCode.NRefactory.CSharp return SharedTypes.UnknownType; } } - MemberType m = node as MemberType; + MemberType m = type as MemberType; if (m != null) { ITypeOrNamespaceReference t; if (m.IsDoubleColon) { @@ -629,7 +630,7 @@ namespace ICSharpCode.NRefactory.CSharp } return new MemberTypeOrNamespaceReference(t, m.MemberName, typeArguments, parentTypeDefinition, parentUsingScope); } - ComposedType c = node as ComposedType; + ComposedType c = type as ComposedType; if (c != null) { ITypeReference t = ConvertType(c.BaseType, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration); if (c.HasNullableSpecifier) { @@ -643,7 +644,7 @@ namespace ICSharpCode.NRefactory.CSharp } return t; } - Debug.WriteLine("Unknown node used as type: " + node); + Debug.WriteLine("Unknown node used as type: " + type); return SharedTypes.UnknownType; } #endregion diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs index 3dbf53a42..904bbae99 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs @@ -26,13 +26,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver internal readonly CancellationToken cancellationToken; #region Constructor - public CSharpResolver(ITypeResolveContext context, CancellationToken cancellationToken = default(CancellationToken)) + public CSharpResolver(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + } + + #if !DOTNET35 + public CSharpResolver(ITypeResolveContext context, CancellationToken cancellationToken) { if (context == null) throw new ArgumentNullException("context"); this.context = context; this.cancellationToken = cancellationToken; } + #endif #endregion #region Properties @@ -1513,12 +1522,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - ResolveResult rr = LookupSimpleNameOrTypeName( + return LookupSimpleNameOrTypeName( identifier, typeArguments, isInvocationTarget ? SimpleNameLookupMode.InvocationTarget : SimpleNameLookupMode.Expression); - if (rr == ErrorResult && typeArguments.Count == 0) - rr = new UnknownIdentifierResolveResult(identifier); - return rr; } public ResolveResult LookupSimpleNamespaceOrTypeName(string identifier, IList typeArguments, bool isUsingDeclaration = false) @@ -1633,7 +1639,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } // if we didn't find anything: repeat lookup with parent namespace } - return ErrorResult; + if (typeArguments.Count == 0) + return new UnknownIdentifierResolveResult(identifier); + else + return ErrorResult; } /// @@ -1822,7 +1831,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { // No candidate found at all (not even an inapplicable one). // This can happen with empty method groups (as sometimes used with extension methods) - return new UnknownMethodResolveResult(mgrr.TargetType, mgrr.MethodName, mgrr.TypeArguments, CreateParameters(arguments, argumentNames)); + return new UnknownMethodResolveResult( + mgrr.TargetType, mgrr.MethodName, mgrr.TypeArguments, CreateParameters(arguments, argumentNames)); } } UnknownMemberResolveResult umrr = target as UnknownMemberResolveResult; @@ -1840,9 +1850,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return ErrorResult; } - static List CreateParameters(ResolveResult[] arguments, string[] argumentNames) + static List CreateParameters(ResolveResult[] arguments, string[] argumentNames) { - List list = new List(); + List list = new List(); if (argumentNames == null) { argumentNames = new string[arguments.Length]; } else { diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs index 615c23947..f124141fa 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs @@ -170,10 +170,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Predicate memberFilter = delegate(IMember member) { return !member.IsOverride && member.Name == name && IsAccessible(member, allowProtectedAccess); }; - members.AddRange(type.GetMethods(context, memberFilter)); - members.AddRange(type.GetProperties(context, memberFilter)); - members.AddRange(type.GetFields(context, memberFilter)); - members.AddRange(type.GetEvents(context, memberFilter)); + members.AddRange(type.GetMethods(context, memberFilter.SafeCast()).SafeCast()); + members.AddRange(type.GetProperties(context, memberFilter.SafeCast()).SafeCast()); + members.AddRange(type.GetFields(context, memberFilter.SafeCast()).SafeCast()); + members.AddRange(type.GetEvents(context, memberFilter.SafeCast()).SafeCast()); if (isInvocation) members.RemoveAll(m => !IsInvocable(m, context)); } else { @@ -183,7 +183,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return method.TypeParameters.Count == typeArgumentCount && !method.IsOverride && method.Name == name && IsAccessible(method, allowProtectedAccess); }; - members.AddRange(type.GetMethods(context, memberFilter)); + members.AddRange(type.GetMethods(context, memberFilter).SafeCast()); } // TODO: can't members also hide types? diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs index e9b0da565..350701a0e 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (typeArguments.Count == 0) return target.ToString() + "." + identifier; else - return target.ToString() + "." + identifier + "<" + string.Join(",", typeArguments) + ">"; + return target.ToString() + "." + identifier + "<" + DotNet35Compat.StringJoin(",", typeArguments) + ">"; } } } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs index 7c72f8d8b..d4d1fca43 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs @@ -446,7 +446,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { bool c1IsBetter = false; bool c2IsBetter = false; - foreach (var pair in t1.Zip>(t2, Tuple.Create)) { + foreach (var pair in t1.Zip(t2, (a,b) => new { Item1 = a, Item2 = b })) { switch (MoreSpecificFormalParameter(pair.Item1, pair.Item2)) { case 1: c1IsBetter = true; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs index f950a474e..060bdfa7f 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -224,11 +224,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return VisitFieldOrEventDeclaration(eventDeclaration); } - ResolveResult VisitFieldOrEventDeclaration(MemberDeclaration fieldDeclaration) + ResolveResult VisitFieldOrEventDeclaration(AttributedNode fieldOrEventDeclaration) { - int initializerCount = fieldDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count(); + int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count(); ResolveResult result = null; - for (AstNode node = fieldDeclaration.FirstChild; node != null; node = node.NextSibling) { + for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) { if (node.Role == FieldDeclaration.Roles.Variable) { if (resolver.CurrentTypeDefinition != null) { resolver.CurrentMember = resolver.CurrentTypeDefinition.Fields.FirstOrDefault(f => f.Region.IsInside(node.StartLocation)); @@ -309,14 +309,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } // handle properties/indexers - ResolveResult VisitPropertyMember(PropertyDeclaration propertyDeclaration) + ResolveResult VisitPropertyMember(MemberDeclaration propertyOrIndexerDeclaration) { try { if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Properties.FirstOrDefault(p => p.Region.IsInside(propertyDeclaration.StartLocation)); + resolver.CurrentMember = resolver.CurrentTypeDefinition.Properties.FirstOrDefault(p => p.Region.IsInside(propertyOrIndexerDeclaration.StartLocation)); } - for (AstNode node = propertyDeclaration.FirstChild; node != null; node = node.NextSibling) { + for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) { if (node.Role == PropertyDeclaration.SetterRole && resolver.CurrentMember != null) { resolver.PushBlock(); resolver.AddVariable(resolver.CurrentMember.ReturnType, "value"); @@ -472,9 +472,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return ie != null && ie.Target == node; } - IType ResolveType(AstNode node) + IType ResolveType(AstType type) { - return MakeTypeReference(node).Resolve(resolver.Context); + return MakeTypeReference(type).Resolve(resolver.Context); } public override ResolveResult VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) @@ -593,7 +593,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - ResolveResult[] GetArguments(IEnumerable argumentExpressions, out string[] argumentNames) + ResolveResult[] GetArguments(IEnumerable argumentExpressions, out string[] argumentNames) { argumentNames = null; // TODO: add support for named arguments ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()]; @@ -951,7 +951,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// Creates a type reference for the specified type node. /// If the type node is 'var', performs type inference on the initializer expression. /// - ITypeReference MakeTypeReference(AstNode type, AstNode initializerExpression, bool isForEach) + ITypeReference MakeTypeReference(AstType type, AstNode initializerExpression, bool isForEach) { if (initializerExpression != null && IsVar(type)) { return new VarTypeReference(this, resolver.Clone(), initializerExpression, isForEach); @@ -960,14 +960,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - ITypeReference MakeTypeReference(AstNode type) + ITypeReference MakeTypeReference(AstType type) { return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope, false); } - static bool IsVar(AstNode returnType) + static bool IsVar(AstType returnType) { - return returnType is IdentifierExpression && ((IdentifierExpression)returnType).Identifier == "var"; + return returnType is SimpleType + && ((SimpleType)returnType).Identifier == "var" + && ((SimpleType)returnType).TypeArguments.Count == 0; } sealed class VarTypeReference : ITypeReference @@ -1072,25 +1074,36 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitPrimitiveType(PrimitiveType primitiveType, object data) { ScanChildren(primitiveType); - return new TypeResolveResult(MakeTypeReference(primitiveType).Resolve(resolver.Context)); + return new TypeResolveResult(ResolveType(primitiveType)); } public override ResolveResult VisitSimpleType(SimpleType simpleType, object data) { ScanChildren(simpleType); - return new TypeResolveResult(MakeTypeReference(simpleType).Resolve(resolver.Context)); + return ResolveTypeOrNamespace(simpleType); + } + + ResolveResult ResolveTypeOrNamespace(AstType type) + { + ITypeReference typeRef = MakeTypeReference(type); + ITypeOrNamespaceReference typeOrNsRef = typeRef as ITypeOrNamespaceReference; + if (typeOrNsRef != null) { + return typeOrNsRef.DoResolve(resolver.Context); + } else { + return new TypeResolveResult(typeRef.Resolve(resolver.Context)); + } } public override ResolveResult VisitMemberType(MemberType memberType, object data) { ScanChildren(memberType); - return new TypeResolveResult(MakeTypeReference(memberType).Resolve(resolver.Context)); + return ResolveTypeOrNamespace(memberType); } public override ResolveResult VisitComposedType(ComposedType composedType, object data) { ScanChildren(composedType); - return new TypeResolveResult(MakeTypeReference(composedType).Resolve(resolver.Context)); + return new TypeResolveResult(ResolveType(composedType)); } #endregion @@ -1135,7 +1148,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { throw new NotImplementedException(); } - */ + */ #endregion public override ResolveResult VisitIdentifier(Identifier identifier, object data) diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs index e51fde628..a500e85e0 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (typeArguments.Count == 0) return identifier; else - return identifier + "<" + string.Join(",", typeArguments) + ">"; + return identifier + "<" + DotNet35Compat.StringJoin(",", typeArguments) + ">"; } } } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs index afdfca58d..488a6c31f 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs @@ -856,7 +856,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool success; IType[] result = InferTypeArgumentsFromBounds( candidateDef.TypeParameters, - new ParameterizedType(candidateDef, candidateDef.TypeParameters), + new ParameterizedType(candidateDef, candidateDef.TypeParameters.SafeCast()), lowerBounds, upperBounds, out success); if (success) { diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 6fdcd0c9f..8698db3e8 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -7,7 +7,7 @@ Library ICSharpCode.NRefactory ICSharpCode.NRefactory - v4.0 + v3.5 Properties 10.0.0 2.0 @@ -15,6 +15,9 @@ False false 1591,0618 + + False + -Microsoft.Design#CA1026;-Microsoft.Security#CA2104 AnyCPU @@ -27,24 +30,27 @@ bin\Debug\ Full False - DEBUG;TRACE;FULL_AST + DEBUG;TRACE;FULL_AST;DOTNET35 + False bin\Release\ None True - TRACE;FULL_AST + TRACE;FULL_AST;DOTNET35 + False - full + Full false 4 true - none + None true 4 + false @@ -322,6 +328,7 @@ + diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 65bcae4b9..7564ed995 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -297,7 +297,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - static readonly string DynamicAttributeFullName = typeof(DynamicAttribute).FullName; + const string DynamicAttributeFullName = "System.Runtime.CompilerServices.DynamicAttribute"; static bool HasDynamicAttribute(ICustomAttributeProvider attributeProvider, int typeIndex) { diff --git a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs index 4c830048a..da2a6c06a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -70,15 +70,17 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new ArgumentNullException("context"); HashSet typeDefinitions = new HashSet(); - Func> recursion = + Func> recursion = t => t.GetBaseTypes(context).Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)); ITypeDefinition typeDef = type as ITypeDefinition; if (typeDef != null) { typeDefinitions.Add(typeDef); - return TreeTraversal.PreOrder(typeDef, recursion); + return TreeTraversal.PreOrder(typeDef, recursion); } else { - return TreeTraversal.PreOrder(recursion(type), recursion); + return TreeTraversal.PreOrder( + type.GetBaseTypes(context).Select(b => b.GetDefinition()).Where(d => d != null && typeDefinitions.Add(d)), + recursion); } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs b/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs index 62d748290..b9bb2dd97 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs @@ -10,7 +10,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents an attribute. /// + #if WITH_CONTRACTS [ContractClass(typeof(IAttributeContract))] + #endif [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")] public interface IAttribute : IFreezable { @@ -35,6 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IList> NamedArguments { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IAttribute))] abstract class IAttributeContract : IFreezableContract, IAttribute { @@ -63,4 +66,5 @@ namespace ICSharpCode.NRefactory.TypeSystem } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs b/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs index 030f5a118..8ea9a8f3d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs @@ -6,7 +6,9 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + #if WITH_CONTRACTS [ContractClass(typeof(IConstantValueContract))] + #endif public interface IConstantValue : IFreezable { /// @@ -30,6 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem object GetValue(ITypeResolveContext context); } + #if WITH_CONTRACTS [ContractClassFor(typeof(IConstantValue))] abstract class IConstantValueContract : IFreezableContract, IConstantValue { @@ -46,4 +49,5 @@ namespace ICSharpCode.NRefactory.TypeSystem return null; } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IEntity.cs b/ICSharpCode.NRefactory/TypeSystem/IEntity.cs index 752cb693d..d9f92d1ce 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IEntity.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IEntity.cs @@ -7,7 +7,9 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + #if WITH_CONTRACTS [ContractClass(typeof(IEntityContract))] + #endif public interface IEntity : INamedElement, IFreezable { EntityType EntityType { get; } @@ -75,6 +77,7 @@ namespace ICSharpCode.NRefactory.TypeSystem //bool IsAccessible(IClass callingClass, bool isAccessThoughReferenceOfCurrentClass); } + #if WITH_CONTRACTS [ContractClassFor(typeof(IEntity))] abstract class IEntityContract : INamedElementContract, IEntity { @@ -144,4 +147,5 @@ namespace ICSharpCode.NRefactory.TypeSystem { } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs b/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs index 91259ff0e..60452a670 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs @@ -9,7 +9,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents an explicit interface implementation. /// + #if WITH_CONTRACTS [ContractClass(typeof(IExplicitInterfaceImplementationContract))] + #endif public interface IExplicitInterfaceImplementation : IFreezable { /// @@ -23,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem string MemberName { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IExplicitInterfaceImplementation))] abstract class IExplicitInterfaceImplementationContract : IFreezableContract, IExplicitInterfaceImplementation { @@ -40,4 +43,5 @@ namespace ICSharpCode.NRefactory.TypeSystem } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IField.cs b/ICSharpCode.NRefactory/TypeSystem/IField.cs index c72526a78..c5c015299 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IField.cs @@ -9,7 +9,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a field or constant. /// + #if WITH_CONTRACTS [ContractClass(typeof(IFieldContract))] + #endif public interface IField : IMember, IVariable { /// @@ -28,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem bool IsVolatile { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IField))] abstract class IFieldContract : IMemberContract, IField { @@ -63,4 +66,5 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return null; } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs b/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs index 1705b4d75..baa35f42d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs @@ -6,7 +6,9 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + #if WITH_CONTRACTS [ContractClass(typeof(IFreezableContract))] + #endif public interface IFreezable { /// @@ -20,6 +22,7 @@ namespace ICSharpCode.NRefactory.TypeSystem void Freeze(); } + #if WITH_CONTRACTS [ContractClassFor(typeof(IFreezable))] abstract class IFreezableContract : IFreezable { @@ -33,4 +36,5 @@ namespace ICSharpCode.NRefactory.TypeSystem Contract.Ensures(self.IsFrozen); } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs index 3e8f45655..16b23d063 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs @@ -25,7 +25,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// and which are used only within a single type definition. Then a persistent file format could be organized so /// that shared objects are loaded only once, yet non-shared objects get loaded lazily together with the class. /// + #if WITH_CONTRACTS [ContractClass(typeof(IInterningProviderContract))] + #endif public interface IInterningProvider { /// @@ -39,6 +41,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IList InternList(IList list) where T : class; } + #if WITH_CONTRACTS [ContractClassFor(typeof(IInterningProvider))] abstract class IInterningProviderContract : IInterningProvider { @@ -54,4 +57,5 @@ namespace ICSharpCode.NRefactory.TypeSystem return list; } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IMember.cs b/ICSharpCode.NRefactory/TypeSystem/IMember.cs index 4fc545495..4a51074bf 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IMember.cs @@ -10,7 +10,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Method/field/entity. /// + #if WITH_CONTRACTS [ContractClass(typeof(IMemberContract))] + #endif public interface IMember : IEntity { /// @@ -58,6 +60,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IMember))] abstract class IMemberContract : IEntityContract, IMember { @@ -101,4 +104,5 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return false; } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IMethod.cs b/ICSharpCode.NRefactory/TypeSystem/IMethod.cs index 56ded253d..e66ab0782 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IMethod.cs @@ -10,7 +10,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a method, constructor, destructor or operator. /// + #if WITH_CONTRACTS [ContractClass(typeof(IMethodContract))] + #endif public interface IMethod : IParameterizedMember { /// @@ -30,6 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem bool IsOperator { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IMethod))] abstract class IMethodContract : IParameterizedMemberContract, IMethod { @@ -47,13 +50,6 @@ namespace ICSharpCode.NRefactory.TypeSystem } } -// IList IMethod.HandlesClauses { -// get { -// Contract.Ensures(Contract.Result>() != null); -// return null; -// } -// } - bool IMethod.IsExtensionMethod { get { return false; } } @@ -70,4 +66,5 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return false; } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs b/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs index 407caf6c3..789108543 100644 --- a/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs +++ b/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs @@ -6,7 +6,9 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + #if WITH_CONTRACTS [ContractClass(typeof(INamedElementContract))] + #endif public interface INamedElement { /// @@ -63,6 +65,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + #if WITH_CONTRACTS [ContractClassFor(typeof(INamedElement))] abstract class INamedElementContract : INamedElement { @@ -94,4 +97,5 @@ namespace ICSharpCode.NRefactory.TypeSystem } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IParameter.cs b/ICSharpCode.NRefactory/TypeSystem/IParameter.cs index 0333a45a9..3f7d9b082 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParameter.cs @@ -7,7 +7,9 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + #if WITH_CONTRACTS [ContractClass(typeof(IParameterContract))] + #endif public interface IParameter : IVariable, IFreezable { /// @@ -46,6 +48,7 @@ namespace ICSharpCode.NRefactory.TypeSystem bool IsOptional { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IParameter))] abstract class IParameterContract : IVariableContract, IParameter { @@ -92,4 +95,5 @@ namespace ICSharpCode.NRefactory.TypeSystem { } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs b/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs index e719ca59a..a60c75133 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs @@ -10,12 +10,15 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a method or property. /// + #if WITH_CONTRACTS [ContractClass(typeof(IParameterizedMemberContract))] + #endif public interface IParameterizedMember : IMember { IList Parameters { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IParameterizedMember))] abstract class IParameterizedMemberContract : IMemberContract, IParameterizedMember { @@ -26,4 +29,5 @@ namespace ICSharpCode.NRefactory.TypeSystem } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs index 274bcfbe3..be4d9651d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs @@ -10,12 +10,15 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Mutable container of all classes in an assembly. /// + #if WITH_CONTRACTS [ContractClass(typeof(IProjectContentContract))] + #endif public interface IProjectContent : ITypeResolveContext { IList AssemblyAttributes { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IProjectContent))] abstract class IProjectContentContract : ITypeResolveContextContract, IProjectContent { @@ -26,4 +29,5 @@ namespace ICSharpCode.NRefactory.TypeSystem } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs b/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs index 771ff43f9..86de1c379 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs @@ -11,7 +11,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Interface for TypeSystem objects that support interning. /// See for more information. /// + #if WITH_CONTRACTS [ContractClass(typeof(ISupportsInterningContract))] + #endif public interface ISupportsInterning { /// @@ -30,6 +32,7 @@ namespace ICSharpCode.NRefactory.TypeSystem bool EqualsForInterning(ISupportsInterning other); } + #if WITH_CONTRACTS [ContractClassFor(typeof(ISupportsInterning))] abstract class ISupportsInterningContract : ISupportsInterning { @@ -48,4 +51,5 @@ namespace ICSharpCode.NRefactory.TypeSystem return false; } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IType.cs b/ICSharpCode.NRefactory/TypeSystem/IType.cs index d8cec4091..f6d3b3a32 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IType.cs @@ -7,7 +7,9 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + #if WITH_CONTRACTS [ContractClass(typeof(ITypeContract))] + #endif public interface IType : ITypeReference, INamedElement, IEquatable { /// @@ -90,6 +92,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null); } + #if WITH_CONTRACTS [ContractClassFor(typeof(IType))] abstract class ITypeContract : ITypeReferenceContract, IType { @@ -209,4 +212,5 @@ namespace ICSharpCode.NRefactory.TypeSystem return this; } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs index dc8576d8f..905a85fdc 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs @@ -10,7 +10,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a class, enum, interface, struct, delegate or VB module. /// + #if WITH_CONTRACTS [ContractClass(typeof(ITypeDefinitionContract))] + #endif public interface ITypeDefinition : IType, IEntity { ClassType ClassType { get; } @@ -44,6 +46,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IEnumerable Members { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(ITypeDefinition))] abstract class ITypeDefinitionContract : ITypeContract, ITypeDefinition { @@ -181,4 +184,5 @@ namespace ICSharpCode.NRefactory.TypeSystem } #endregion } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs index ee7f43dfc..75d6d4cb4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs @@ -11,7 +11,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Type parameter of a generic class/method. /// + #if WITH_CONTRACTS [ContractClass(typeof(ITypeParameterContract))] + #endif public interface ITypeParameter : IType, IFreezable { /// @@ -99,6 +101,7 @@ namespace ICSharpCode.NRefactory.TypeSystem Contravariant }; + #if WITH_CONTRACTS [ContractClassFor(typeof(ITypeParameter))] abstract class ITypeParameterContract : ITypeContract, ITypeParameter { @@ -178,4 +181,5 @@ namespace ICSharpCode.NRefactory.TypeSystem { } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs index 70f105b3a..50795311b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs @@ -11,7 +11,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Represents a reference to a type. /// Must be resolved before it can be used as type. /// + #if WITH_CONTRACTS [ContractClass(typeof(ITypeReferenceContract))] + #endif public interface ITypeReference { // Keep this interface simple: I decided against having GetMethods/GetEvents etc. here, @@ -26,6 +28,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IType Resolve(ITypeResolveContext context); } + #if WITH_CONTRACTS [ContractClassFor(typeof(ITypeReference))] abstract class ITypeReferenceContract : ITypeReference { @@ -36,4 +39,5 @@ namespace ICSharpCode.NRefactory.TypeSystem return null; } } + #endif } \ No newline at end of file diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs index 335153ee6..3c89b13ad 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs @@ -12,7 +12,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Context representing the set of assemblies in which a type is being searched. /// + #if WITH_CONTRACTS [ContractClass(typeof(ITypeResolveContextContract))] + #endif public interface ITypeResolveContext { /// @@ -91,6 +93,7 @@ namespace ICSharpCode.NRefactory.TypeSystem CacheManager CacheManager { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(ITypeResolveContext))] abstract class ITypeResolveContextContract : ITypeResolveContext { @@ -140,4 +143,5 @@ namespace ICSharpCode.NRefactory.TypeSystem return null; } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/IVariable.cs b/ICSharpCode.NRefactory/TypeSystem/IVariable.cs index cc4dfa9c4..5c8f1d903 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IVariable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IVariable.cs @@ -9,7 +9,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents a variable (name/return type pair). /// + #if WITH_CONTRACTS [ContractClass(typeof(IVariableContract))] + #endif public interface IVariable { /// @@ -33,6 +35,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IConstantValue ConstantValue { get; } } + #if WITH_CONTRACTS [ContractClassFor(typeof(IVariable))] abstract class IVariableContract : IVariable { @@ -62,4 +65,5 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return null; } } } + #endif } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs index b2f981df6..9fd926da9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs @@ -19,9 +19,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (string.IsNullOrEmpty(ns)) { return name; } else { - string combinedName = ns + "." + name; - Contract.Assume(!string.IsNullOrEmpty(combinedName)); - return combinedName; + return ns + "." + name; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs index 220f09a12..0f412842d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs @@ -53,19 +53,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation base.FreezeInternal(); } - [ContractInvariantMethod] - void ObjectInvariant() - { - Contract.Invariant(type != null); - Contract.Invariant(name != null); - } - public string Name { get { return name; } set { if (value == null) throw new ArgumentNullException(); - Contract.EndContractBlock(); CheckBeforeMutation(); name = value; } @@ -76,7 +68,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation set { if (value == null) throw new ArgumentNullException(); - Contract.EndContractBlock(); CheckBeforeMutation(); type = value; } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs index 4964cacc4..881d38585 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -60,7 +60,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation throw new ArgumentNullException("declaringTypeDefinition"); if (string.IsNullOrEmpty(name)) throw new ArgumentException("name"); - Contract.EndContractBlock(); this.projectContent = declaringTypeDefinition.ProjectContent; this.declaringTypeDefinition = declaringTypeDefinition; this.name = name; @@ -73,20 +72,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation throw new ArgumentNullException("projectContent"); if (string.IsNullOrEmpty(name)) throw new ArgumentException("name"); - Contract.EndContractBlock(); this.projectContent = projectContent; this.ns = ns ?? string.Empty; this.name = name; } - [ContractInvariantMethod] - void ObjectInvariant() - { - Contract.Invariant(projectContent != null); - Contract.Invariant(!string.IsNullOrEmpty(name)); - Contract.Invariant(ns != null); - } - public ClassType ClassType { get { return classType; } set { @@ -164,7 +154,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IEnumerable Members { get { - return this.Fields.Concat(this.Properties).Concat(this.Methods).Concat(this.Events); + return this.Fields.SafeCast() + .Concat(this.Properties.SafeCast()) + .Concat(this.Methods.SafeCast()) + .Concat(this.Events.SafeCast()); } } @@ -187,15 +180,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public string FullName { get { if (declaringTypeDefinition != null) { - string combinedName = declaringTypeDefinition.FullName + "." + this.name; - Contract.Assume(!string.IsNullOrEmpty(combinedName)); - return combinedName; + return declaringTypeDefinition.FullName + "." + this.name; } else if (string.IsNullOrEmpty(ns)) { return this.name; } else { - string combinedName = this.ns + "." + this.name; - Contract.Assume(!string.IsNullOrEmpty(combinedName)); - return combinedName; + return this.ns + "." + this.name; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs index ce5c85864..7ed18be85 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs @@ -2,6 +2,7 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -51,16 +52,27 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - sealed class ListComparer : IEqualityComparer> + sealed class ListComparer : IEqualityComparer { - public bool Equals(IEnumerable a, IEnumerable b) + public bool Equals(IEnumerable a, IEnumerable b) { if (a.GetType() != b.GetType()) return false; - return Enumerable.SequenceEqual(a, b, ReferenceComparer.Instance); + IEnumerator e1 = a.GetEnumerator(); + IEnumerator e2 = b.GetEnumerator(); + while (e1.MoveNext()) { + // e1 has more elements than e2; or elements are different + if (!e2.MoveNext() || e1.Current != e2.Current) + return false; + } + if (e2.MoveNext()) // e2 has more elements than e1 + return false; + // No need to dispose e1/e2: non-generic IEnumerator doesn't implement IDisposable, + // and the underlying enumerator will likely be a List.Enumerator which has an empty Dispose() method. + return true; } - public int GetHashCode(IEnumerable obj) + public int GetHashCode(IEnumerable obj) { int hashCode = obj.GetType().GetHashCode(); unchecked { @@ -75,7 +87,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation Dictionary byValueDict = new Dictionary(); Dictionary supportsInternDict = new Dictionary(new InterningComparer()); - Dictionary, IEnumerable> listDict = new Dictionary, IEnumerable>(new ListComparer()); + Dictionary listDict = new Dictionary(new ListComparer()); public T Intern(T obj) where T : class { @@ -118,7 +130,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } if (!list.IsReadOnly) list = new ReadOnlyCollection(list); - IEnumerable output; + IEnumerable output; if (listDict.TryGetValue(list, out output)) list = (IList)output; else diff --git a/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs b/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs new file mode 100644 index 000000000..85c599947 --- /dev/null +++ b/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs @@ -0,0 +1,58 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +internal static class DotNet35Compat +{ + public static string StringJoin(string separator, IEnumerable elements) + { + #if DOTNET35 + return string.Join(separator, elements.Select(e => e != null ? e.ToString() : null).ToArray()); + #else + return string.Join(separator, elements); + #endif + } + + public static IEnumerable SafeCast(this IEnumerable elements) where T : U + { + #if DOTNET35 + foreach (T item in elements) + yield return item; + #else + return elements; + #endif + } + + public static Predicate SafeCast(this Predicate predicate) where U : T + { + #if DOTNET35 + return e => predicate(e); + #else + return predicate; + #endif + } + + #if DOTNET35 + public static IEnumerable Zip(this IEnumerable input1, IEnumerable input2, Func f) + { + using (var e1 = input1.GetEnumerator()) + using (var e2 = input2.GetEnumerator()) + while (e1.MoveNext() && e2.MoveNext()) + yield return f(e1.Current, e2.Current); + } + #endif +} + +#if DOTNET35 +namespace System.Diagnostics.Contracts { } +namespace System.Threading +{ + internal struct CancellationToken + { + public void ThrowIfCancellationRequested() {} + } +} +#endif diff --git a/NRefactory.sln b/NRefactory.sln index 575ae336b..24aed9f13 100644 --- a/NRefactory.sln +++ b/NRefactory.sln @@ -71,13 +71,13 @@ Global {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|x86.Build.0 = Release|Any CPU {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|x86.ActiveCfg = Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_3_5_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_3_5_Release|Any CPU EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj diff --git a/README b/README index 9cdcf0b24..ea347e6d3 100644 --- a/README +++ b/README @@ -6,15 +6,22 @@ ICSharpCode.NRefactory.TypeSystem: ICSharpCode.NRefactory.TypeSystem.Implementation: Contains base classes that help implementing the type system interfaces. -ICSharpCode.NRefactory.CSharp.Dom: +ICSharpCode.NRefactory.CSharp.Ast: Abstract Syntax Tree for C# ICSharpCode.NRefactory.CSharp.Resolver: Semantic analysis for C# -ICSharpCode.NRefactory.VB.Dom: +ICSharpCode.NRefactory.Util: + Various helper classes. + +ICSharpCode.NRefactory.VB.Dom: (in the separate ICSharpCode.NRefactory.VB assembly) Abstract Syntax Tree for VB +Dependencies: + .NET 3.5 or .NET 4.0 + Mono.Cecil 0.9.4 + Null-Object pattern: The NRefactory library makes extensive use of the null object pattern. As a result, NullReferenceExceptions should be very rare when working with this library. @@ -32,6 +39,10 @@ Null-Object pattern: error cases. Use ResolveResult.IsError to detect resolver errors. Also note that many resolver errors still have a meaningful type attached, this allows code completion to work in the presence of minor semantic errors. + + The C# AST makes use of special null nodes when accessing the getter of an AST property and no + child node with that role exists. Check the IsNull property to test whether a node is a null node. + Null nodes are not considered to be part of the AST (e.g. they don't have a parent). FAQ: Q: What is the difference between types and type definitions? @@ -193,3 +204,13 @@ A: Because if you're asking whether a type is a struct, it's very likely that yo If you really need to know, you can do "type.GetDefinition() != null && type.GetDefinition().ClassType == WhatIWant" yourself, but for the most part you should be fine with IsReferenceType, IsEnum and IsDelegate. + + +Q: What's the difference between the .NET 3.5 and .NET 4.0 versions? + +A: As for visible API difference, not much. The .NET 4.0 build has some additional overloads for a few methods, + taking a System.Threading.CancellationToken to allow aborting a resolve run. + Internally, the .NET 4.0 version might be tiny bit more performant because it uses covariance for IEnumerable, + where the .NET 3.5 version has to allocate wrapper objects instead. + + Both versions support loading assemblies of all .NET versions (1.0 to 4.0); and both support C# 4.0. diff --git a/VBDomGenerator/VBDomGenerator.csproj b/VBDomGenerator/VBDomGenerator.csproj index 8de206bd6..c9e014b1f 100644 --- a/VBDomGenerator/VBDomGenerator.csproj +++ b/VBDomGenerator/VBDomGenerator.csproj @@ -19,6 +19,7 @@ false v4.0 OnBuildSuccess + Client bin\Debug\ diff --git a/doc/TODO b/doc/TODO index a0e8045ea..1b43f8b85 100644 --- a/doc/TODO +++ b/doc/TODO @@ -1,15 +1,24 @@ -TypeSystem API: + +Parser: +- "extern alias" declarations +- "fixed int Field[100];" (fixed-size field declarations) +- support generics +- fix bugs (see currently ignored unit tests) +- put newlines into the AST +- add API to report errors +- allow multithreaded parsing -* Decide on the fate of ISupportsInterning (depends on how we're going to implement persistence) +Resolver: +- Tons of unit tests for TypeSystemConvertVisitor +- Lambda expressions +- Handle attributes +- Port all #D resolver unit tests to NR +- Port all MD resolver unit tests to NR -* Try to build SharedTypes for void, int, etc. - Take care of equality with the real System.Void, System.Int32 etc. - This seems to be hard/impossible to do, see comment in SharedTypes.cs. - I'm trying to work without those types now. - - Note that having shared type *references* is possible (typeof(int).ToTypeReference()) +Features: +- Code Completion +- Find References +- Extract Method refactoring -* Implement the C# parser producing the DOM -* Implement ResolveVisitor -* Implement all the nasty context-dependent stuff (local variables, lambdas) that CSharpResolver doesn't do (yet) - Where should that go? I'd like to keep it out of CSharpResolver, that class is bloated enough with the pure logic. +For integration into SharpDevelop: +- Review NR and DOM changes done in the timeframe \ No newline at end of file