diff --git a/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs index 16534dd1d6..183efacdb2 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 8b0298e605..41ba8452c0 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 90e68d8079..a1d4e1a45e 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 e3173c8cd8..fbe1af58e9 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 57604d083b..54d8d8c8b1 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 7419740ff7..9c52969206 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 6cd54f521b..d79658eff0 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 f3a39b6fd1..73ad175029 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 4b50395659..bbab99a6f4 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 5f4addd3ee..8350a6756a 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 3f9ce69eb6..960b53355f 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 f02c795e25..895ffff4c0 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 7b1d18e035..5601797c95 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 a50c1b77f6..f6a85fcb3b 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 038925a42a..c28d559fcb 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 599aae19fb..3dcc932d98 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 c704b88577..a968af1ebd 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 51e046976a..e443e7b94c 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 525306bd61..8748164503 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 d79e33fe24..c9d4b7801f 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 94b282539a..7522b0284b 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 08ff938b82..bf62bec0e2 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 1d0324f4a4..fc18cdab4c 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 202b7f0ae8..7187f4b5d6 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 ae5598f2c3..ae4d75d933 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 fe1bd468c9..7e9d13453f 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 f91cbed4a1..6f47dc5887 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 90f14b26e0..5353808fca 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 53e0f31388..e3302d7c07 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 e2901f54ee..4956d374aa 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 5c4bebed3d..fba68f26ee 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 11ab8c47ce..2f84aa28c1 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 374817f4d1..40cd75b3b8 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 bf77b15c9e..f5ef169b6d 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 f08560c21d..7bc0981b52 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 db980b3703..fef832cb37 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 52d8510108..4770022416 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 511d6fd06a..2d0a5a7962 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 a5361ef4f9..2dab5a5ad9 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 033ad79131..c7f266d97b 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 08bf473d4b..a35204e3cd 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 6b2b12959a..ec0a85705c 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 4e62889636..a776f259f5 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 6578c58269..dffc3dd3dc 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 79a357e87b..9841a74685 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 a192718dac..901f6ba06e 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 514a411922..8bac245c76 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 eccac93825..e014a4b3f8 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 fd638f2da9..df7ac21388 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 30e2fdf2fa..84c9b2f507 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 f63e97bf74..2db1b06e02 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 70448e56a9..b91048a5c9 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 073415f519..37c89a58e1 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 2bac1c6e19..f68feb443d 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 55839229ce..237b3b55ba 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 d43a0d538a..9ee89966d0 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 b1b7759f03..9a8efbc9ac 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 910aec75fb..c487032ebc 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 1b878d91ce..41eec380d1 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 97f808051d..4971a4eec3 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 2798d0660c..8a892b275c 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 0715898f04..e2784f565a 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 3a916782d3..49d28ede35 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 3ca04772df..1003aa9b75 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 5b63c9c4f3..4d19c97d73 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 5cd468cfe8..a7e1b74e46 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 ef740bd86b..556c0a3a4c 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 c8a326c497..7215412eb7 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 0334d2a3fb..5544c5aa77 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 d13ce8f5c1..2d1376a0ed 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 88995ee47f..e5c307f668 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); } } @@ -1043,7 +1069,7 @@ namespace ICSharpCode.NRefactory.CSharp StartNode(queryOrderClause); WriteKeyword("orderby"); Space(); - WriteCommaSeparatedList(queryOrderClause.Orderings); + WriteCommaSeparatedList(queryOrderClause.Orderings.SafeCast()); return EndNode(queryOrderClause); } @@ -1093,7 +1119,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); } @@ -1106,9 +1133,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); } @@ -1186,7 +1214,7 @@ namespace ICSharpCode.NRefactory.CSharp if (first) { first = false; } else { - Comma(member); + Comma(member, noSpaceAfterComma: true); NewLine(); } member.AcceptVisitor(this, data); @@ -1355,7 +1383,7 @@ namespace ICSharpCode.NRefactory.CSharp LPar(); Space(policy.WithinForParentheses); - WriteCommaSeparatedList(forStatement.Initializers); + WriteCommaSeparatedList(forStatement.Initializers.SafeCast()); WriteToken(";", AstNode.Roles.Semicolon); Space(policy.SpacesAfterSemicolon); @@ -1363,7 +1391,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken(";", AstNode.Roles.Semicolon); Space(policy.SpacesAfterSemicolon); - WriteCommaSeparatedList(forStatement.Iterators); + WriteCommaSeparatedList(forStatement.Iterators.SafeCast()); Space(policy.WithinForParentheses); RPar(); @@ -1899,7 +1927,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); @@ -1935,6 +1966,11 @@ namespace ICSharpCode.NRefactory.CSharp { StartNode(primitiveType); WriteKeyword(primitiveType.Keyword); + if (primitiveType.Keyword == "new") { + // new() constraint + LPar(); + RPar(); + } return EndNode(primitiveType); } @@ -1953,6 +1989,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 bb447f4c6c..68ac7ee2f6 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 281e3e569c..6fac5b0daf 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 3dbf53a42a..904bbae995 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 615c23947c..f124141faf 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 e9b0da565b..350701a0e0 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 7c72f8d8bc..d4d1fca43c 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 f950a474ee..060bdfa7fa 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 e51fde6286..a500e85e00 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 afdfca58d0..488a6c31fc 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 a001adbd43..6dcddc3105 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 65bcae4b9c..7564ed9959 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 4c830048a2..da2a6c06af 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 62d748290f..b9bb2dd97d 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 030f5a1186..8ea9a8f3df 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 752cb693dc..d9f92d1cea 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 91259ff0e1..60452a6702 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 c72526a78e..c5c0152998 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 1705b4d752..baa35f42db 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 3e8f456553..16b23d0634 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 4fc545495e..4a51074bf5 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 56ded253d2..e66ab07820 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 407caf6c38..789108543b 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 0333a45a94..3f7d9b0825 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 e719ca59a8..a60c75133b 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 274bcfbe3a..be4d9651d7 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 771ff43f9a..86de1c3790 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 d8cec40917..f6d3b3a32d 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 dc8576d8f3..905a85fdca 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 ee7f43dfc6..75d6d4cb4d 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 70f105b3a8..50795311b2 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 335153ee6c..3c89b13ade 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 cc4dfa9c45..5c8f1d9031 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 b2f981df6a..9fd926da90 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 220f09a12a..0f412842d5 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 4964cacc4e..881d38585b 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 ce5c858644..7ed18be858 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 0000000000..85c599947e --- /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 575ae336b1..24aed9f134 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 9cdcf0b241..ea347e6d30 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 8de206bd6d..c9e014b1f8 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 a0e8045eaf..1b43f8b85f 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