From 0ecf1fc71e441c6058735ee946112f13f4412c6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 15 Aug 2011 09:49:35 +0200 Subject: [PATCH 01/15] Fixed collection initializer parsing. --- .../CSharp/Parser/CSharpParser.cs | 32 +- .../CSharp/Parser/mcs/cs-parser.cs | 1288 +++++++++-------- .../CSharp/Parser/mcs/cs-parser.jay | 8 + .../CSharp/Parser/mcs/expression.cs | 14 +- 4 files changed, 698 insertions(+), 644 deletions(-) diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index 498e26b46b..48be73e35c 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -2262,7 +2262,6 @@ namespace ICSharpCode.NRefactory.CSharp return; var commaLocations = LocationsBag.GetLocations (args); - for (int i = 0; i < args.Count; i++) { parent.AddChild (ConvertArgument (args[i]), InvocationExpression.Roles.Argument); if (commaLocations != null && i > 0) { @@ -2279,7 +2278,8 @@ namespace ICSharpCode.NRefactory.CSharp { var result = new InvocationExpression (); var location = LocationsBag.GetLocations (invocationExpression); - result.AddChild ((Expression)invocationExpression.Expression.Accept (this), InvocationExpression.Roles.TargetExpression); + if (invocationExpression.Expression != null) + result.AddChild ((Expression)invocationExpression.Expression.Accept (this), InvocationExpression.Roles.TargetExpression); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), InvocationExpression.Roles.LPar); AddArguments (result, location, invocationExpression.Arguments); @@ -2292,7 +2292,6 @@ namespace ICSharpCode.NRefactory.CSharp public override object Visit (New newExpression) { var result = new ObjectCreateExpression (); - var location = LocationsBag.GetLocations (newExpression); result.AddChild (new CSharpTokenNode (Convert (newExpression.Location), "new".Length), ObjectCreateExpression.Roles.Keyword); @@ -2345,6 +2344,33 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ObjectCreateExpression.Roles.RPar); + var minit = newInitializeExpression.Initializers; + if (minit != null){ + var init = new ArrayInitializerExpression (); + var initLoc = LocationsBag.GetLocations (newInitializeExpression); + if (initLoc != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ArrayInitializerExpression.Roles.LBrace); + var commaLoc = LocationsBag.GetLocations (minit.Initializers); + int curComma = commaLoc != null ? commaLoc.Count - 1 : -1; + foreach (var expr in minit.Initializers) { + var eleInit = expr as CollectionElementInitializer; + if (eleInit == null) + continue; + for (int i = 0; i < eleInit.Arguments.Count; i++) { + var arg = eleInit.Arguments[i] as CollectionElementInitializer.ElementInitializerArgument; + if (arg == null) + continue; + init.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); + if (curComma >= 0) + init.AddChild (new CSharpTokenNode (Convert (commaLoc[curComma--]), 1), ArrayInitializerExpression.Roles.Comma); + } + } + if (initLoc != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ArrayInitializerExpression.Roles.RBrace); + result.AddChild (init, ObjectCreateExpression.InitializerRole); + } + + return result; } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs index 0cee24dd0c..871c6b38a7 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs @@ -1518,7 +1518,7 @@ case 62: case_62(); break; case 63: -#line 765 "cs-parser.jay" +#line 766 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1527,14 +1527,14 @@ case 64: case_64(); break; case 66: -#line 789 "cs-parser.jay" +#line 790 "cs-parser.jay" { yyVal = null; } break; case 67: case_67(); break; case 68: -#line 800 "cs-parser.jay" +#line 801 "cs-parser.jay" { yyVal = null; } break; case 69: @@ -1550,13 +1550,13 @@ case 72: case_72(); break; case 73: -#line 844 "cs-parser.jay" +#line 845 "cs-parser.jay" { yyVal = new Argument ((Expression) yyVals[0+yyTop]); } break; case 75: -#line 852 "cs-parser.jay" +#line 853 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1568,17 +1568,17 @@ case 77: case_77(); break; case 78: -#line 877 "cs-parser.jay" +#line 878 "cs-parser.jay" { yyVal = null; } break; case 79: -#line 881 "cs-parser.jay" +#line 882 "cs-parser.jay" { yyVal = Argument.AType.Ref; } break; case 80: -#line 885 "cs-parser.jay" +#line 886 "cs-parser.jay" { yyVal = Argument.AType.Out; } @@ -1587,7 +1587,7 @@ case 95: case_95(); break; case 96: -#line 926 "cs-parser.jay" +#line 927 "cs-parser.jay" { lexer.ConstraintsParsing = true; } @@ -1605,7 +1605,7 @@ case 100: case_100(); break; case 101: -#line 958 "cs-parser.jay" +#line 959 "cs-parser.jay" { Error_SyntaxError (yyToken); } @@ -1614,7 +1614,7 @@ case 102: case_102(); break; case 103: -#line 970 "cs-parser.jay" +#line 971 "cs-parser.jay" { lbag.AppendToMember (current_class, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); } @@ -1626,13 +1626,13 @@ case 119: case_119(); break; case 122: -#line 1039 "cs-parser.jay" +#line 1040 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; case 123: -#line 1043 "cs-parser.jay" +#line 1044 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } @@ -1641,7 +1641,7 @@ case 124: case_124(); break; case 125: -#line 1059 "cs-parser.jay" +#line 1060 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1665,7 +1665,7 @@ case 133: case_133(); break; case 134: -#line 1138 "cs-parser.jay" +#line 1139 "cs-parser.jay" { report.Error (1641, GetLocation (yyVals[-1+yyTop]), "A fixed size buffer field must have the array size specifier after the field name"); } @@ -1677,13 +1677,13 @@ case 137: case_137(); break; case 140: -#line 1168 "cs-parser.jay" +#line 1169 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; case 141: -#line 1172 "cs-parser.jay" +#line 1173 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } @@ -1692,7 +1692,7 @@ case 142: case_142(); break; case 143: -#line 1185 "cs-parser.jay" +#line 1186 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1701,13 +1701,13 @@ case 144: case_144(); break; case 147: -#line 1204 "cs-parser.jay" +#line 1205 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; case 148: -#line 1208 "cs-parser.jay" +#line 1209 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } @@ -1716,7 +1716,7 @@ case 149: case_149(); break; case 150: -#line 1224 "cs-parser.jay" +#line 1225 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1737,13 +1737,13 @@ case 157: case_157(); break; case 158: -#line 1291 "cs-parser.jay" +#line 1292 "cs-parser.jay" { valid_param_mod = ParameterModifierType.All; } break; case 159: -#line 1295 "cs-parser.jay" +#line 1296 "cs-parser.jay" { lexer.ConstraintsParsing = true; } @@ -1752,7 +1752,7 @@ case 160: case_160(); break; case 161: -#line 1335 "cs-parser.jay" +#line 1336 "cs-parser.jay" { lexer.parsing_generic_declaration = true; } @@ -1761,7 +1761,7 @@ case 162: case_162(); break; case 163: -#line 1345 "cs-parser.jay" +#line 1346 "cs-parser.jay" { lexer.ConstraintsParsing = true; } @@ -1773,11 +1773,11 @@ case 165: case_165(); break; case 167: -#line 1419 "cs-parser.jay" +#line 1420 "cs-parser.jay" { yyVal = null; } break; case 168: -#line 1423 "cs-parser.jay" +#line 1424 "cs-parser.jay" { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } break; case 170: @@ -1802,13 +1802,13 @@ case 176: case_176(); break; case 177: -#line 1482 "cs-parser.jay" +#line 1483 "cs-parser.jay" { yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[0+yyTop] } ); } break; case 178: -#line 1486 "cs-parser.jay" +#line 1487 "cs-parser.jay" { yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[0+yyTop])) }, true); } @@ -1832,7 +1832,7 @@ case 184: case_184(); break; case 185: -#line 1561 "cs-parser.jay" +#line 1562 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1841,7 +1841,7 @@ case 186: case_186(); break; case 187: -#line 1602 "cs-parser.jay" +#line 1603 "cs-parser.jay" { yyVal = Parameter.Modifier.NONE; } break; case 189: @@ -1875,7 +1875,7 @@ case 198: case_198(); break; case 199: -#line 1700 "cs-parser.jay" +#line 1701 "cs-parser.jay" { Error_DuplicateParameterModifier (GetLocation (yyVals[-1+yyTop]), Parameter.Modifier.PARAMS); } @@ -1896,7 +1896,7 @@ case 204: case_204(); break; case 205: -#line 1754 "cs-parser.jay" +#line 1755 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; } @@ -1905,7 +1905,7 @@ case 206: case_206(); break; case 207: -#line 1783 "cs-parser.jay" +#line 1784 "cs-parser.jay" { lexer.PropertyParsing = false; } @@ -1935,7 +1935,7 @@ case 220: case_220(); break; case 221: -#line 1928 "cs-parser.jay" +#line 1929 "cs-parser.jay" { lexer.ConstraintsParsing = true; } @@ -1953,43 +1953,43 @@ case 225: case_225(); break; case 226: -#line 1961 "cs-parser.jay" +#line 1962 "cs-parser.jay" { Error_SyntaxError (yyToken); } break; case 231: -#line 1978 "cs-parser.jay" +#line 1979 "cs-parser.jay" { report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); } break; case 232: -#line 1982 "cs-parser.jay" +#line 1983 "cs-parser.jay" { report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); } break; case 237: -#line 1990 "cs-parser.jay" +#line 1991 "cs-parser.jay" { report.Error (567, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain operators"); } break; case 238: -#line 1994 "cs-parser.jay" +#line 1995 "cs-parser.jay" { report.Error (526, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain contructors"); } break; case 239: -#line 1998 "cs-parser.jay" +#line 1999 "cs-parser.jay" { report.Error (524, GetLocation (yyVals[0+yyTop]), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); } break; case 240: -#line 2004 "cs-parser.jay" +#line 2005 "cs-parser.jay" { } break; @@ -1997,14 +1997,14 @@ case 241: case_241(); break; case 243: -#line 2034 "cs-parser.jay" +#line 2035 "cs-parser.jay" { yyVal = null; } break; case 245: case_245(); break; case 246: -#line 2050 "cs-parser.jay" +#line 2051 "cs-parser.jay" { valid_param_mod = ParameterModifierType.DefaultValue; } @@ -2013,95 +2013,95 @@ case 247: case_247(); break; case 249: -#line 2096 "cs-parser.jay" +#line 2097 "cs-parser.jay" { yyVal = Operator.OpType.LogicalNot; } break; case 250: -#line 2097 "cs-parser.jay" +#line 2098 "cs-parser.jay" { yyVal = Operator.OpType.OnesComplement; } break; case 251: -#line 2098 "cs-parser.jay" +#line 2099 "cs-parser.jay" { yyVal = Operator.OpType.Increment; } break; case 252: -#line 2099 "cs-parser.jay" +#line 2100 "cs-parser.jay" { yyVal = Operator.OpType.Decrement; } break; case 253: -#line 2100 "cs-parser.jay" +#line 2101 "cs-parser.jay" { yyVal = Operator.OpType.True; } break; case 254: -#line 2101 "cs-parser.jay" +#line 2102 "cs-parser.jay" { yyVal = Operator.OpType.False; } break; case 255: -#line 2103 "cs-parser.jay" +#line 2104 "cs-parser.jay" { yyVal = Operator.OpType.Addition; } break; case 256: -#line 2104 "cs-parser.jay" +#line 2105 "cs-parser.jay" { yyVal = Operator.OpType.Subtraction; } break; case 257: -#line 2106 "cs-parser.jay" +#line 2107 "cs-parser.jay" { yyVal = Operator.OpType.Multiply; } break; case 258: -#line 2107 "cs-parser.jay" +#line 2108 "cs-parser.jay" { yyVal = Operator.OpType.Division; } break; case 259: -#line 2108 "cs-parser.jay" +#line 2109 "cs-parser.jay" { yyVal = Operator.OpType.Modulus; } break; case 260: -#line 2109 "cs-parser.jay" +#line 2110 "cs-parser.jay" { yyVal = Operator.OpType.BitwiseAnd; } break; case 261: -#line 2110 "cs-parser.jay" +#line 2111 "cs-parser.jay" { yyVal = Operator.OpType.BitwiseOr; } break; case 262: -#line 2111 "cs-parser.jay" +#line 2112 "cs-parser.jay" { yyVal = Operator.OpType.ExclusiveOr; } break; case 263: -#line 2112 "cs-parser.jay" +#line 2113 "cs-parser.jay" { yyVal = Operator.OpType.LeftShift; } break; case 264: -#line 2113 "cs-parser.jay" +#line 2114 "cs-parser.jay" { yyVal = Operator.OpType.RightShift; } break; case 265: -#line 2114 "cs-parser.jay" +#line 2115 "cs-parser.jay" { yyVal = Operator.OpType.Equality; } break; case 266: -#line 2115 "cs-parser.jay" +#line 2116 "cs-parser.jay" { yyVal = Operator.OpType.Inequality; } break; case 267: -#line 2116 "cs-parser.jay" +#line 2117 "cs-parser.jay" { yyVal = Operator.OpType.GreaterThan; } break; case 268: -#line 2117 "cs-parser.jay" +#line 2118 "cs-parser.jay" { yyVal = Operator.OpType.LessThan; } break; case 269: -#line 2118 "cs-parser.jay" +#line 2119 "cs-parser.jay" { yyVal = Operator.OpType.GreaterThanOrEqual; } break; case 270: -#line 2119 "cs-parser.jay" +#line 2120 "cs-parser.jay" { yyVal = Operator.OpType.LessThanOrEqual; } break; case 271: -#line 2126 "cs-parser.jay" +#line 2127 "cs-parser.jay" { valid_param_mod = ParameterModifierType.DefaultValue; } @@ -2110,7 +2110,7 @@ case 272: case_272(); break; case 273: -#line 2145 "cs-parser.jay" +#line 2146 "cs-parser.jay" { valid_param_mod = ParameterModifierType.DefaultValue; } @@ -2137,11 +2137,11 @@ case 280: case_280(); break; case 282: -#line 2248 "cs-parser.jay" +#line 2249 "cs-parser.jay" { current_block = null; yyVal = null; } break; case 285: -#line 2260 "cs-parser.jay" +#line 2261 "cs-parser.jay" { ++lexer.parsing_block; } @@ -2150,7 +2150,7 @@ case 286: case_286(); break; case 287: -#line 2270 "cs-parser.jay" +#line 2271 "cs-parser.jay" { ++lexer.parsing_block; } @@ -2183,7 +2183,7 @@ case 296: case_296(); break; case 298: -#line 2379 "cs-parser.jay" +#line 2380 "cs-parser.jay" { ++lexer.parsing_block; } @@ -2192,13 +2192,13 @@ case 299: case_299(); break; case 302: -#line 2396 "cs-parser.jay" +#line 2397 "cs-parser.jay" { current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; case 303: -#line 2400 "cs-parser.jay" +#line 2401 "cs-parser.jay" { current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } @@ -2207,7 +2207,7 @@ case 304: case_304(); break; case 305: -#line 2413 "cs-parser.jay" +#line 2414 "cs-parser.jay" { ++lexer.parsing_block; } @@ -2219,7 +2219,7 @@ case 307: case_307(); break; case 308: -#line 2438 "cs-parser.jay" +#line 2439 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; } @@ -2267,7 +2267,7 @@ case 326: case_326(); break; case 329: -#line 2593 "cs-parser.jay" +#line 2594 "cs-parser.jay" { lbag.AddLocation (yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); } @@ -2285,7 +2285,7 @@ case 334: case_334(); break; case 335: -#line 2651 "cs-parser.jay" +#line 2652 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; } @@ -2294,7 +2294,7 @@ case 336: case_336(); break; case 337: -#line 2673 "cs-parser.jay" +#line 2674 "cs-parser.jay" { lexer.ConstraintsParsing = false; } @@ -2327,7 +2327,7 @@ case 350: case_350(); break; case 351: -#line 2777 "cs-parser.jay" +#line 2779 "cs-parser.jay" { lexer.parsing_generic_declaration = true; } @@ -2372,13 +2372,13 @@ case 366: case_366(); break; case 368: -#line 2895 "cs-parser.jay" +#line 2897 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); } break; case 369: -#line 2902 "cs-parser.jay" +#line 2904 "cs-parser.jay" { lexer.parsing_generic_declaration = true; } @@ -2393,7 +2393,7 @@ case 375: case_375(); break; case 377: -#line 2940 "cs-parser.jay" +#line 2942 "cs-parser.jay" { yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } @@ -2402,7 +2402,7 @@ case 378: case_378(); break; case 379: -#line 2960 "cs-parser.jay" +#line 2962 "cs-parser.jay" { yyVal = new ComposedCast (((MemberName) yyVals[-1+yyTop]).GetTypeExpression (), (ComposedTypeSpecifier) yyVals[0+yyTop]); } @@ -2411,13 +2411,13 @@ case 380: case_380(); break; case 381: -#line 2969 "cs-parser.jay" +#line 2971 "cs-parser.jay" { yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; case 382: -#line 2973 "cs-parser.jay" +#line 2975 "cs-parser.jay" { yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); } @@ -2435,63 +2435,63 @@ case 386: case_386(); break; case 387: -#line 3011 "cs-parser.jay" +#line 3014 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation (yyVals[0+yyTop])); } break; case 388: -#line 3012 "cs-parser.jay" +#line 3015 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.String, GetLocation (yyVals[0+yyTop])); } break; case 389: -#line 3013 "cs-parser.jay" +#line 3016 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation (yyVals[0+yyTop])); } break; case 390: -#line 3014 "cs-parser.jay" +#line 3017 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation (yyVals[0+yyTop])); } break; case 391: -#line 3015 "cs-parser.jay" +#line 3018 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation (yyVals[0+yyTop])); } break; case 392: -#line 3016 "cs-parser.jay" +#line 3019 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation (yyVals[0+yyTop])); } break; case 394: -#line 3021 "cs-parser.jay" +#line 3024 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation (yyVals[0+yyTop])); } break; case 395: -#line 3022 "cs-parser.jay" +#line 3025 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation (yyVals[0+yyTop])); } break; case 396: -#line 3023 "cs-parser.jay" +#line 3026 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation (yyVals[0+yyTop])); } break; case 397: -#line 3024 "cs-parser.jay" +#line 3027 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation (yyVals[0+yyTop])); } break; case 398: -#line 3025 "cs-parser.jay" +#line 3028 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation (yyVals[0+yyTop])); } break; case 399: -#line 3026 "cs-parser.jay" +#line 3029 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation (yyVals[0+yyTop])); } break; case 400: -#line 3027 "cs-parser.jay" +#line 3030 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation (yyVals[0+yyTop])); } break; case 401: -#line 3028 "cs-parser.jay" +#line 3031 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation (yyVals[0+yyTop])); } break; case 402: -#line 3029 "cs-parser.jay" +#line 3032 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation (yyVals[0+yyTop])); } break; case 423: @@ -2501,22 +2501,22 @@ case 424: case_424(); break; case 428: -#line 3076 "cs-parser.jay" +#line 3079 "cs-parser.jay" { yyVal = new NullLiteral (GetLocation (yyVals[0+yyTop])); } break; case 429: -#line 3080 "cs-parser.jay" +#line 3083 "cs-parser.jay" { yyVal = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation (yyVals[0+yyTop])); } break; case 430: -#line 3081 "cs-parser.jay" +#line 3084 "cs-parser.jay" { yyVal = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation (yyVals[0+yyTop])); } break; case 435: case_435(); break; case 436: -#line 3114 "cs-parser.jay" +#line 3117 "cs-parser.jay" { yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); } @@ -2534,7 +2534,7 @@ case 440: case_440(); break; case 441: -#line 3146 "cs-parser.jay" +#line 3149 "cs-parser.jay" { yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null,GetLocation (yyVals[0+yyTop])); } @@ -2543,7 +2543,7 @@ case 442: case_442(); break; case 443: -#line 3154 "cs-parser.jay" +#line 3157 "cs-parser.jay" { yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null, lexer.Location); } @@ -2555,7 +2555,7 @@ case 445: case_445(); break; case 446: -#line 3170 "cs-parser.jay" +#line 3173 "cs-parser.jay" { yyVal = null; } break; case 448: @@ -2565,11 +2565,11 @@ case 449: case_449(); break; case 450: -#line 3193 "cs-parser.jay" +#line 3196 "cs-parser.jay" { yyVal = null; } break; case 451: -#line 3197 "cs-parser.jay" +#line 3200 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; } @@ -2587,7 +2587,7 @@ case 455: case_455(); break; case 456: -#line 3229 "cs-parser.jay" +#line 3233 "cs-parser.jay" { yyVal = new CompletionElementInitializer (null, GetLocation (yyVals[0+yyTop])); } @@ -2602,7 +2602,7 @@ case 459: case_459(); break; case 462: -#line 3257 "cs-parser.jay" +#line 3261 "cs-parser.jay" { yyVal = null; } break; case 464: @@ -2621,7 +2621,7 @@ case 468: case_468(); break; case 469: -#line 3309 "cs-parser.jay" +#line 3313 "cs-parser.jay" { yyVal = new Argument ((Expression) yyVals[0+yyTop]); } @@ -2657,13 +2657,13 @@ case 483: case_483(); break; case 484: -#line 3396 "cs-parser.jay" +#line 3400 "cs-parser.jay" { yyVal = new Argument ((Expression) yyVals[0+yyTop]); } break; case 486: -#line 3404 "cs-parser.jay" +#line 3408 "cs-parser.jay" { yyVal = new This (GetLocation (yyVals[0+yyTop])); } @@ -2675,13 +2675,13 @@ case 488: case_488(); break; case 489: -#line 3424 "cs-parser.jay" +#line 3428 "cs-parser.jay" { yyVal = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); } break; case 490: -#line 3431 "cs-parser.jay" +#line 3435 "cs-parser.jay" { yyVal = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); } @@ -2708,7 +2708,7 @@ case 497: case_497(); break; case 498: -#line 3497 "cs-parser.jay" +#line 3501 "cs-parser.jay" { ++lexer.parsing_type; } @@ -2720,7 +2720,7 @@ case 500: case_500(); break; case 503: -#line 3524 "cs-parser.jay" +#line 3528 "cs-parser.jay" { yyVal = null; } break; case 505: @@ -2751,25 +2751,25 @@ case 516: case_516(); break; case 517: -#line 3600 "cs-parser.jay" +#line 3606 "cs-parser.jay" { yyVal = 2; } break; case 518: -#line 3604 "cs-parser.jay" +#line 3610 "cs-parser.jay" { yyVal = ((int) yyVals[-1+yyTop]) + 1; } break; case 519: -#line 3611 "cs-parser.jay" +#line 3617 "cs-parser.jay" { yyVal = null; } break; case 520: -#line 3615 "cs-parser.jay" +#line 3621 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; } @@ -2787,7 +2787,7 @@ case 524: case_524(); break; case 525: -#line 3659 "cs-parser.jay" +#line 3665 "cs-parser.jay" { lexer.TypeOfParsing = true; } @@ -2832,7 +2832,7 @@ case 540: case_540(); break; case 541: -#line 3773 "cs-parser.jay" +#line 3779 "cs-parser.jay" { start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], false, GetLocation (yyVals[-1+yyTop])); } @@ -2841,25 +2841,25 @@ case 542: case_542(); break; case 543: -#line 3786 "cs-parser.jay" +#line 3792 "cs-parser.jay" { start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], true, GetLocation (yyVals[-2+yyTop])); } break; case 544: -#line 3790 "cs-parser.jay" +#line 3796 "cs-parser.jay" { yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); } break; case 545: -#line 3797 "cs-parser.jay" +#line 3803 "cs-parser.jay" { yyVal = ParametersCompiled.Undefined; } break; case 547: -#line 3805 "cs-parser.jay" +#line 3811 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } @@ -2871,13 +2871,13 @@ case 549: case_549(); break; case 551: -#line 3831 "cs-parser.jay" +#line 3837 "cs-parser.jay" { yyVal = new Unary (Unary.Operator.LogicalNot, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 552: -#line 3835 "cs-parser.jay" +#line 3841 "cs-parser.jay" { yyVal = new Unary (Unary.Operator.OnesComplement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } @@ -2889,37 +2889,37 @@ case 556: case_556(); break; case 558: -#line 3865 "cs-parser.jay" +#line 3871 "cs-parser.jay" { yyVal = new Unary (Unary.Operator.UnaryPlus, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 559: -#line 3869 "cs-parser.jay" +#line 3875 "cs-parser.jay" { yyVal = new Unary (Unary.Operator.UnaryNegation, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 560: -#line 3873 "cs-parser.jay" +#line 3879 "cs-parser.jay" { yyVal = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 561: -#line 3877 "cs-parser.jay" +#line 3883 "cs-parser.jay" { yyVal = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 562: -#line 3881 "cs-parser.jay" +#line 3887 "cs-parser.jay" { yyVal = new Indirection ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 563: -#line 3885 "cs-parser.jay" +#line 3891 "cs-parser.jay" { yyVal = new Unary (Unary.Operator.AddressOf, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } @@ -2937,7 +2937,7 @@ case 569: case_569(); break; case 570: -#line 3917 "cs-parser.jay" +#line 3923 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } @@ -2946,13 +2946,13 @@ case 571: case_571(); break; case 572: -#line 3926 "cs-parser.jay" +#line 3932 "cs-parser.jay" { yyVal = new As ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 573: -#line 3930 "cs-parser.jay" +#line 3936 "cs-parser.jay" { yyVal = new Is ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } @@ -3003,7 +3003,7 @@ case 598: case_598(); break; case 599: -#line 4054 "cs-parser.jay" +#line 4060 "cs-parser.jay" { yyVal = new SimpleAssign ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } @@ -3054,14 +3054,14 @@ case 614: case_614(); break; case 615: -#line 4149 "cs-parser.jay" +#line 4157 "cs-parser.jay" { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } break; case 616: case_616(); break; case 619: -#line 4164 "cs-parser.jay" +#line 4172 "cs-parser.jay" { start_block (lexer.Location); } @@ -3085,7 +3085,7 @@ case 626: case_626(); break; case 627: -#line 4209 "cs-parser.jay" +#line 4217 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } @@ -3097,7 +3097,7 @@ case 629: case_629(); break; case 630: -#line 4223 "cs-parser.jay" +#line 4231 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } @@ -3109,7 +3109,7 @@ case 632: case_632(); break; case 638: -#line 4248 "cs-parser.jay" +#line 4256 "cs-parser.jay" { yyVal = new ArglistAccess (GetLocation (yyVals[0+yyTop])); } @@ -3124,13 +3124,13 @@ case 641: case_641(); break; case 643: -#line 4277 "cs-parser.jay" +#line 4285 "cs-parser.jay" { yyVal = new BooleanExpression ((Expression) yyVals[0+yyTop]); } break; case 644: -#line 4290 "cs-parser.jay" +#line 4298 "cs-parser.jay" { lexer.ConstraintsParsing = true; } @@ -3148,11 +3148,11 @@ case 648: case_648(); break; case 649: -#line 4329 "cs-parser.jay" +#line 4337 "cs-parser.jay" { yyVal = null; } break; case 650: -#line 4331 "cs-parser.jay" +#line 4339 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; StoreModifierLocation (Modifiers.PARTIAL, GetLocation (yyVals[0+yyTop])); } break; case 651: @@ -3207,13 +3207,13 @@ case 669: case_669(); break; case 671: -#line 4451 "cs-parser.jay" +#line 4459 "cs-parser.jay" { current_container.AddBasesForPart (current_class, (List) yyVals[0+yyTop]); } break; case 673: -#line 4459 "cs-parser.jay" +#line 4467 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; } @@ -3243,19 +3243,19 @@ case 681: case_681(); break; case 682: -#line 4548 "cs-parser.jay" +#line 4556 "cs-parser.jay" { yyVal = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation (yyVals[0+yyTop])); } break; case 683: -#line 4552 "cs-parser.jay" +#line 4560 "cs-parser.jay" { yyVal = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation (yyVals[0+yyTop])); } break; case 684: -#line 4559 "cs-parser.jay" +#line 4567 "cs-parser.jay" { yyVal = Variance.None; } @@ -3264,13 +3264,13 @@ case 685: case_685(); break; case 686: -#line 4573 "cs-parser.jay" +#line 4581 "cs-parser.jay" { yyVal = Variance.Covariant; } break; case 687: -#line 4577 "cs-parser.jay" +#line 4585 "cs-parser.jay" { yyVal = Variance.Contravariant; } @@ -3279,7 +3279,7 @@ case 688: case_688(); break; case 689: -#line 4602 "cs-parser.jay" +#line 4610 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; } @@ -3297,13 +3297,13 @@ case 693: case_693(); break; case 698: -#line 4646 "cs-parser.jay" +#line 4654 "cs-parser.jay" { current_block.AddStatement ((Statement) yyVals[0+yyTop]); } break; case 699: -#line 4650 "cs-parser.jay" +#line 4658 "cs-parser.jay" { current_block.AddStatement ((Statement) yyVals[0+yyTop]); } @@ -3312,13 +3312,13 @@ case 701: case_701(); break; case 704: -#line 4674 "cs-parser.jay" +#line 4682 "cs-parser.jay" { current_block.AddStatement ((Statement) yyVals[0+yyTop]); } break; case 705: -#line 4678 "cs-parser.jay" +#line 4686 "cs-parser.jay" { current_block.AddStatement ((Statement) yyVals[0+yyTop]); } @@ -3351,13 +3351,13 @@ case 744: case_744(); break; case 745: -#line 4822 "cs-parser.jay" +#line 4830 "cs-parser.jay" { yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; case 746: -#line 4826 "cs-parser.jay" +#line 4834 "cs-parser.jay" { yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); } @@ -3369,7 +3369,7 @@ case 749: case_749(); break; case 750: -#line 4847 "cs-parser.jay" +#line 4855 "cs-parser.jay" { yyVal = ComposedTypeSpecifier.CreatePointer (GetLocation (yyVals[0+yyTop])); } @@ -3399,7 +3399,7 @@ case 763: case_763(); break; case 764: -#line 4936 "cs-parser.jay" +#line 4944 "cs-parser.jay" { report.Error (145, lexer.Location, "A const field requires a value to be provided"); } @@ -3420,15 +3420,15 @@ case 774: case_774(); break; case 775: -#line 4986 "cs-parser.jay" +#line 4994 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; } break; case 776: -#line 4990 "cs-parser.jay" +#line 4998 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; } break; case 777: -#line 4991 "cs-parser.jay" +#line 4999 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; } break; case 778: @@ -3447,7 +3447,7 @@ case 784: case_784(); break; case 785: -#line 5059 "cs-parser.jay" +#line 5067 "cs-parser.jay" { start_block (GetLocation (yyVals[0+yyTop])); } @@ -3468,13 +3468,13 @@ case 791: case_791(); break; case 792: -#line 5103 "cs-parser.jay" +#line 5111 "cs-parser.jay" { current_block = current_block.CreateSwitchBlock (lexer.Location); } break; case 793: -#line 5107 "cs-parser.jay" +#line 5115 "cs-parser.jay" { yyVal = new SwitchSection ((List) yyVals[-2+yyTop], current_block); } @@ -3489,7 +3489,7 @@ case 796: case_796(); break; case 797: -#line 5136 "cs-parser.jay" +#line 5144 "cs-parser.jay" { yyVal = new SwitchLabel (null, GetLocation (yyVals[0+yyTop])); } @@ -3504,7 +3504,7 @@ case 804: case_804(); break; case 805: -#line 5175 "cs-parser.jay" +#line 5183 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; } @@ -3516,7 +3516,7 @@ case 807: case_807(); break; case 808: -#line 5203 "cs-parser.jay" +#line 5211 "cs-parser.jay" { yyVal = new EmptyStatement (lexer.Location); } break; case 810: @@ -3526,11 +3526,11 @@ case 811: case_811(); break; case 813: -#line 5224 "cs-parser.jay" +#line 5232 "cs-parser.jay" { yyVal = null; } break; case 815: -#line 5229 "cs-parser.jay" +#line 5237 "cs-parser.jay" { yyVal = new EmptyStatement (lexer.Location); } break; case 819: @@ -3573,7 +3573,7 @@ case 837: case_837(); break; case 840: -#line 5384 "cs-parser.jay" +#line 5392 "cs-parser.jay" { yyVal = new TryCatch ((Block) yyVals[-1+yyTop], (List) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop]), false); } @@ -3594,7 +3594,7 @@ case 845: case_845(); break; case 848: -#line 5437 "cs-parser.jay" +#line 5445 "cs-parser.jay" { yyVal = new Catch ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } @@ -3603,7 +3603,7 @@ case 849: case_849(); break; case 850: -#line 5456 "cs-parser.jay" +#line 5464 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; } @@ -3612,13 +3612,13 @@ case 851: case_851(); break; case 852: -#line 5474 "cs-parser.jay" +#line 5482 "cs-parser.jay" { yyVal = new Checked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 853: -#line 5481 "cs-parser.jay" +#line 5489 "cs-parser.jay" { yyVal = new Unchecked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } @@ -3627,7 +3627,7 @@ case 854: case_854(); break; case 855: -#line 5491 "cs-parser.jay" +#line 5499 "cs-parser.jay" { yyVal = new Unsafe ((Block) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); } @@ -3657,7 +3657,7 @@ case 863: case_863(); break; case 864: -#line 5574 "cs-parser.jay" +#line 5582 "cs-parser.jay" { report.Error (210, lexer.Location, "You must provide an initializer in a fixed or using statement declaration"); } @@ -3690,7 +3690,7 @@ case 873: case_873(); break; case 874: -#line 5674 "cs-parser.jay" +#line 5682 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); } @@ -3699,7 +3699,7 @@ case 875: case_875(); break; case 876: -#line 5689 "cs-parser.jay" +#line 5697 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); } @@ -3714,7 +3714,7 @@ case 880: case_880(); break; case 881: -#line 5734 "cs-parser.jay" +#line 5742 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); } @@ -3735,7 +3735,7 @@ case 889: case_889(); break; case 895: -#line 5793 "cs-parser.jay" +#line 5801 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); } @@ -3744,7 +3744,7 @@ case 896: case_896(); break; case 897: -#line 5812 "cs-parser.jay" +#line 5820 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); } @@ -3777,13 +3777,13 @@ case 906: case_906(); break; case 908: -#line 5956 "cs-parser.jay" +#line 5964 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; } break; case 909: -#line 5963 "cs-parser.jay" +#line 5971 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); } @@ -3804,7 +3804,7 @@ case 916: case_916(); break; case 917: -#line 6009 "cs-parser.jay" +#line 6017 "cs-parser.jay" { yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); } @@ -3816,7 +3816,7 @@ case 919: case_919(); break; case 920: -#line 6026 "cs-parser.jay" +#line 6034 "cs-parser.jay" { yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); } @@ -3840,13 +3840,13 @@ case 929: case_929(); break; case 937: -#line 6150 "cs-parser.jay" +#line 6158 "cs-parser.jay" { module.DocumentationBuilder.ParsedName = (MemberName) yyVals[0+yyTop]; } break; case 938: -#line 6157 "cs-parser.jay" +#line 6165 "cs-parser.jay" { module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; } @@ -3858,13 +3858,13 @@ case 940: case_940(); break; case 941: -#line 6174 "cs-parser.jay" +#line 6182 "cs-parser.jay" { yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], new MemberName (MemberCache.IndexerNameAlias)); } break; case 942: -#line 6178 "cs-parser.jay" +#line 6186 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } @@ -3882,25 +3882,25 @@ case 946: case_946(); break; case 948: -#line 6214 "cs-parser.jay" +#line 6222 "cs-parser.jay" { yyVal = new MemberName (((MemberName) yyVals[-2+yyTop]), (MemberName) yyVals[0+yyTop]); } break; case 950: -#line 6222 "cs-parser.jay" +#line 6230 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } break; case 951: -#line 6226 "cs-parser.jay" +#line 6234 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; } break; case 952: -#line 6233 "cs-parser.jay" +#line 6241 "cs-parser.jay" { yyVal = new List (0); } @@ -4223,12 +4223,13 @@ void case_62() { var attrs = (List) yyVals[-2+yyTop]; attrs.Add ((Attribute) yyVals[0+yyTop]); + lbag.AppendTo (attrs, GetLocation (yyVals[-1+yyTop])); yyVal = attrs; } void case_64() -#line 767 "cs-parser.jay" +#line 768 "cs-parser.jay" { --lexer.parsing_block; MemberName mname = (MemberName) yyVals[-2+yyTop]; @@ -4246,7 +4247,7 @@ void case_64() } void case_67() -#line 791 "cs-parser.jay" +#line 792 "cs-parser.jay" { savedAttrParenOpenLocation = GetLocation (yyVals[-2+yyTop]); savedAttrParenCloseLocation = GetLocation (yyVals[0+yyTop]); @@ -4254,7 +4255,7 @@ void case_67() } void case_69() -#line 802 "cs-parser.jay" +#line 803 "cs-parser.jay" { Arguments a = new Arguments (4); a.Add ((Argument) yyVals[0+yyTop]); @@ -4262,7 +4263,7 @@ void case_69() } void case_70() -#line 808 "cs-parser.jay" +#line 809 "cs-parser.jay" { Arguments a = new Arguments (4); a.Add ((Argument) yyVals[0+yyTop]); @@ -4270,7 +4271,7 @@ void case_70() } void case_71() -#line 814 "cs-parser.jay" +#line 815 "cs-parser.jay" { Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; if (o [1] != null) { @@ -4287,7 +4288,7 @@ void case_71() } void case_72() -#line 829 "cs-parser.jay" +#line 830 "cs-parser.jay" { Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; if (o [1] == null) { @@ -4299,7 +4300,7 @@ void case_72() } void case_76() -#line 854 "cs-parser.jay" +#line 855 "cs-parser.jay" { --lexer.parsing_block; var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; @@ -4308,7 +4309,7 @@ void case_76() } void case_77() -#line 864 "cs-parser.jay" +#line 865 "cs-parser.jay" { if (lang_version <= LanguageVersion.V_3) FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "named argument"); @@ -4321,7 +4322,7 @@ void case_77() } void case_95() -#line 911 "cs-parser.jay" +#line 912 "cs-parser.jay" { report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", GetSymbolName (yyToken)); @@ -4330,14 +4331,14 @@ void case_95() } void case_97() -#line 928 "cs-parser.jay" +#line 929 "cs-parser.jay" { MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); push_current_class (new Struct (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]), yyVals[-3+yyTop]); } void case_98() -#line 934 "cs-parser.jay" +#line 935 "cs-parser.jay" { lexer.ConstraintsParsing = false; @@ -4350,7 +4351,7 @@ void case_98() } void case_99() -#line 945 "cs-parser.jay" +#line 946 "cs-parser.jay" { --lexer.parsing_declaration; if (doc_support) @@ -4358,21 +4359,21 @@ void case_99() } void case_100() -#line 951 "cs-parser.jay" +#line 952 "cs-parser.jay" { lbag.AppendToMember (current_class, GetLocation (yyVals[0+yyTop])); yyVal = pop_current_class (); } void case_102() -#line 963 "cs-parser.jay" +#line 964 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } void case_118() -#line 1005 "cs-parser.jay" +#line 1006 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var mod = (Modifiers) yyVals[-3+yyTop]; @@ -4387,7 +4388,7 @@ void case_118() } void case_119() -#line 1018 "cs-parser.jay" +#line 1019 "cs-parser.jay" { if (doc_support) { current_field.DocComment = Lexer.consume_doc_comment (); @@ -4400,7 +4401,7 @@ void case_119() } void case_124() -#line 1048 "cs-parser.jay" +#line 1049 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) yyVals[0+yyTop]); @@ -4408,7 +4409,7 @@ void case_124() } void case_126() -#line 1061 "cs-parser.jay" +#line 1062 "cs-parser.jay" { --lexer.parsing_block; yyVal = new ConstInitializer (current_field, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); @@ -4416,14 +4417,14 @@ void case_126() } void case_127() -#line 1067 "cs-parser.jay" +#line 1068 "cs-parser.jay" { report.Error (145, lexer.Location, "A const field requires a value to be provided"); yyVal = null; } void case_130() -#line 1082 "cs-parser.jay" +#line 1083 "cs-parser.jay" { lexer.parsing_generic_declaration = false; @@ -4438,7 +4439,7 @@ void case_130() } void case_131() -#line 1097 "cs-parser.jay" +#line 1098 "cs-parser.jay" { if (doc_support) { current_field.DocComment = Lexer.consume_doc_comment (); @@ -4451,7 +4452,7 @@ void case_131() } void case_132() -#line 1110 "cs-parser.jay" +#line 1111 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "fixed size buffers"); @@ -4464,7 +4465,7 @@ void case_132() } void case_133() -#line 1121 "cs-parser.jay" +#line 1122 "cs-parser.jay" { if (doc_support) { current_field.DocComment = Lexer.consume_doc_comment (); @@ -4478,7 +4479,7 @@ void case_133() } void case_136() -#line 1144 "cs-parser.jay" +#line 1145 "cs-parser.jay" { ++lexer.parsing_block; current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; @@ -4486,7 +4487,7 @@ void case_136() } void case_137() -#line 1150 "cs-parser.jay" +#line 1151 "cs-parser.jay" { --lexer.parsing_block; current_field.Initializer = (Expression) yyVals[0+yyTop]; @@ -4496,7 +4497,7 @@ void case_137() } void case_142() -#line 1177 "cs-parser.jay" +#line 1178 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); @@ -4504,7 +4505,7 @@ void case_142() } void case_144() -#line 1187 "cs-parser.jay" +#line 1188 "cs-parser.jay" { --lexer.parsing_block; var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; @@ -4513,7 +4514,7 @@ void case_144() } void case_149() -#line 1213 "cs-parser.jay" +#line 1214 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), (ConstInitializer) yyVals[0+yyTop]); @@ -4521,7 +4522,7 @@ void case_149() } void case_151() -#line 1226 "cs-parser.jay" +#line 1227 "cs-parser.jay" { --lexer.parsing_block; yyVal = new ConstInitializer (current_field, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); @@ -4529,14 +4530,14 @@ void case_151() } void case_152() -#line 1232 "cs-parser.jay" +#line 1233 "cs-parser.jay" { report.Error (443, lexer.Location, "Value or constant expected"); yyVal = null; } void case_155() -#line 1242 "cs-parser.jay" +#line 1243 "cs-parser.jay" { /* It has to be here for the parent to safely restore artificial block*/ Error_SyntaxError (yyToken); @@ -4544,7 +4545,7 @@ void case_155() } void case_156() -#line 1251 "cs-parser.jay" +#line 1252 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.NotAllowed; @@ -4554,7 +4555,7 @@ void case_156() } void case_157() -#line 1259 "cs-parser.jay" +#line 1260 "cs-parser.jay" { Method method = (Method) yyVals[-2+yyTop]; method.Block = (ToplevelBlock) yyVals[0+yyTop]; @@ -4580,7 +4581,7 @@ void case_157() } void case_160() -#line 1297 "cs-parser.jay" +#line 1298 "cs-parser.jay" { lexer.ConstraintsParsing = false; valid_param_mod = 0; @@ -4615,14 +4616,14 @@ void case_160() } void case_162() -#line 1338 "cs-parser.jay" +#line 1339 "cs-parser.jay" { lexer.parsing_generic_declaration = false; valid_param_mod = ParameterModifierType.All; } void case_164() -#line 1347 "cs-parser.jay" +#line 1348 "cs-parser.jay" { lexer.ConstraintsParsing = false; valid_param_mod = 0; @@ -4674,7 +4675,7 @@ void case_164() } void case_165() -#line 1400 "cs-parser.jay" +#line 1401 "cs-parser.jay" { MemberName name = (MemberName) yyVals[-3+yyTop]; report.Error (1585, name.Location, @@ -4692,7 +4693,7 @@ void case_165() } void case_170() -#line 1429 "cs-parser.jay" +#line 1430 "cs-parser.jay" { var pars_list = (List) yyVals[0+yyTop]; yyVal = new ParametersCompiled (pars_list.ToArray ()); @@ -4700,7 +4701,7 @@ void case_170() } void case_171() -#line 1435 "cs-parser.jay" +#line 1436 "cs-parser.jay" { var pars_list = (List) yyVals[-2+yyTop]; pars_list.Add ((Parameter) yyVals[0+yyTop]); @@ -4709,7 +4710,7 @@ void case_171() } void case_172() -#line 1442 "cs-parser.jay" +#line 1443 "cs-parser.jay" { var pars_list = (List) yyVals[-2+yyTop]; pars_list.Add (new ArglistParameter (GetLocation (yyVals[0+yyTop]))); @@ -4717,7 +4718,7 @@ void case_172() } void case_173() -#line 1448 "cs-parser.jay" +#line 1449 "cs-parser.jay" { if (yyVals[-2+yyTop] != null) report.Error (231, ((Parameter) yyVals[-2+yyTop]).Location, "A params parameter must be the last parameter in a formal parameter list"); @@ -4726,7 +4727,7 @@ void case_173() } void case_174() -#line 1455 "cs-parser.jay" +#line 1456 "cs-parser.jay" { if (yyVals[-2+yyTop] != null) report.Error (231, ((Parameter) yyVals[-2+yyTop]).Location, "A params parameter must be the last parameter in a formal parameter list"); @@ -4738,7 +4739,7 @@ void case_174() } void case_175() -#line 1465 "cs-parser.jay" +#line 1466 "cs-parser.jay" { report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); @@ -4746,7 +4747,7 @@ void case_175() } void case_176() -#line 1471 "cs-parser.jay" +#line 1472 "cs-parser.jay" { report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); @@ -4757,14 +4758,14 @@ void case_176() } void case_179() -#line 1488 "cs-parser.jay" +#line 1489 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = ParametersCompiled.EmptyReadOnlyParameters; } void case_180() -#line 1496 "cs-parser.jay" +#line 1497 "cs-parser.jay" { parameters_bucket.Clear (); Parameter p = (Parameter) yyVals[0+yyTop]; @@ -4775,7 +4776,7 @@ void case_180() } void case_181() -#line 1505 "cs-parser.jay" +#line 1506 "cs-parser.jay" { var pars = (List) yyVals[-2+yyTop]; Parameter p = (Parameter) yyVals[0+yyTop]; @@ -4795,7 +4796,7 @@ void case_181() } void case_182() -#line 1529 "cs-parser.jay" +#line 1530 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Parameter.Modifier) yyVals[-2+yyTop], (Attributes) yyVals[-3+yyTop], lt.Location); @@ -4803,7 +4804,7 @@ void case_182() } void case_183() -#line 1538 "cs-parser.jay" +#line 1539 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); @@ -4812,7 +4813,7 @@ void case_183() } void case_184() -#line 1548 "cs-parser.jay" +#line 1549 "cs-parser.jay" { Error_SyntaxError (yyToken); Location l = GetLocation (yyVals[0+yyTop]); @@ -4821,7 +4822,7 @@ void case_184() } void case_186() -#line 1563 "cs-parser.jay" +#line 1564 "cs-parser.jay" { --lexer.parsing_block; if (lang_version <= LanguageVersion.V_3) { @@ -4860,14 +4861,14 @@ void case_186() } void case_189() -#line 1608 "cs-parser.jay" +#line 1609 "cs-parser.jay" { yyVal = yyVals[0+yyTop]; parameterModifierLocation = GetLocation (yyVals[0+yyTop]); } void case_190() -#line 1613 "cs-parser.jay" +#line 1614 "cs-parser.jay" { Parameter.Modifier p2 = (Parameter.Modifier)yyVals[0+yyTop]; Parameter.Modifier mod = (Parameter.Modifier)yyVals[-1+yyTop] | p2; @@ -4890,7 +4891,7 @@ void case_190() } void case_191() -#line 1637 "cs-parser.jay" +#line 1638 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.Ref) == 0) Error_ParameterModifierNotValid ("ref", GetLocation (yyVals[0+yyTop])); @@ -4899,7 +4900,7 @@ void case_191() } void case_192() -#line 1644 "cs-parser.jay" +#line 1645 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.Out) == 0) Error_ParameterModifierNotValid ("out", GetLocation (yyVals[0+yyTop])); @@ -4908,7 +4909,7 @@ void case_192() } void case_193() -#line 1651 "cs-parser.jay" +#line 1652 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.This) == 0) Error_ParameterModifierNotValid ("this", GetLocation (yyVals[0+yyTop])); @@ -4920,14 +4921,14 @@ void case_193() } void case_194() -#line 1664 "cs-parser.jay" +#line 1665 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new ParamsParameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Attributes) yyVals[-3+yyTop], lt.Location); } void case_195() -#line 1669 "cs-parser.jay" +#line 1670 "cs-parser.jay" { report.Error (1751, GetLocation (yyVals[-4+yyTop]), "Cannot specify a default value for a parameter array"); @@ -4936,21 +4937,21 @@ void case_195() } void case_196() -#line 1676 "cs-parser.jay" +#line 1677 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } void case_197() -#line 1684 "cs-parser.jay" +#line 1685 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.Params) == 0) report.Error (1670, (GetLocation (yyVals[0+yyTop])), "The `params' modifier is not allowed in current context"); } void case_198() -#line 1689 "cs-parser.jay" +#line 1690 "cs-parser.jay" { Parameter.Modifier mod = (Parameter.Modifier)yyVals[0+yyTop]; if ((mod & Parameter.Modifier.This) != 0) { @@ -4961,21 +4962,21 @@ void case_198() } void case_200() -#line 1705 "cs-parser.jay" +#line 1706 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.Arglist) == 0) report.Error (1669, GetLocation (yyVals[0+yyTop]), "__arglist is not valid in this context"); } void case_201() -#line 1716 "cs-parser.jay" +#line 1717 "cs-parser.jay" { if (doc_support) tmpComment = Lexer.consume_doc_comment (); } void case_202() -#line 1721 "cs-parser.jay" +#line 1722 "cs-parser.jay" { var type = (FullNamedExpression) yyVals[-3+yyTop]; current_property = new Property (current_class, type, (Modifiers) yyVals[-4+yyTop], @@ -4991,7 +4992,7 @@ void case_202() } void case_203() -#line 1735 "cs-parser.jay" +#line 1736 "cs-parser.jay" { lexer.PropertyParsing = false; @@ -5000,14 +5001,14 @@ void case_203() } void case_204() -#line 1742 "cs-parser.jay" +#line 1743 "cs-parser.jay" { lbag.AppendToMember (current_property, GetLocation (yyVals[0+yyTop])); current_property = null; } void case_206() -#line 1756 "cs-parser.jay" +#line 1757 "cs-parser.jay" { valid_param_mod = 0; var type = (FullNamedExpression) yyVals[-6+yyTop]; @@ -5034,7 +5035,7 @@ void case_206() } void case_208() -#line 1785 "cs-parser.jay" +#line 1786 "cs-parser.jay" { if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null) ((Indexer) current_property).ParameterInfo.CheckParameters (current_property); @@ -5047,7 +5048,7 @@ void case_208() } void case_213() -#line 1804 "cs-parser.jay" +#line 1805 "cs-parser.jay" { if (yyToken == Token.CLOSE_BRACE) { report.Error (548, lexer.Location, "`{0}': property or indexer must have at least one accessor", current_property.GetSignatureForError ()); @@ -5060,7 +5061,7 @@ void case_213() } void case_214() -#line 1818 "cs-parser.jay" +#line 1819 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); @@ -5084,7 +5085,7 @@ void case_214() } void case_215() -#line 1840 "cs-parser.jay" +#line 1841 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { current_property.Get.Block = (ToplevelBlock) yyVals[0+yyTop]; @@ -5104,7 +5105,7 @@ void case_215() } void case_216() -#line 1861 "cs-parser.jay" +#line 1862 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); @@ -5133,7 +5134,7 @@ void case_216() } void case_217() -#line 1888 "cs-parser.jay" +#line 1889 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { current_property.Set.Block = (ToplevelBlock) yyVals[0+yyTop]; @@ -5153,21 +5154,21 @@ void case_217() } void case_219() -#line 1910 "cs-parser.jay" +#line 1911 "cs-parser.jay" { lbag.AppendToMember (lbag.LastMember, GetLocation (yyVals[0+yyTop])); yyVal = null; } void case_220() -#line 1915 "cs-parser.jay" +#line 1916 "cs-parser.jay" { Error_SyntaxError (1043, yyToken, "Invalid accessor body"); yyVal = null; } void case_222() -#line 1930 "cs-parser.jay" +#line 1931 "cs-parser.jay" { MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); push_current_class (new Interface (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]), yyVals[-3+yyTop]); @@ -5175,7 +5176,7 @@ void case_222() } void case_223() -#line 1937 "cs-parser.jay" +#line 1938 "cs-parser.jay" { lexer.ConstraintsParsing = false; @@ -5188,7 +5189,7 @@ void case_223() } void case_224() -#line 1948 "cs-parser.jay" +#line 1949 "cs-parser.jay" { --lexer.parsing_declaration; if (doc_support) @@ -5196,14 +5197,14 @@ void case_224() } void case_225() -#line 1954 "cs-parser.jay" +#line 1955 "cs-parser.jay" { lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); yyVal = pop_current_class (); } void case_241() -#line 2006 "cs-parser.jay" +#line 2007 "cs-parser.jay" { OperatorDeclaration decl = (OperatorDeclaration) yyVals[-2+yyTop]; if (decl != null) { @@ -5230,14 +5231,14 @@ void case_241() } void case_245() -#line 2040 "cs-parser.jay" +#line 2041 "cs-parser.jay" { report.Error (590, GetLocation (yyVals[0+yyTop]), "User-defined operators cannot return void"); yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); } void case_247() -#line 2052 "cs-parser.jay" +#line 2053 "cs-parser.jay" { valid_param_mod = 0; @@ -5279,7 +5280,7 @@ void case_247() } void case_272() -#line 2128 "cs-parser.jay" +#line 2129 "cs-parser.jay" { valid_param_mod = 0; @@ -5296,7 +5297,7 @@ void case_272() } void case_274() -#line 2147 "cs-parser.jay" +#line 2148 "cs-parser.jay" { valid_param_mod = 0; @@ -5313,7 +5314,7 @@ void case_274() } void case_275() -#line 2162 "cs-parser.jay" +#line 2163 "cs-parser.jay" { Error_SyntaxError (yyToken); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; @@ -5321,7 +5322,7 @@ void case_275() } void case_276() -#line 2168 "cs-parser.jay" +#line 2169 "cs-parser.jay" { Error_SyntaxError (yyToken); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; @@ -5329,7 +5330,7 @@ void case_276() } void case_277() -#line 2178 "cs-parser.jay" +#line 2179 "cs-parser.jay" { Constructor c = (Constructor) yyVals[-1+yyTop]; c.Block = (ToplevelBlock) yyVals[0+yyTop]; @@ -5345,7 +5346,7 @@ void case_277() } void case_278() -#line 2197 "cs-parser.jay" +#line 2198 "cs-parser.jay" { if (doc_support) { tmpComment = Lexer.consume_doc_comment (); @@ -5356,7 +5357,7 @@ void case_278() } void case_279() -#line 2206 "cs-parser.jay" +#line 2207 "cs-parser.jay" { valid_param_mod = 0; current_local_parameters = (ParametersCompiled) yyVals[-1+yyTop]; @@ -5369,7 +5370,7 @@ void case_279() } void case_280() -#line 2217 "cs-parser.jay" +#line 2218 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-6+yyTop]; var mods = (Modifiers) yyVals[-7+yyTop]; @@ -5399,7 +5400,7 @@ void case_280() } void case_286() -#line 2262 "cs-parser.jay" +#line 2263 "cs-parser.jay" { --lexer.parsing_block; yyVal = new ConstructorBaseInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); @@ -5407,7 +5408,7 @@ void case_286() } void case_288() -#line 2272 "cs-parser.jay" +#line 2273 "cs-parser.jay" { --lexer.parsing_block; yyVal = new ConstructorThisInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); @@ -5415,14 +5416,14 @@ void case_288() } void case_289() -#line 2278 "cs-parser.jay" +#line 2279 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } void case_290() -#line 2286 "cs-parser.jay" +#line 2287 "cs-parser.jay" { if (doc_support) { tmpComment = Lexer.consume_doc_comment (); @@ -5433,7 +5434,7 @@ void case_290() } void case_291() -#line 2295 "cs-parser.jay" +#line 2296 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; if (lt.Value != current_container.MemberName.Name){ @@ -5455,7 +5456,7 @@ void case_291() } void case_292() -#line 2320 "cs-parser.jay" +#line 2321 "cs-parser.jay" { current_event_field = new EventField (current_class, (FullNamedExpression) yyVals[-1+yyTop], (Modifiers) yyVals[-3+yyTop], (MemberName) yyVals[0+yyTop], (Attributes) yyVals[-4+yyTop]); current_container.AddEvent (current_event_field); @@ -5469,7 +5470,7 @@ void case_292() } void case_293() -#line 2334 "cs-parser.jay" +#line 2335 "cs-parser.jay" { if (doc_support) { current_event_field.DocComment = Lexer.consume_doc_comment (); @@ -5481,7 +5482,7 @@ void case_293() } void case_294() -#line 2347 "cs-parser.jay" +#line 2348 "cs-parser.jay" { current_event = new EventProperty (current_class, (FullNamedExpression) yyVals[-2+yyTop], (Modifiers) yyVals[-4+yyTop], (MemberName) yyVals[-1+yyTop], (Attributes) yyVals[-5+yyTop]); current_container.AddEvent (current_event); @@ -5491,7 +5492,7 @@ void case_294() } void case_295() -#line 2355 "cs-parser.jay" +#line 2356 "cs-parser.jay" { if (current_container.Kind == MemberKind.Interface) report.Error (69, GetLocation (yyVals[-2+yyTop]), "Event in interface cannot have add or remove accessors"); @@ -5500,7 +5501,7 @@ void case_295() } void case_296() -#line 2362 "cs-parser.jay" +#line 2363 "cs-parser.jay" { if (doc_support) { current_event.DocComment = Lexer.consume_doc_comment (); @@ -5513,14 +5514,14 @@ void case_296() } void case_299() -#line 2381 "cs-parser.jay" +#line 2382 "cs-parser.jay" { --lexer.parsing_block; current_event_field.Initializer = (Expression) yyVals[0+yyTop]; } void case_304() -#line 2405 "cs-parser.jay" +#line 2406 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); @@ -5528,7 +5529,7 @@ void case_304() } void case_306() -#line 2415 "cs-parser.jay" +#line 2416 "cs-parser.jay" { --lexer.parsing_block; var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; @@ -5537,7 +5538,7 @@ void case_306() } void case_307() -#line 2424 "cs-parser.jay" +#line 2425 "cs-parser.jay" { if (current_container.Kind == MemberKind.Interface) { report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", @@ -5551,28 +5552,28 @@ void case_307() } void case_311() -#line 2445 "cs-parser.jay" +#line 2446 "cs-parser.jay" { report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", current_event.GetSignatureForError ()); } void case_312() -#line 2450 "cs-parser.jay" +#line 2451 "cs-parser.jay" { report.Error (65, lexer.Location, "`{0}': event property must have both add and remove accessors", current_event.GetSignatureForError ()); } void case_313() -#line 2455 "cs-parser.jay" +#line 2456 "cs-parser.jay" { report.Error (1055, GetLocation (yyVals[0+yyTop]), "An add or remove accessor expected"); yyVal = null; } void case_314() -#line 2463 "cs-parser.jay" +#line 2464 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone) { report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); @@ -5586,7 +5587,7 @@ void case_314() } void case_315() -#line 2475 "cs-parser.jay" +#line 2476 "cs-parser.jay" { lexer.EventParsing = true; @@ -5601,7 +5602,7 @@ void case_315() } void case_316() -#line 2491 "cs-parser.jay" +#line 2492 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone) { report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); @@ -5615,7 +5616,7 @@ void case_316() } void case_317() -#line 2503 "cs-parser.jay" +#line 2504 "cs-parser.jay" { lexer.EventParsing = true; @@ -5630,21 +5631,21 @@ void case_317() } void case_318() -#line 2519 "cs-parser.jay" +#line 2520 "cs-parser.jay" { report.Error (73, lexer.Location, "An add or remove accessor must have a body"); yyVal = null; } void case_320() -#line 2531 "cs-parser.jay" +#line 2532 "cs-parser.jay" { if (doc_support) enumTypeComment = Lexer.consume_doc_comment (); } void case_321() -#line 2536 "cs-parser.jay" +#line 2537 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; @@ -5658,7 +5659,7 @@ void case_321() } void case_322() -#line 2548 "cs-parser.jay" +#line 2549 "cs-parser.jay" { /* here will be evaluated after CLOSE_BLACE is consumed.*/ if (doc_support) @@ -5666,7 +5667,7 @@ void case_322() } void case_323() -#line 2554 "cs-parser.jay" +#line 2555 "cs-parser.jay" { if (doc_support) current_class.DocComment = enumTypeComment; @@ -5681,7 +5682,7 @@ void case_323() } void case_325() -#line 2571 "cs-parser.jay" +#line 2572 "cs-parser.jay" { var te = yyVals[0+yyTop] as TypeExpression; if (te == null || !EnumSpec.IsValidUnderlyingType (te.Type)) { @@ -5693,21 +5694,21 @@ void case_325() } void case_326() -#line 2581 "cs-parser.jay" +#line 2582 "cs-parser.jay" { Error_TypeExpected (GetLocation (yyVals[-1+yyTop])); yyVal = null; } void case_331() -#line 2599 "cs-parser.jay" +#line 2600 "cs-parser.jay" { lbag.AddLocation (yyVals[-2+yyTop], GetLocation (yyVals[-1+yyTop])); yyVal = yyVals[0+yyTop]; } void case_332() -#line 2607 "cs-parser.jay" +#line 2608 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var em = new EnumMember ((Enum) current_class, new MemberName (lt.Value, lt.Location), (Attributes) yyVals[-1+yyTop]); @@ -5722,7 +5723,7 @@ void case_332() } void case_333() -#line 2620 "cs-parser.jay" +#line 2621 "cs-parser.jay" { ++lexer.parsing_block; if (doc_support) { @@ -5732,7 +5733,7 @@ void case_333() } void case_334() -#line 2628 "cs-parser.jay" +#line 2629 "cs-parser.jay" { --lexer.parsing_block; @@ -5748,7 +5749,7 @@ void case_334() } void case_336() -#line 2653 "cs-parser.jay" +#line 2654 "cs-parser.jay" { valid_param_mod = 0; @@ -5768,7 +5769,7 @@ void case_336() } void case_338() -#line 2675 "cs-parser.jay" +#line 2676 "cs-parser.jay" { if (doc_support) { current_delegate.DocComment = Lexer.consume_doc_comment (); @@ -5784,7 +5785,7 @@ void case_338() } void case_340() -#line 2693 "cs-parser.jay" +#line 2694 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "nullable types"); @@ -5793,7 +5794,7 @@ void case_340() } void case_342() -#line 2704 "cs-parser.jay" +#line 2705 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -5802,7 +5803,7 @@ void case_342() } void case_344() -#line 2715 "cs-parser.jay" +#line 2716 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new MemberName ((MemberName) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); @@ -5810,14 +5811,14 @@ void case_344() } void case_345() -#line 2724 "cs-parser.jay" +#line 2725 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new MemberName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); } void case_347() -#line 2736 "cs-parser.jay" +#line 2737 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); @@ -5830,14 +5831,14 @@ void case_347() } void case_348() -#line 2747 "cs-parser.jay" +#line 2748 "cs-parser.jay" { Error_TypeExpected (lexer.Location); yyVal = new TypeArguments (); } void case_349() -#line 2755 "cs-parser.jay" +#line 2756 "cs-parser.jay" { TypeArguments type_args = new TypeArguments (); type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); @@ -5846,16 +5847,17 @@ void case_349() } void case_350() -#line 2762 "cs-parser.jay" +#line 2763 "cs-parser.jay" { TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); + lbag.AppendTo (type_args, GetLocation (yyVals[-1+yyTop])); yyVal = type_args; locationListStack.Peek ().Add (GetLocation (yyVals[-1+yyTop])); } void case_352() -#line 2779 "cs-parser.jay" +#line 2781 "cs-parser.jay" { lexer.parsing_generic_declaration = false; var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; @@ -5863,7 +5865,7 @@ void case_352() } void case_353() -#line 2788 "cs-parser.jay" +#line 2790 "cs-parser.jay" { MemberName mn = (MemberName)yyVals[0+yyTop]; if (mn.TypeArguments != null) @@ -5872,7 +5874,7 @@ void case_353() } void case_355() -#line 2799 "cs-parser.jay" +#line 2801 "cs-parser.jay" { lexer.parsing_generic_declaration = false; var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -5880,21 +5882,21 @@ void case_355() } void case_356() -#line 2808 "cs-parser.jay" +#line 2810 "cs-parser.jay" { lexer.parsing_generic_declaration = false; yyVal = new MemberName (TypeContainer.DefaultIndexerName, GetLocation (yyVals[0+yyTop])); } void case_357() -#line 2813 "cs-parser.jay" +#line 2815 "cs-parser.jay" { lexer.parsing_generic_declaration = false; yyVal = new MemberName ((MemberName) yyVals[-1+yyTop], TypeContainer.DefaultIndexerName, null, GetLocation (yyVals[-1+yyTop])); } void case_358() -#line 2821 "cs-parser.jay" +#line 2823 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new MemberName (lt.Value, (TypeArguments) yyVals[-1+yyTop], lt.Location); @@ -5902,7 +5904,7 @@ void case_358() } void case_359() -#line 2827 "cs-parser.jay" +#line 2829 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; @@ -5912,7 +5914,7 @@ void case_359() } void case_360() -#line 2835 "cs-parser.jay" +#line 2837 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new MemberName ((MemberName) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[-1+yyTop], lt.Location); @@ -5920,7 +5922,7 @@ void case_360() } void case_362() -#line 2845 "cs-parser.jay" +#line 2847 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); @@ -5930,7 +5932,7 @@ void case_362() } void case_363() -#line 2856 "cs-parser.jay" +#line 2858 "cs-parser.jay" { TypeArguments type_args = new TypeArguments (); type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); @@ -5938,7 +5940,7 @@ void case_363() } void case_364() -#line 2862 "cs-parser.jay" +#line 2864 "cs-parser.jay" { TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); @@ -5947,14 +5949,14 @@ void case_364() } void case_365() -#line 2872 "cs-parser.jay" +#line 2874 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken)yyVals[0+yyTop]; yyVal = new TypeParameterName (lt.Value, (Attributes)yyVals[-2+yyTop], (Variance) yyVals[-1+yyTop], lt.Location); } void case_366() -#line 2877 "cs-parser.jay" +#line 2879 "cs-parser.jay" { if (GetTokenName (yyToken) == "type") report.Error (81, GetLocation (yyVals[0+yyTop]), "Type parameter declaration must be an identifier not a type"); @@ -5965,28 +5967,28 @@ void case_366() } void case_371() -#line 2911 "cs-parser.jay" +#line 2913 "cs-parser.jay" { Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); } void case_373() -#line 2920 "cs-parser.jay" +#line 2922 "cs-parser.jay" { Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); } void case_375() -#line 2929 "cs-parser.jay" +#line 2931 "cs-parser.jay" { report.Error (1536, GetLocation (yyVals[0+yyTop]), "Invalid parameter type `void'"); yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); } void case_378() -#line 2945 "cs-parser.jay" +#line 2947 "cs-parser.jay" { MemberName name = (MemberName) yyVals[-1+yyTop]; @@ -6001,14 +6003,14 @@ void case_378() } void case_380() -#line 2962 "cs-parser.jay" +#line 2964 "cs-parser.jay" { if (yyVals[0+yyTop] != null) yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } void case_383() -#line 2978 "cs-parser.jay" +#line 2980 "cs-parser.jay" { var types = new List (2); types.Add ((FullNamedExpression) yyVals[0+yyTop]); @@ -6016,15 +6018,16 @@ void case_383() } void case_384() -#line 2984 "cs-parser.jay" +#line 2986 "cs-parser.jay" { var types = (List) yyVals[-2+yyTop]; types.Add ((FullNamedExpression) yyVals[0+yyTop]); + lbag.AppendTo (types, GetLocation (yyVals[-1+yyTop])); yyVal = types; } void case_385() -#line 2993 "cs-parser.jay" +#line 2996 "cs-parser.jay" { if (yyVals[0+yyTop] is ComposedCast) { report.Error (1521, GetLocation (yyVals[0+yyTop]), "Invalid base type `{0}'", ((ComposedCast)yyVals[0+yyTop]).GetSignatureForError ()); @@ -6033,35 +6036,35 @@ void case_385() } void case_386() -#line 3000 "cs-parser.jay" +#line 3003 "cs-parser.jay" { Error_TypeExpected (lexer.Location); yyVal = null; } void case_423() -#line 3062 "cs-parser.jay" +#line 3065 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new SimpleName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); } void case_424() -#line 3066 "cs-parser.jay" +#line 3069 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new CompletionSimpleName (MemberName.MakeName (lt.Value, null), lt.Location); } void case_435() -#line 3107 "cs-parser.jay" +#line 3110 "cs-parser.jay" { yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_437() -#line 3119 "cs-parser.jay" +#line 3122 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); @@ -6069,7 +6072,7 @@ void case_437() } void case_438() -#line 3125 "cs-parser.jay" +#line 3128 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); @@ -6077,7 +6080,7 @@ void case_438() } void case_439() -#line 3131 "cs-parser.jay" +#line 3134 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new MemberAccess (new BaseThis (GetLocation (yyVals[-3+yyTop])), lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); @@ -6085,7 +6088,7 @@ void case_439() } void case_440() -#line 3137 "cs-parser.jay" +#line 3140 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -6095,28 +6098,28 @@ void case_440() } void case_442() -#line 3147 "cs-parser.jay" +#line 3150 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new CompletionMemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, lt.Location); } void case_444() -#line 3155 "cs-parser.jay" +#line 3158 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new CompletionMemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, lt.Location); } void case_445() -#line 3163 "cs-parser.jay" +#line 3166 "cs-parser.jay" { yyVal = new Invocation ((Expression) yyVals[-3+yyTop], (Arguments) yyVals[-1+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_448() -#line 3176 "cs-parser.jay" +#line 3179 "cs-parser.jay" { if (yyVals[-1+yyTop] == null) { yyVal = CollectionOrObjectInitializers.Empty; @@ -6128,14 +6131,14 @@ void case_448() } void case_449() -#line 3186 "cs-parser.jay" +#line 3189 "cs-parser.jay" { yyVal = new CollectionOrObjectInitializers ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_452() -#line 3202 "cs-parser.jay" +#line 3205 "cs-parser.jay" { var a = new List (); a.Add ((Expression) yyVals[0+yyTop]); @@ -6143,22 +6146,23 @@ void case_452() } void case_453() -#line 3208 "cs-parser.jay" +#line 3211 "cs-parser.jay" { var a = (List)yyVals[-2+yyTop]; a.Add ((Expression) yyVals[0+yyTop]); + lbag.AppendTo (a, GetLocation (yyVals[-1+yyTop])); yyVal = a; } void case_454() -#line 3213 "cs-parser.jay" +#line 3217 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = yyVals[-1+yyTop]; } void case_455() -#line 3221 "cs-parser.jay" +#line 3225 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new ElementInitializer (lt.Value, (Expression)yyVals[0+yyTop], lt.Location); @@ -6166,7 +6170,7 @@ void case_455() } void case_457() -#line 3230 "cs-parser.jay" +#line 3234 "cs-parser.jay" { CompletionSimpleName csn = yyVals[-1+yyTop] as CompletionSimpleName; if (csn == null) @@ -6176,7 +6180,7 @@ void case_457() } void case_458() -#line 3238 "cs-parser.jay" +#line 3242 "cs-parser.jay" { if (yyVals[-1+yyTop] == null) yyVal = null; @@ -6185,14 +6189,14 @@ void case_458() } void case_459() -#line 3245 "cs-parser.jay" +#line 3249 "cs-parser.jay" { report.Error (1920, GetLocation (yyVals[-1+yyTop]), "An element initializer cannot be empty"); yyVal = null; } void case_464() -#line 3263 "cs-parser.jay" +#line 3267 "cs-parser.jay" { Arguments list = new Arguments (4); list.Add ((Argument) yyVals[0+yyTop]); @@ -6200,7 +6204,7 @@ void case_464() } void case_465() -#line 3269 "cs-parser.jay" +#line 3273 "cs-parser.jay" { Arguments list = (Arguments) yyVals[-2+yyTop]; if (list [list.Count - 1] is NamedArgument) @@ -6212,7 +6216,7 @@ void case_465() } void case_466() -#line 3279 "cs-parser.jay" +#line 3283 "cs-parser.jay" { Arguments list = (Arguments) yyVals[-2+yyTop]; NamedArgument a = (NamedArgument) yyVals[0+yyTop]; @@ -6229,56 +6233,56 @@ void case_466() } void case_467() -#line 3294 "cs-parser.jay" +#line 3298 "cs-parser.jay" { report.Error (839, GetLocation (yyVals[0+yyTop]), "An argument is missing"); yyVal = yyVals[-1+yyTop]; } void case_468() -#line 3299 "cs-parser.jay" +#line 3303 "cs-parser.jay" { report.Error (839, GetLocation (yyVals[-1+yyTop]), "An argument is missing"); yyVal = null; } void case_473() -#line 3320 "cs-parser.jay" +#line 3324 "cs-parser.jay" { yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Ref); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } void case_474() -#line 3325 "cs-parser.jay" +#line 3329 "cs-parser.jay" { yyVal = new Argument ((Expression) yyVals[0+yyTop], Argument.AType.Out); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } void case_475() -#line 3330 "cs-parser.jay" +#line 3334 "cs-parser.jay" { yyVal = new Argument (new Arglist ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop]))); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_476() -#line 3335 "cs-parser.jay" +#line 3339 "cs-parser.jay" { yyVal = new Argument (new Arglist (GetLocation (yyVals[-2+yyTop]))); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_478() -#line 3347 "cs-parser.jay" +#line 3351 "cs-parser.jay" { yyVal = new ElementAccess ((Expression) yyVals[-3+yyTop], (Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_479() -#line 3355 "cs-parser.jay" +#line 3359 "cs-parser.jay" { var list = new List (4); list.Add ((Expression) yyVals[0+yyTop]); @@ -6286,7 +6290,7 @@ void case_479() } void case_480() -#line 3361 "cs-parser.jay" +#line 3365 "cs-parser.jay" { var list = (List) yyVals[-2+yyTop]; list.Add ((Expression) yyVals[0+yyTop]); @@ -6295,14 +6299,14 @@ void case_480() } void case_481() -#line 3367 "cs-parser.jay" +#line 3371 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = yyVals[-1+yyTop]; } void case_482() -#line 3375 "cs-parser.jay" +#line 3379 "cs-parser.jay" { Arguments args = new Arguments (4); args.Add ((Argument) yyVals[0+yyTop]); @@ -6310,7 +6314,7 @@ void case_482() } void case_483() -#line 3381 "cs-parser.jay" +#line 3385 "cs-parser.jay" { Arguments args = (Arguments) yyVals[-2+yyTop]; if (args [args.Count - 1] is NamedArgument && !(yyVals[0+yyTop] is NamedArgument)) @@ -6322,21 +6326,21 @@ void case_483() } void case_487() -#line 3409 "cs-parser.jay" +#line 3413 "cs-parser.jay" { yyVal = new ElementAccess (new BaseThis (GetLocation (yyVals[-3+yyTop])), (Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_488() -#line 3414 "cs-parser.jay" +#line 3418 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new ElementAccess (null, null, GetLocation (yyVals[-1+yyTop])); } void case_491() -#line 3436 "cs-parser.jay" +#line 3440 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { if (lang_version <= LanguageVersion.ISO_2) @@ -6351,7 +6355,7 @@ void case_491() } void case_492() -#line 3449 "cs-parser.jay" +#line 3453 "cs-parser.jay" { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "collection initializers"); @@ -6360,7 +6364,7 @@ void case_492() } void case_493() -#line 3461 "cs-parser.jay" +#line 3465 "cs-parser.jay" { yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-5+yyTop], (List) yyVals[-3+yyTop], new ComposedTypeSpecifier (((List) yyVals[-3+yyTop]).Count, GetLocation (yyVals[-4+yyTop])) { @@ -6370,7 +6374,7 @@ void case_493() } void case_494() -#line 3469 "cs-parser.jay" +#line 3473 "cs-parser.jay" { if (yyVals[0+yyTop] == null) report.Error (1586, GetLocation (yyVals[-3+yyTop]), "Array creation must have array size or array initializer"); @@ -6379,7 +6383,7 @@ void case_494() } void case_495() -#line 3476 "cs-parser.jay" +#line 3480 "cs-parser.jay" { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "implicitly typed arrays"); @@ -6388,28 +6392,28 @@ void case_495() } void case_496() -#line 3483 "cs-parser.jay" +#line 3487 "cs-parser.jay" { report.Error (178, GetLocation (yyVals[-1+yyTop]), "Invalid rank specifier, expecting `,' or `]'"); yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-5+yyTop], null, GetLocation (yyVals[-6+yyTop])); } void case_497() -#line 3488 "cs-parser.jay" +#line 3492 "cs-parser.jay" { Error_SyntaxError (1526, yyToken, "Unexpected symbol"); yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-1+yyTop], null, GetLocation (yyVals[-2+yyTop])); } void case_499() -#line 3499 "cs-parser.jay" +#line 3503 "cs-parser.jay" { --lexer.parsing_type; yyVal = yyVals[0+yyTop]; } void case_500() -#line 3507 "cs-parser.jay" +#line 3511 "cs-parser.jay" { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "anonymous types"); @@ -6421,7 +6425,7 @@ void case_500() } void case_505() -#line 3530 "cs-parser.jay" +#line 3534 "cs-parser.jay" { var a = new List (4); a.Add ((AnonymousTypeParameter) yyVals[0+yyTop]); @@ -6429,15 +6433,17 @@ void case_505() } void case_506() -#line 3536 "cs-parser.jay" +#line 3540 "cs-parser.jay" { var a = (List) yyVals[-2+yyTop]; a.Add ((AnonymousTypeParameter) yyVals[0+yyTop]); + lbag.AppendTo (a, GetLocation (yyVals[-1+yyTop])); + yyVal = a; } void case_507() -#line 3545 "cs-parser.jay" +#line 3551 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken)yyVals[-2+yyTop]; yyVal = new AnonymousTypeParameter ((Expression)yyVals[0+yyTop], lt.Value, lt.Location); @@ -6445,7 +6451,7 @@ void case_507() } void case_508() -#line 3551 "cs-parser.jay" +#line 3557 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken)yyVals[0+yyTop]; yyVal = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), @@ -6453,14 +6459,14 @@ void case_508() } void case_509() -#line 3557 "cs-parser.jay" +#line 3563 "cs-parser.jay" { MemberAccess ma = (MemberAccess) yyVals[0+yyTop]; yyVal = new AnonymousTypeParameter (ma, ma.Name, ma.Location); } void case_510() -#line 3562 "cs-parser.jay" +#line 3568 "cs-parser.jay" { report.Error (746, lexer.Location, "Invalid anonymous type member declarator. Anonymous type members must be a member assignment, simple name or member access expression"); @@ -6468,28 +6474,28 @@ void case_510() } void case_514() -#line 3577 "cs-parser.jay" +#line 3583 "cs-parser.jay" { ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; yyVal = yyVals[-1+yyTop]; } void case_515() -#line 3585 "cs-parser.jay" +#line 3591 "cs-parser.jay" { yyVal = ComposedTypeSpecifier.CreateArrayDimension (1, GetLocation (yyVals[-1+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_516() -#line 3590 "cs-parser.jay" +#line 3596 "cs-parser.jay" { yyVal = ComposedTypeSpecifier.CreateArrayDimension ((int)yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_521() -#line 3620 "cs-parser.jay" +#line 3626 "cs-parser.jay" { var ai = new ArrayInitializer (0, GetLocation (yyVals[-1+yyTop])); ai.VariableDeclaration = current_variable; @@ -6498,7 +6504,7 @@ void case_521() } void case_522() -#line 3627 "cs-parser.jay" +#line 3633 "cs-parser.jay" { var ai = new ArrayInitializer ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); ai.VariableDeclaration = current_variable; @@ -6511,7 +6517,7 @@ void case_522() } void case_523() -#line 3641 "cs-parser.jay" +#line 3647 "cs-parser.jay" { var list = new List (4); list.Add ((Expression) yyVals[0+yyTop]); @@ -6519,7 +6525,7 @@ void case_523() } void case_524() -#line 3647 "cs-parser.jay" +#line 3653 "cs-parser.jay" { var list = (List) yyVals[-2+yyTop]; list.Add ((Expression) yyVals[0+yyTop]); @@ -6528,7 +6534,7 @@ void case_524() } void case_526() -#line 3661 "cs-parser.jay" +#line 3667 "cs-parser.jay" { lexer.TypeOfParsing = false; yyVal = new TypeOf ((FullNamedExpression) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); @@ -6536,14 +6542,14 @@ void case_526() } void case_529() -#line 3672 "cs-parser.jay" +#line 3678 "cs-parser.jay" { Error_TypeExpected (lexer.Location); yyVal = null; } void case_530() -#line 3680 "cs-parser.jay" +#line 3686 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -6551,7 +6557,7 @@ void case_530() } void case_531() -#line 3686 "cs-parser.jay" +#line 3692 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -6561,7 +6567,7 @@ void case_531() } void case_532() -#line 3694 "cs-parser.jay" +#line 3700 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; @@ -6569,7 +6575,7 @@ void case_532() } void case_533() -#line 3700 "cs-parser.jay" +#line 3706 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -6577,7 +6583,7 @@ void case_533() } void case_534() -#line 3706 "cs-parser.jay" +#line 3712 "cs-parser.jay" { var te = ((MemberName) yyVals[-3+yyTop]).GetTypeExpression (); if (te.HasTypeArguments) @@ -6588,7 +6594,7 @@ void case_534() } void case_535() -#line 3718 "cs-parser.jay" +#line 3724 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "generics"); @@ -6597,7 +6603,7 @@ void case_535() } void case_536() -#line 3728 "cs-parser.jay" +#line 3734 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; if (lang_version == LanguageVersion.ISO_1) @@ -6607,35 +6613,35 @@ void case_536() } void case_537() -#line 3739 "cs-parser.jay" +#line 3745 "cs-parser.jay" { yyVal = new SizeOf ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_538() -#line 3747 "cs-parser.jay" +#line 3753 "cs-parser.jay" { yyVal = new CheckedExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_539() -#line 3755 "cs-parser.jay" +#line 3761 "cs-parser.jay" { yyVal = new UnCheckedExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_540() -#line 3763 "cs-parser.jay" +#line 3769 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new MemberAccess (new Indirection ((Expression) yyVals[-3+yyTop], GetLocation (yyVals[-2+yyTop])), lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); } void case_542() -#line 3775 "cs-parser.jay" +#line 3781 "cs-parser.jay" { yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); if ((ParametersCompiled) yyVals[-2+yyTop] != ParametersCompiled.Undefined) { @@ -6646,7 +6652,7 @@ void case_542() } void case_548() -#line 3807 "cs-parser.jay" +#line 3813 "cs-parser.jay" { valid_param_mod = 0; yyVal = yyVals[-1+yyTop]; @@ -6655,7 +6661,7 @@ void case_548() } void case_549() -#line 3817 "cs-parser.jay" +#line 3823 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "default value expression"); @@ -6665,147 +6671,147 @@ void case_549() } void case_555() -#line 3842 "cs-parser.jay" +#line 3848 "cs-parser.jay" { yyVal = new Cast ((FullNamedExpression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } void case_556() -#line 3850 "cs-parser.jay" +#line 3856 "cs-parser.jay" { current_block.ParametersBlock.IsAsync = true; yyVal = new Await ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_565() -#line 3891 "cs-parser.jay" +#line 3897 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.Multiply, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_566() -#line 3896 "cs-parser.jay" +#line 3902 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.Division, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_567() -#line 3901 "cs-parser.jay" +#line 3907 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.Modulus, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_569() -#line 3910 "cs-parser.jay" +#line 3916 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.Addition, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_571() -#line 3919 "cs-parser.jay" +#line 3925 "cs-parser.jay" { /* Shift/Reduce conflict*/ yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_575() -#line 3936 "cs-parser.jay" +#line 3942 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.LeftShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_576() -#line 3941 "cs-parser.jay" +#line 3947 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.RightShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_578() -#line 3950 "cs-parser.jay" +#line 3956 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.LessThan, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_579() -#line 3955 "cs-parser.jay" +#line 3961 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.GreaterThan, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_580() -#line 3960 "cs-parser.jay" +#line 3966 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.LessThanOrEqual, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_581() -#line 3965 "cs-parser.jay" +#line 3971 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.GreaterThanOrEqual, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_583() -#line 3974 "cs-parser.jay" +#line 3980 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.Equality, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_584() -#line 3979 "cs-parser.jay" +#line 3985 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.Inequality, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_586() -#line 3988 "cs-parser.jay" +#line 3994 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.BitwiseAnd, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_588() -#line 3997 "cs-parser.jay" +#line 4003 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.ExclusiveOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_590() -#line 4006 "cs-parser.jay" +#line 4012 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.BitwiseOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_592() -#line 4015 "cs-parser.jay" +#line 4021 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.LogicalAnd, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_594() -#line 4024 "cs-parser.jay" +#line 4030 "cs-parser.jay" { yyVal = new Binary (Binary.Operator.LogicalOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_596() -#line 4033 "cs-parser.jay" +#line 4039 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "null coalescing operator"); @@ -6814,84 +6820,84 @@ void case_596() } void case_598() -#line 4044 "cs-parser.jay" +#line 4050 "cs-parser.jay" { yyVal = new Conditional (new BooleanExpression ((Expression) yyVals[-4+yyTop]), (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } void case_600() -#line 4056 "cs-parser.jay" +#line 4062 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.Multiply, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_601() -#line 4061 "cs-parser.jay" +#line 4067 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.Division, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_602() -#line 4066 "cs-parser.jay" +#line 4072 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.Modulus, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_603() -#line 4071 "cs-parser.jay" +#line 4077 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.Addition, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_604() -#line 4076 "cs-parser.jay" +#line 4082 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_605() -#line 4081 "cs-parser.jay" +#line 4087 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.LeftShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_606() -#line 4086 "cs-parser.jay" +#line 4092 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.RightShift, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_607() -#line 4091 "cs-parser.jay" +#line 4097 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.BitwiseAnd, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_608() -#line 4096 "cs-parser.jay" +#line 4102 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.BitwiseOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_609() -#line 4101 "cs-parser.jay" +#line 4107 "cs-parser.jay" { yyVal = new CompoundAssign ( Binary.Operator.ExclusiveOr, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } void case_610() -#line 4109 "cs-parser.jay" +#line 4115 "cs-parser.jay" { var pars = new List (4); pars.Add ((Parameter) yyVals[0+yyTop]); @@ -6900,7 +6906,7 @@ void case_610() } void case_611() -#line 4116 "cs-parser.jay" +#line 4122 "cs-parser.jay" { var pars = (List) yyVals[-2+yyTop]; Parameter p = (Parameter)yyVals[0+yyTop]; @@ -6909,11 +6915,13 @@ void case_611() } pars.Add (p); + lbag.AppendTo (pars, GetLocation (yyVals[-1+yyTop])); + yyVal = pars; } void case_612() -#line 4130 "cs-parser.jay" +#line 4138 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; @@ -6921,7 +6929,7 @@ void case_612() } void case_613() -#line 4136 "cs-parser.jay" +#line 4144 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; @@ -6929,21 +6937,21 @@ void case_613() } void case_614() -#line 4142 "cs-parser.jay" +#line 4150 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new ImplicitLambdaParameter (lt.Value, lt.Location); } void case_616() -#line 4150 "cs-parser.jay" +#line 4158 "cs-parser.jay" { var pars_list = (List) yyVals[0+yyTop]; yyVal = new ParametersCompiled (pars_list.ToArray ()); } void case_620() -#line 4166 "cs-parser.jay" +#line 4174 "cs-parser.jay" { Block b = end_block (lexer.Location); b.IsCompilerGenerated = true; @@ -6952,14 +6960,14 @@ void case_620() } void case_622() -#line 4177 "cs-parser.jay" +#line 4185 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = EmptyExpression.Null; } void case_623() -#line 4185 "cs-parser.jay" +#line 4193 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); @@ -6967,14 +6975,14 @@ void case_623() } void case_624() -#line 4191 "cs-parser.jay" +#line 4199 "cs-parser.jay" { yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); } void case_625() -#line 4196 "cs-parser.jay" +#line 4204 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); @@ -6982,63 +6990,63 @@ void case_625() } void case_626() -#line 4202 "cs-parser.jay" +#line 4210 "cs-parser.jay" { yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); } void case_628() -#line 4211 "cs-parser.jay" +#line 4219 "cs-parser.jay" { valid_param_mod = 0; start_anonymous (true, (ParametersCompiled) yyVals[-2+yyTop], false, GetLocation (yyVals[-4+yyTop])); } void case_629() -#line 4216 "cs-parser.jay" +#line 4224 "cs-parser.jay" { yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop])); } void case_631() -#line 4225 "cs-parser.jay" +#line 4233 "cs-parser.jay" { valid_param_mod = 0; start_anonymous (true, (ParametersCompiled) yyVals[-2+yyTop], true, GetLocation (yyVals[-5+yyTop])); } void case_632() -#line 4230 "cs-parser.jay" +#line 4238 "cs-parser.jay" { yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[-7+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-2+yyTop])); } void case_639() -#line 4253 "cs-parser.jay" +#line 4261 "cs-parser.jay" { yyVal = new RefValueExpr ((Expression) yyVals[-3+yyTop], (FullNamedExpression) yyVals[-1+yyTop], GetLocation (yyVals[-5+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_640() -#line 4258 "cs-parser.jay" +#line 4266 "cs-parser.jay" { yyVal = new RefTypeExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_641() -#line 4263 "cs-parser.jay" +#line 4271 "cs-parser.jay" { yyVal = new MakeRefExpr ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_645() -#line 4292 "cs-parser.jay" +#line 4300 "cs-parser.jay" { MemberName name = MakeName ((MemberName) yyVals[0+yyTop]); Class c = new Class (current_namespace, current_class, name, (Modifiers) yyVals[-4+yyTop], (Attributes) yyVals[-5+yyTop]); @@ -7050,7 +7058,7 @@ void case_645() } void case_646() -#line 4303 "cs-parser.jay" +#line 4311 "cs-parser.jay" { lexer.ConstraintsParsing = false; @@ -7064,7 +7072,7 @@ void case_646() } void case_647() -#line 4315 "cs-parser.jay" +#line 4323 "cs-parser.jay" { --lexer.parsing_declaration; if (doc_support) @@ -7072,21 +7080,21 @@ void case_647() } void case_648() -#line 4321 "cs-parser.jay" +#line 4329 "cs-parser.jay" { lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); yyVal = pop_current_class (); } void case_651() -#line 4336 "cs-parser.jay" +#line 4344 "cs-parser.jay" { mod_locations = null; yyVal = ModifierNone; } void case_654() -#line 4346 "cs-parser.jay" +#line 4354 "cs-parser.jay" { var m1 = (Modifiers) yyVals[-1+yyTop]; var m2 = (Modifiers) yyVals[0+yyTop]; @@ -7104,7 +7112,7 @@ void case_654() } void case_655() -#line 4365 "cs-parser.jay" +#line 4373 "cs-parser.jay" { yyVal = Modifiers.NEW; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); @@ -7114,91 +7122,91 @@ void case_655() } void case_656() -#line 4373 "cs-parser.jay" +#line 4381 "cs-parser.jay" { yyVal = Modifiers.PUBLIC; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_657() -#line 4378 "cs-parser.jay" +#line 4386 "cs-parser.jay" { yyVal = Modifiers.PROTECTED; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_658() -#line 4383 "cs-parser.jay" +#line 4391 "cs-parser.jay" { yyVal = Modifiers.INTERNAL; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_659() -#line 4388 "cs-parser.jay" +#line 4396 "cs-parser.jay" { yyVal = Modifiers.PRIVATE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_660() -#line 4393 "cs-parser.jay" +#line 4401 "cs-parser.jay" { yyVal = Modifiers.ABSTRACT; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_661() -#line 4398 "cs-parser.jay" +#line 4406 "cs-parser.jay" { yyVal = Modifiers.SEALED; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_662() -#line 4403 "cs-parser.jay" +#line 4411 "cs-parser.jay" { yyVal = Modifiers.STATIC; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_663() -#line 4408 "cs-parser.jay" +#line 4416 "cs-parser.jay" { yyVal = Modifiers.READONLY; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_664() -#line 4413 "cs-parser.jay" +#line 4421 "cs-parser.jay" { yyVal = Modifiers.VIRTUAL; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_665() -#line 4418 "cs-parser.jay" +#line 4426 "cs-parser.jay" { yyVal = Modifiers.OVERRIDE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_666() -#line 4423 "cs-parser.jay" +#line 4431 "cs-parser.jay" { yyVal = Modifiers.EXTERN; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_667() -#line 4428 "cs-parser.jay" +#line 4436 "cs-parser.jay" { yyVal = Modifiers.VOLATILE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_668() -#line 4433 "cs-parser.jay" +#line 4441 "cs-parser.jay" { yyVal = Modifiers.UNSAFE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); @@ -7207,21 +7215,21 @@ void case_668() } void case_669() -#line 4440 "cs-parser.jay" +#line 4448 "cs-parser.jay" { yyVal = Modifiers.ASYNC; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_674() -#line 4461 "cs-parser.jay" +#line 4469 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } void case_675() -#line 4469 "cs-parser.jay" +#line 4477 "cs-parser.jay" { var constraints = new List (1); constraints.Add ((Constraints) yyVals[0+yyTop]); @@ -7229,7 +7237,7 @@ void case_675() } void case_676() -#line 4475 "cs-parser.jay" +#line 4483 "cs-parser.jay" { var constraints = (List) yyVals[-1+yyTop]; Constraints new_constraint = (Constraints)yyVals[0+yyTop]; @@ -7247,14 +7255,14 @@ void case_676() } void case_677() -#line 4494 "cs-parser.jay" +#line 4502 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); } void case_678() -#line 4502 "cs-parser.jay" +#line 4510 "cs-parser.jay" { var constraints = new List (1); constraints.Add ((FullNamedExpression) yyVals[0+yyTop]); @@ -7262,7 +7270,7 @@ void case_678() } void case_679() -#line 4508 "cs-parser.jay" +#line 4516 "cs-parser.jay" { var constraints = (List) yyVals[-2+yyTop]; var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; @@ -7287,7 +7295,7 @@ void case_679() } void case_680() -#line 4534 "cs-parser.jay" +#line 4542 "cs-parser.jay" { if (yyVals[0+yyTop] is ComposedCast) report.Error (706, GetLocation (yyVals[0+yyTop]), "Invalid constraint type `{0}'", ((ComposedCast)yyVals[0+yyTop]).GetSignatureForError ()); @@ -7296,14 +7304,14 @@ void case_680() } void case_681() -#line 4541 "cs-parser.jay" +#line 4549 "cs-parser.jay" { yyVal = new SpecialContraintExpr (SpecialConstraint.Constructor, GetLocation (yyVals[-2+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_685() -#line 4561 "cs-parser.jay" +#line 4569 "cs-parser.jay" { if (lang_version <= LanguageVersion.V_3) FeatureIsNotAvailable (lexer.Location, "generic type variance"); @@ -7312,77 +7320,77 @@ void case_685() } void case_688() -#line 4595 "cs-parser.jay" +#line 4603 "cs-parser.jay" { ++lexer.parsing_block; start_block (GetLocation (yyVals[0+yyTop])); } void case_690() -#line 4607 "cs-parser.jay" +#line 4615 "cs-parser.jay" { --lexer.parsing_block; yyVal = end_block (GetLocation (yyVals[0+yyTop])); } void case_691() -#line 4612 "cs-parser.jay" +#line 4620 "cs-parser.jay" { --lexer.parsing_block; yyVal = end_block (lexer.Location); } void case_692() -#line 4621 "cs-parser.jay" +#line 4629 "cs-parser.jay" { ++lexer.parsing_block; current_block.StartLocation = GetLocation (yyVals[0+yyTop]); } void case_693() -#line 4626 "cs-parser.jay" +#line 4634 "cs-parser.jay" { --lexer.parsing_block; yyVal = end_block (GetLocation (yyVals[0+yyTop])); } void case_701() -#line 4653 "cs-parser.jay" +#line 4661 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } void case_734() -#line 4717 "cs-parser.jay" +#line 4725 "cs-parser.jay" { report.Error (1023, GetLocation (yyVals[0+yyTop]), "An embedded statement may not be a declaration or labeled statement"); yyVal = null; } void case_735() -#line 4722 "cs-parser.jay" +#line 4730 "cs-parser.jay" { report.Error (1023, GetLocation (yyVals[0+yyTop]), "An embedded statement may not be a declaration or labeled statement"); yyVal = null; } void case_736() -#line 4727 "cs-parser.jay" +#line 4735 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); } void case_737() -#line 4735 "cs-parser.jay" +#line 4743 "cs-parser.jay" { /* Uses lexer.Location because semicolon location is not kept in quick mode*/ yyVal = new EmptyStatement (lexer.Location); } void case_738() -#line 4743 "cs-parser.jay" +#line 4751 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); @@ -7392,7 +7400,7 @@ void case_738() } void case_741() -#line 4756 "cs-parser.jay" +#line 4764 "cs-parser.jay" { if (yyVals[-1+yyTop] is VarExpr) yyVals[-1+yyTop] = new SimpleName ("var", ((VarExpr) yyVals[-1+yyTop]).Location); @@ -7401,7 +7409,7 @@ void case_741() } void case_742() -#line 4772 "cs-parser.jay" +#line 4780 "cs-parser.jay" { /* Ok, the above "primary_expression" is there to get rid of*/ /* both reduce/reduce and shift/reduces in the grammar, it should*/ @@ -7433,7 +7441,7 @@ void case_742() } void case_743() -#line 4802 "cs-parser.jay" +#line 4810 "cs-parser.jay" { ATypeNameExpression expr = yyVals[-1+yyTop] as ATypeNameExpression; @@ -7446,7 +7454,7 @@ void case_743() } void case_744() -#line 4813 "cs-parser.jay" +#line 4821 "cs-parser.jay" { if (yyVals[0+yyTop] == null) yyVal = yyVals[-1+yyTop]; @@ -7455,21 +7463,21 @@ void case_744() } void case_747() -#line 4828 "cs-parser.jay" +#line 4836 "cs-parser.jay" { Expression.Error_VoidInvalidInTheContext (GetLocation (yyVals[0+yyTop]), report); yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); } void case_749() -#line 4837 "cs-parser.jay" +#line 4845 "cs-parser.jay" { ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; yyVal = yyVals[-1+yyTop]; } void case_751() -#line 4852 "cs-parser.jay" +#line 4860 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_block, lt.Value, lt.Location); @@ -7478,7 +7486,7 @@ void case_751() } void case_752() -#line 4859 "cs-parser.jay" +#line 4867 "cs-parser.jay" { yyVal = current_variable; current_variable = null; @@ -7486,7 +7494,7 @@ void case_752() } void case_753() -#line 4865 "cs-parser.jay" +#line 4873 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); @@ -7495,7 +7503,7 @@ void case_753() } void case_754() -#line 4872 "cs-parser.jay" +#line 4880 "cs-parser.jay" { if (current_variable.Initializer != null) { lbag.AddLocation (current_variable, GetLocation (yyVals[-6+yyTop]), savedLocation, GetLocation (yyVals[0+yyTop])); @@ -7507,14 +7515,14 @@ void case_754() } void case_756() -#line 4886 "cs-parser.jay" +#line 4894 "cs-parser.jay" { current_variable.Initializer = (Expression) yyVals[0+yyTop]; lbag.AppendTo (current_variable, GetLocation (yyVals[-1+yyTop])); } void case_757() -#line 4891 "cs-parser.jay" +#line 4899 "cs-parser.jay" { if (yyToken == Token.OPEN_BRACKET_EXPR) { report.Error (650, lexer.Location, @@ -7525,7 +7533,7 @@ void case_757() } void case_762() -#line 4913 "cs-parser.jay" +#line 4921 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); @@ -7536,7 +7544,7 @@ void case_762() } void case_763() -#line 4922 "cs-parser.jay" +#line 4930 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); @@ -7547,14 +7555,14 @@ void case_763() } void case_765() -#line 4938 "cs-parser.jay" +#line 4946 "cs-parser.jay" { savedLocation = GetLocation (yyVals[-1+yyTop]); current_variable.Initializer = (Expression) yyVals[0+yyTop]; } void case_770() -#line 4956 "cs-parser.jay" +#line 4964 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); @@ -7565,28 +7573,28 @@ void case_770() } void case_772() -#line 4969 "cs-parser.jay" +#line 4977 "cs-parser.jay" { yyVal = new StackAlloc ((Expression) yyVals[-3+yyTop], (Expression) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_773() -#line 4974 "cs-parser.jay" +#line 4982 "cs-parser.jay" { report.Error (1575, GetLocation (yyVals[-1+yyTop]), "A stackalloc expression requires [] after type"); yyVal = new StackAlloc ((Expression) yyVals[0+yyTop], null, GetLocation (yyVals[-1+yyTop])); } void case_774() -#line 4982 "cs-parser.jay" +#line 4990 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); } void case_778() -#line 5000 "cs-parser.jay" +#line 5008 "cs-parser.jay" { ExpressionStatement s = yyVals[0+yyTop] as ExpressionStatement; if (s == null) { @@ -7598,7 +7606,7 @@ void case_778() } void case_779() -#line 5013 "cs-parser.jay" +#line 5021 "cs-parser.jay" { Expression expr = (Expression) yyVals[0+yyTop]; ExpressionStatement s; @@ -7608,14 +7616,14 @@ void case_779() } void case_780() -#line 5021 "cs-parser.jay" +#line 5029 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); } void case_783() -#line 5035 "cs-parser.jay" +#line 5043 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7625,7 +7633,7 @@ void case_783() } void case_784() -#line 5044 "cs-parser.jay" +#line 5052 "cs-parser.jay" { yyVal = new If ((BooleanExpression) yyVals[-4+yyTop], (Statement) yyVals[-2+yyTop], (Statement) yyVals[0+yyTop], GetLocation (yyVals[-6+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); @@ -7637,7 +7645,7 @@ void case_784() } void case_786() -#line 5061 "cs-parser.jay" +#line 5069 "cs-parser.jay" { yyVal = new Switch ((Expression) yyVals[-5+yyTop], (ExplicitBlock) current_block.Explicit, (List) yyVals[-1+yyTop], GetLocation (yyVals[-7+yyTop])); end_block (GetLocation (yyVals[0+yyTop])); @@ -7645,14 +7653,14 @@ void case_786() } void case_787() -#line 5070 "cs-parser.jay" +#line 5078 "cs-parser.jay" { report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); yyVal = new List (); } void case_789() -#line 5079 "cs-parser.jay" +#line 5087 "cs-parser.jay" { var sections = new List (4); @@ -7661,7 +7669,7 @@ void case_789() } void case_790() -#line 5086 "cs-parser.jay" +#line 5094 "cs-parser.jay" { var sections = (List) yyVals[-1+yyTop]; @@ -7670,14 +7678,14 @@ void case_790() } void case_791() -#line 5093 "cs-parser.jay" +#line 5101 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new List (); } void case_794() -#line 5112 "cs-parser.jay" +#line 5120 "cs-parser.jay" { var labels = new List (2); @@ -7686,7 +7694,7 @@ void case_794() } void case_795() -#line 5119 "cs-parser.jay" +#line 5127 "cs-parser.jay" { var labels = (List) (yyVals[-1+yyTop]); labels.Add ((SwitchLabel) yyVals[0+yyTop]); @@ -7695,14 +7703,14 @@ void case_795() } void case_796() -#line 5129 "cs-parser.jay" +#line 5137 "cs-parser.jay" { yyVal = new SwitchLabel ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_802() -#line 5148 "cs-parser.jay" +#line 5156 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7712,21 +7720,21 @@ void case_802() } void case_803() -#line 5160 "cs-parser.jay" +#line 5168 "cs-parser.jay" { yyVal = new Do ((Statement) yyVals[-5+yyTop], (BooleanExpression) yyVals[-2+yyTop], GetLocation (yyVals[-6+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_804() -#line 5168 "cs-parser.jay" +#line 5176 "cs-parser.jay" { start_block (GetLocation (yyVals[0+yyTop])); current_block.IsCompilerGenerated = true; } void case_806() -#line 5184 "cs-parser.jay" +#line 5192 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7740,14 +7748,14 @@ void case_806() } void case_807() -#line 5196 "cs-parser.jay" +#line 5204 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = end_block (current_block.StartLocation); } void case_810() -#line 5209 "cs-parser.jay" +#line 5217 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_block, lt.Value, lt.Location); @@ -7756,14 +7764,14 @@ void case_810() } void case_811() -#line 5216 "cs-parser.jay" +#line 5224 "cs-parser.jay" { yyVal = current_variable; current_variable = null; } void case_819() -#line 5240 "cs-parser.jay" +#line 5248 "cs-parser.jay" { var sl = yyVals[-2+yyTop] as StatementList; if (sl == null) { @@ -7778,14 +7786,14 @@ void case_819() } void case_820() -#line 5256 "cs-parser.jay" +#line 5264 "cs-parser.jay" { report.Error (230, GetLocation (yyVals[-5+yyTop]), "Type and identifier are both required in a foreach statement"); yyVal = null; } void case_821() -#line 5261 "cs-parser.jay" +#line 5269 "cs-parser.jay" { start_block (GetLocation (yyVals[-5+yyTop])); current_block.IsCompilerGenerated = true; @@ -7796,7 +7804,7 @@ void case_821() } void case_822() -#line 5270 "cs-parser.jay" +#line 5278 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7809,21 +7817,21 @@ void case_822() } void case_829() -#line 5293 "cs-parser.jay" +#line 5301 "cs-parser.jay" { yyVal = new Break (GetLocation (yyVals[-1+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); } void case_830() -#line 5301 "cs-parser.jay" +#line 5309 "cs-parser.jay" { yyVal = new Continue (GetLocation (yyVals[-1+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); } void case_831() -#line 5309 "cs-parser.jay" +#line 5317 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new Goto (lt.Value, GetLocation (yyVals[-2+yyTop])); @@ -7831,35 +7839,35 @@ void case_831() } void case_832() -#line 5315 "cs-parser.jay" +#line 5323 "cs-parser.jay" { yyVal = new GotoCase ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_833() -#line 5320 "cs-parser.jay" +#line 5328 "cs-parser.jay" { yyVal = new GotoDefault (GetLocation (yyVals[-2+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_834() -#line 5328 "cs-parser.jay" +#line 5336 "cs-parser.jay" { yyVal = new Return ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); } void case_835() -#line 5336 "cs-parser.jay" +#line 5344 "cs-parser.jay" { yyVal = new Throw ((Expression) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); } void case_836() -#line 5344 "cs-parser.jay" +#line 5352 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; string s = lt.Value; @@ -7877,7 +7885,7 @@ void case_836() } void case_837() -#line 5360 "cs-parser.jay" +#line 5368 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; string s = lt.Value; @@ -7893,28 +7901,28 @@ void case_837() } void case_841() -#line 5386 "cs-parser.jay" +#line 5394 "cs-parser.jay" { yyVal = new TryFinally ((Statement) yyVals[-2+yyTop], (Block) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop])); } void case_842() -#line 5391 "cs-parser.jay" +#line 5399 "cs-parser.jay" { yyVal = new TryFinally (new TryCatch ((Block) yyVals[-3+yyTop], (List) yyVals[-2+yyTop], GetLocation (yyVals[-4+yyTop]), true), (Block) yyVals[0+yyTop], GetLocation (yyVals[-4+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop])); } void case_843() -#line 5396 "cs-parser.jay" +#line 5404 "cs-parser.jay" { report.Error (1524, GetLocation (yyVals[-2+yyTop]), "Expected catch or finally"); yyVal = null; } void case_844() -#line 5404 "cs-parser.jay" +#line 5412 "cs-parser.jay" { var l = new List (2); @@ -7923,7 +7931,7 @@ void case_844() } void case_845() -#line 5411 "cs-parser.jay" +#line 5419 "cs-parser.jay" { var l = (List) yyVals[-1+yyTop]; @@ -7941,7 +7949,7 @@ void case_845() } void case_849() -#line 5439 "cs-parser.jay" +#line 5447 "cs-parser.jay" { start_block (GetLocation (yyVals[-3+yyTop])); var c = new Catch (current_block, GetLocation (yyVals[-4+yyTop])); @@ -7958,7 +7966,7 @@ void case_849() } void case_851() -#line 5458 "cs-parser.jay" +#line 5466 "cs-parser.jay" { if (yyToken == Token.CLOSE_PARENS) { report.Error (1015, lexer.Location, @@ -7971,14 +7979,14 @@ void case_851() } void case_854() -#line 5486 "cs-parser.jay" +#line 5494 "cs-parser.jay" { if (!settings.Unsafe) Error_UnsafeCodeNotAllowed (GetLocation (yyVals[0+yyTop])); } void case_856() -#line 5496 "cs-parser.jay" +#line 5504 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7988,7 +7996,7 @@ void case_856() } void case_857() -#line 5507 "cs-parser.jay" +#line 5515 "cs-parser.jay" { start_block (GetLocation (yyVals[-2+yyTop])); @@ -8000,14 +8008,14 @@ void case_857() } void case_858() -#line 5517 "cs-parser.jay" +#line 5525 "cs-parser.jay" { yyVal = current_variable; current_variable = null; } void case_859() -#line 5522 "cs-parser.jay" +#line 5530 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -8019,7 +8027,7 @@ void case_859() } void case_860() -#line 5535 "cs-parser.jay" +#line 5543 "cs-parser.jay" { start_block (GetLocation (yyVals[-2+yyTop])); @@ -8031,14 +8039,14 @@ void case_860() } void case_861() -#line 5545 "cs-parser.jay" +#line 5553 "cs-parser.jay" { yyVal = current_variable; current_variable = null; } void case_862() -#line 5550 "cs-parser.jay" +#line 5558 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -8050,7 +8058,7 @@ void case_862() } void case_863() -#line 5560 "cs-parser.jay" +#line 5568 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -8061,14 +8069,14 @@ void case_863() } void case_865() -#line 5576 "cs-parser.jay" +#line 5584 "cs-parser.jay" { current_variable.Initializer = (Expression) yyVals[0+yyTop]; yyVal = current_variable; } void case_866() -#line 5587 "cs-parser.jay" +#line 5595 "cs-parser.jay" { lexer.query_parsing = false; @@ -8082,7 +8090,7 @@ void case_866() } void case_867() -#line 5599 "cs-parser.jay" +#line 5607 "cs-parser.jay" { Linq.AQueryClause from = yyVals[-1+yyTop] as Linq.AQueryClause; @@ -8094,7 +8102,7 @@ void case_867() } void case_868() -#line 5610 "cs-parser.jay" +#line 5618 "cs-parser.jay" { lexer.query_parsing = false; yyVal = yyVals[-1+yyTop]; @@ -8104,7 +8112,7 @@ void case_868() } void case_869() -#line 5617 "cs-parser.jay" +#line 5625 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; current_block.SetEndLocation (lexer.Location); @@ -8112,7 +8120,7 @@ void case_869() } void case_870() -#line 5626 "cs-parser.jay" +#line 5634 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8122,7 +8130,7 @@ void case_870() } void case_871() -#line 5634 "cs-parser.jay" +#line 5642 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8136,7 +8144,7 @@ void case_871() } void case_872() -#line 5649 "cs-parser.jay" +#line 5657 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8146,7 +8154,7 @@ void case_872() } void case_873() -#line 5657 "cs-parser.jay" +#line 5665 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8160,7 +8168,7 @@ void case_873() } void case_875() -#line 5676 "cs-parser.jay" +#line 5684 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var sn = new Linq.RangeVariable (lt.Value, lt.Location); @@ -8173,7 +8181,7 @@ void case_875() } void case_877() -#line 5691 "cs-parser.jay" +#line 5699 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var sn = new Linq.RangeVariable (lt.Value, lt.Location); @@ -8189,7 +8197,7 @@ void case_877() } void case_878() -#line 5708 "cs-parser.jay" +#line 5716 "cs-parser.jay" { Linq.AQueryClause head = (Linq.AQueryClause)yyVals[-1+yyTop]; @@ -8206,14 +8214,14 @@ void case_878() } void case_880() -#line 5724 "cs-parser.jay" +#line 5732 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } void case_882() -#line 5736 "cs-parser.jay" +#line 5744 "cs-parser.jay" { yyVal = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); @@ -8222,7 +8230,7 @@ void case_882() } void case_883() -#line 5743 "cs-parser.jay" +#line 5751 "cs-parser.jay" { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); @@ -8232,7 +8240,7 @@ void case_883() } void case_884() -#line 5751 "cs-parser.jay" +#line 5759 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8241,7 +8249,7 @@ void case_884() } void case_885() -#line 5758 "cs-parser.jay" +#line 5766 "cs-parser.jay" { yyVal = new Linq.GroupBy ((Linq.QueryBlock)current_block, (Expression)yyVals[-3+yyTop], linq_clause_blocks.Pop (), (Expression)yyVals[0+yyTop], GetLocation (yyVals[-5+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); @@ -8251,14 +8259,14 @@ void case_885() } void case_889() -#line 5775 "cs-parser.jay" +#line 5783 "cs-parser.jay" { ((Linq.AQueryClause)yyVals[-1+yyTop]).Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; yyVal = yyVals[-1+yyTop]; } void case_896() -#line 5795 "cs-parser.jay" +#line 5803 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var sn = new Linq.RangeVariable (lt.Value, lt.Location); @@ -8272,7 +8280,7 @@ void case_896() } void case_898() -#line 5814 "cs-parser.jay" +#line 5822 "cs-parser.jay" { yyVal = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); @@ -8281,7 +8289,7 @@ void case_898() } void case_899() -#line 5824 "cs-parser.jay" +#line 5832 "cs-parser.jay" { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); @@ -8291,7 +8299,7 @@ void case_899() } void case_900() -#line 5832 "cs-parser.jay" +#line 5840 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8301,7 +8309,7 @@ void case_900() } void case_901() -#line 5840 "cs-parser.jay" +#line 5848 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8311,7 +8319,7 @@ void case_901() } void case_902() -#line 5848 "cs-parser.jay" +#line 5856 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8351,7 +8359,7 @@ void case_902() } void case_903() -#line 5886 "cs-parser.jay" +#line 5894 "cs-parser.jay" { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); @@ -8361,7 +8369,7 @@ void case_903() } void case_904() -#line 5894 "cs-parser.jay" +#line 5902 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8371,7 +8379,7 @@ void case_904() } void case_905() -#line 5902 "cs-parser.jay" +#line 5910 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8381,7 +8389,7 @@ void case_905() } void case_906() -#line 5910 "cs-parser.jay" +#line 5918 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8423,7 +8431,7 @@ void case_906() } void case_910() -#line 5965 "cs-parser.jay" +#line 5973 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8432,7 +8440,7 @@ void case_910() } void case_912() -#line 5976 "cs-parser.jay" +#line 5984 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8441,14 +8449,14 @@ void case_912() } void case_913() -#line 5983 "cs-parser.jay" +#line 5991 "cs-parser.jay" { ((Linq.AQueryClause)yyVals[-3+yyTop]).Next = (Linq.AQueryClause)yyVals[0+yyTop]; yyVal = yyVals[-3+yyTop]; } void case_915() -#line 5992 "cs-parser.jay" +#line 6000 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8457,42 +8465,42 @@ void case_915() } void case_916() -#line 5999 "cs-parser.jay" +#line 6007 "cs-parser.jay" { ((Linq.AQueryClause)yyVals[-3+yyTop]).Tail.Next = (Linq.AQueryClause)yyVals[0+yyTop]; yyVal = yyVals[-3+yyTop]; } void case_918() -#line 6011 "cs-parser.jay" +#line 6019 "cs-parser.jay" { yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_919() -#line 6016 "cs-parser.jay" +#line 6024 "cs-parser.jay" { yyVal = new Linq.OrderByDescending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_921() -#line 6028 "cs-parser.jay" +#line 6036 "cs-parser.jay" { yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_922() -#line 6033 "cs-parser.jay" +#line 6041 "cs-parser.jay" { yyVal = new Linq.ThenByDescending ((Linq.QueryBlock) current_block, (Expression)yyVals[-1+yyTop]); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } void case_924() -#line 6043 "cs-parser.jay" +#line 6051 "cs-parser.jay" { /* query continuation block is not linked with query block but with block*/ /* before. This means each query can use same range variable names for*/ @@ -8510,7 +8518,7 @@ void case_924() } void case_925() -#line 6059 "cs-parser.jay" +#line 6067 "cs-parser.jay" { var current_block = linq_clause_blocks.Pop (); var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; @@ -8521,7 +8529,7 @@ void case_925() } void case_928() -#line 6086 "cs-parser.jay" +#line 6094 "cs-parser.jay" { current_container = new Class (current_namespace, current_class, new MemberName (""), Modifiers.PUBLIC, null); current_class = current_container; @@ -8553,7 +8561,7 @@ void case_928() } void case_929() -#line 6116 "cs-parser.jay" +#line 6124 "cs-parser.jay" { --lexer.parsing_block; Method method = (Method) oob_stack.Pop (); @@ -8565,7 +8573,7 @@ void case_929() } void case_939() -#line 6159 "cs-parser.jay" +#line 6167 "cs-parser.jay" { module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-1+yyTop]; module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; @@ -8573,7 +8581,7 @@ void case_939() } void case_940() -#line 6165 "cs-parser.jay" +#line 6173 "cs-parser.jay" { module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-3+yyTop]; module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; @@ -8582,14 +8590,14 @@ void case_940() } void case_943() -#line 6180 "cs-parser.jay" +#line 6188 "cs-parser.jay" { module.DocumentationBuilder.ParsedParameters = (List)yyVals[-1+yyTop]; yyVal = new MemberName ((MemberName) yyVals[-6+yyTop], new MemberName (MemberCache.IndexerNameAlias)); } void case_944() -#line 6185 "cs-parser.jay" +#line 6193 "cs-parser.jay" { var p = (List)yyVals[0+yyTop] ?? new List (1); p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); @@ -8599,7 +8607,7 @@ void case_944() } void case_945() -#line 6193 "cs-parser.jay" +#line 6201 "cs-parser.jay" { var p = (List)yyVals[0+yyTop] ?? new List (1); p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); @@ -8609,7 +8617,7 @@ void case_945() } void case_946() -#line 6201 "cs-parser.jay" +#line 6209 "cs-parser.jay" { var p = (List)yyVals[0+yyTop] ?? new List (1); module.DocumentationBuilder.ParsedParameters = p; @@ -8618,7 +8626,7 @@ void case_946() } void case_954() -#line 6239 "cs-parser.jay" +#line 6247 "cs-parser.jay" { var parameters = new List (); parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); @@ -8626,7 +8634,7 @@ void case_954() } void case_955() -#line 6245 "cs-parser.jay" +#line 6253 "cs-parser.jay" { var parameters = yyVals[-2+yyTop] as List; parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); @@ -8634,7 +8642,7 @@ void case_955() } void case_956() -#line 6254 "cs-parser.jay" +#line 6262 "cs-parser.jay" { if (yyVals[-1+yyTop] != null) yyVal = new DocumentationParameter ((Parameter.Modifier) yyVals[-1+yyTop], (FullNamedExpression) yyVals[0+yyTop]); @@ -11970,7 +11978,7 @@ void case_956() -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, }; -#line 6263 "cs-parser.jay" +#line 6271 "cs-parser.jay" // // A class used to hold info about an operator declarator diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay index 5e6f9e9095..94d77c5963 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay @@ -753,6 +753,7 @@ attribute_list { var attrs = (List) $1; attrs.Add ((Attribute) $3); + lbag.AppendTo (attrs, GetLocation ($2)); $$ = attrs; } @@ -2762,6 +2763,7 @@ type_arguments { TypeArguments type_args = (TypeArguments) $1; type_args.Add ((FullNamedExpression) $3); + lbag.AppendTo (type_args, GetLocation ($2)); $$ = type_args; locationListStack.Peek ().Add (GetLocation ($2)); } @@ -2984,6 +2986,7 @@ type_list { var types = (List) $1; types.Add ((FullNamedExpression) $3); + lbag.AppendTo (types, GetLocation ($2)); $$ = types; } ; @@ -3208,6 +3211,7 @@ member_initializer_list { var a = (List)$1; a.Add ((Expression) $3); + lbag.AppendTo (a, GetLocation ($2)); $$ = a; } | member_initializer_list error { @@ -3536,6 +3540,8 @@ anonymous_type_parameters { var a = (List) $1; a.Add ((AnonymousTypeParameter) $3); + lbag.AppendTo (a, GetLocation ($2)); + $$ = a; } ; @@ -4121,6 +4127,8 @@ lambda_parameter_list } pars.Add (p); + lbag.AppendTo (pars, GetLocation ($2)); + $$ = pars; } ; diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs b/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs index 24e1c343f9..d27f6f88f2 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs @@ -8855,7 +8855,7 @@ namespace Mono.CSharp public override void EmitSideEffect (EmitContext ec) { } - + public override object Accept (StructuralVisitor visitor) { return visitor.Visit (this); @@ -9527,6 +9527,12 @@ namespace Mono.CSharp } } + public IList Initializers { + get { + return initializers; + } + } + protected override void CloneTo (CloneContext clonectx, Expression target) { CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target; @@ -9681,6 +9687,12 @@ namespace Mono.CSharp CollectionOrObjectInitializers initializers; IMemoryLocation instance; + public CollectionOrObjectInitializers Initializers { + get { + return initializers; + } + } + public NewInitialize (FullNamedExpression requested_type, Arguments arguments, CollectionOrObjectInitializers initializers, Location l) : base (requested_type, arguments, l) { From 3763397da8b50c5e9b20bb6ce6b2c350b8a1ee1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 15 Aug 2011 11:54:37 +0200 Subject: [PATCH 02/15] Introduced namedexpression/namedexpressionlist to handle the collection initializers better. --- .../CSharp/Ast/DepthFirstAstVisitor.cs | 10 +++ .../CSharp/Ast/Expressions/NamedExpression.cs | 86 +++++++++++++++++++ .../Ast/Expressions/NamedExpressionList.cs | 86 +++++++++++++++++++ .../CSharp/Ast/IAstVisitor.cs | 2 + .../CSharp/Ast/ObservableAstVisitor.cs | 20 +++++ .../CSharp/OutputVisitor/OutputVisitor.cs | 23 +++++ .../CSharp/Parser/CSharpParser.cs | 81 +++++++++++------ .../CSharp/Parser/mcs/cs-parser.cs | 4 +- .../CSharp/Parser/mcs/cs-parser.jay | 4 +- .../ICSharpCode.NRefactory.csproj | 13 ++- 10 files changed, 293 insertions(+), 36 deletions(-) create mode 100644 ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpression.cs create mode 100644 ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs diff --git a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs index ee0a2180f5..347f90b820 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs @@ -585,6 +585,16 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (namedArgumentExpression, data); } + public virtual S VisitNamedExpression (NamedExpression namedExpression, T data) + { + return VisitChildren (namedExpression, data); + } + + public virtual S VisitNamedExpressionList (NamedExpressionList namedExpressionList, T data) + { + return VisitChildren (namedExpressionList, data); + } + public virtual S VisitEmptyExpression (EmptyExpression emptyExpression, T data) { return VisitChildren (emptyExpression, data); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpression.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpression.cs new file mode 100644 index 0000000000..c0b78ce042 --- /dev/null +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpression.cs @@ -0,0 +1,86 @@ +// +// NamedExpression.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// name = expression + /// This isn't the same as 'assign' even if it has the same syntax. This expression is used in object initializers. + /// + public class NamedExpression : Expression + { + public NamedExpression() + { + } + + public NamedExpression (string identifier, Expression expression) + { + this.Identifier = identifier; + this.Expression = expression; + } + + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier IdentifierToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); + } + } + + public CSharpTokenNode AssignToken { + get { return GetChildByRole (Roles.Assign); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitNamedExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as NamedExpression; + return o != null && MatchString(this.Identifier, o.Identifier) && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs new file mode 100644 index 0000000000..95b5ec1d63 --- /dev/null +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs @@ -0,0 +1,86 @@ +// +// NamedExpressionList.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// name = { expression1, ... , expressionN } + /// + public class NamedExpressionList : Expression + { + public NamedExpressionList() + { + } + + public string Identifier { + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + } + } + + public Identifier IdentifierToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); + } + } + + public CSharpTokenNode AssignToken { + get { return GetChildByRole (Roles.Assign); } + } + + public CSharpTokenNode LBraceToken { + get { return GetChildByRole (Roles.LBrace); } + } + + public AstNodeCollection Expressions { + get { return GetChildrenByRole (Roles.Expression); } + } + + public CSharpTokenNode RBraceToken { + get { return GetChildByRole (Roles.RBrace); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitNamedExpressionList(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as NamedExpressionList; + return o != null && MatchString(this.Identifier, o.Identifier) && this.Expressions.DoMatch(o.Expressions, match); + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs index 0a0c944f88..b24358fba8 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs @@ -45,6 +45,8 @@ namespace ICSharpCode.NRefactory.CSharp S VisitLambdaExpression(LambdaExpression lambdaExpression, T data); S VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, T data); S VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, T data); + S VisitNamedExpression(NamedExpression namedExpression, T data); + S VisitNamedExpressionList(NamedExpressionList namedExpressionList, T data); S VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, T data); S VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, T data); S VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs index 253f6ef3c3..26253be52e 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs @@ -1121,6 +1121,26 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (namedArgumentExpression, data); } + public event Action NamedExpressionVisited; + + S IAstVisitor.VisitNamedExpression (NamedExpression namedExpression, T data) + { + var handler = NamedExpressionVisited; + if (handler != null) + handler (namedExpression, data); + return VisitChildren (namedExpression, data); + } + + public event Action NamedExpressionListVisited; + + S IAstVisitor.VisitNamedExpressionList (NamedExpressionList namedExpressionList, T data) + { + var handler = NamedExpressionListVisited; + if (handler != null) + handler (namedExpressionList, data); + return VisitChildren (namedExpressionList, data); + } + public event Action EmptyExpressionVisited; S IAstVisitor.VisitEmptyExpression (EmptyExpression emptyExpression, T data) diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index 07387700ef..ede6d17974 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -575,6 +575,7 @@ namespace ICSharpCode.NRefactory.CSharp OpenBrace(style); bool isFirst = true; foreach (AstNode node in elements) { + Console.WriteLine ("expr:"+node.GetType ()); if (isFirst) { isFirst = false; } else { @@ -830,6 +831,28 @@ namespace ICSharpCode.NRefactory.CSharp return EndNode (namedArgumentExpression); } + public object VisitNamedExpression (NamedExpression namedExpression, object data) + { + StartNode (namedExpression); + WriteIdentifier (namedExpression.Identifier); + Space(); + WriteToken("=", NamedArgumentExpression.Roles.Assign); + Space (); + namedExpression.Expression.AcceptVisitor (this, data); + return EndNode (namedExpression); + } + + public object VisitNamedExpressionList (NamedExpressionList namedExpressionList, object data) + { + StartNode (namedExpressionList); + WriteIdentifier (namedExpressionList.Identifier); + Space(); + WriteToken("=", NamedArgumentExpression.Roles.Assign); + Space (); + PrintInitializerElements(namedExpressionList.Expressions); + return EndNode (namedExpressionList); + } + public object VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, object data) { StartNode (nullReferenceExpression); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index 48be73e35c..6974cc2467 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -2328,6 +2328,60 @@ namespace ICSharpCode.NRefactory.CSharp return result; } + ArrayInitializerExpression ConvertCollectionOrObjectInitializers (CollectionOrObjectInitializers minit) + { + if (minit == null) + return null; + var init = new ArrayInitializerExpression (); + AddConvertCollectionOrObjectInitializers (init, minit); + return init; + } + + void AddConvertCollectionOrObjectInitializers (AstNode init, CollectionOrObjectInitializers minit) + { + var initLoc = LocationsBag.GetLocations (minit); + var commaLoc = LocationsBag.GetLocations (minit.Initializers); + int curComma = commaLoc != null ? commaLoc.Count - 1 : -1; + foreach (var expr in minit.Initializers) { + var collectionInit = expr as CollectionElementInitializer; + if (collectionInit != null) { + for (int i = 0; i < collectionInit.Arguments.Count; i++) { + var arg = collectionInit.Arguments[i] as CollectionElementInitializer.ElementInitializerArgument; + if (arg == null) + continue; + init.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); + if (curComma >= 0) + init.AddChild (new CSharpTokenNode (Convert (commaLoc[curComma--]), 1), ArrayInitializerExpression.Roles.Comma); + } + continue; + } + + var eleInit = expr as ElementInitializer; + if (eleInit != null) { + var nexpr = eleInit.Source is CollectionOrObjectInitializers ? (ICSharpCode.NRefactory.CSharp.Expression)new NamedExpressionList () : new NamedExpression (); + nexpr.AddChild (Identifier.Create (eleInit.Name, Convert(eleInit.Location)), NamedArgumentExpression.Roles.Identifier); + var assignLoc = LocationsBag.GetLocations (eleInit); + if (assignLoc != null) + nexpr.AddChild (new CSharpTokenNode (Convert (assignLoc[0]), 1), NamedArgumentExpression.Roles.Assign); + if (eleInit.Source != null) { + if (eleInit.Source is CollectionOrObjectInitializers) { + AddConvertCollectionOrObjectInitializers (nexpr, eleInit.Source as CollectionOrObjectInitializers); + } else { + nexpr.AddChild ((Expression)eleInit.Source.Accept (this), NamedArgumentExpression.Roles.Expression); + } + } + + init.AddChild (nexpr, ArrayInitializerExpression.Roles.Expression); + } + + } + if (initLoc != null) { + if (initLoc.Count == 3) // optional comma + init.AddChild (new CSharpTokenNode (Convert (initLoc[1]), 1), ArrayInitializerExpression.Roles.Comma); + init.AddChild (new CSharpTokenNode (Convert (initLoc[initLoc.Count - 1]), 1), ArrayInitializerExpression.Roles.RBrace); + } + } + public override object Visit (NewInitialize newInitializeExpression) { @@ -2344,32 +2398,9 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ObjectCreateExpression.Roles.RPar); - var minit = newInitializeExpression.Initializers; - if (minit != null){ - var init = new ArrayInitializerExpression (); - var initLoc = LocationsBag.GetLocations (newInitializeExpression); - if (initLoc != null) - result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ArrayInitializerExpression.Roles.LBrace); - var commaLoc = LocationsBag.GetLocations (minit.Initializers); - int curComma = commaLoc != null ? commaLoc.Count - 1 : -1; - foreach (var expr in minit.Initializers) { - var eleInit = expr as CollectionElementInitializer; - if (eleInit == null) - continue; - for (int i = 0; i < eleInit.Arguments.Count; i++) { - var arg = eleInit.Arguments[i] as CollectionElementInitializer.ElementInitializerArgument; - if (arg == null) - continue; - init.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); - if (curComma >= 0) - init.AddChild (new CSharpTokenNode (Convert (commaLoc[curComma--]), 1), ArrayInitializerExpression.Roles.Comma); - } - } - if (initLoc != null) - result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ArrayInitializerExpression.Roles.RBrace); + var init = ConvertCollectionOrObjectInitializers (newInitializeExpression.Initializers); + if (init != null) result.AddChild (init, ObjectCreateExpression.InitializerRole); - } - return result; } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs index 871c6b38a7..afe73763df 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs @@ -6126,7 +6126,7 @@ void case_448() /* TODO: lbag*/ } else { yyVal = new CollectionOrObjectInitializers ((List) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); - lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } } @@ -6134,7 +6134,7 @@ void case_449() #line 3189 "cs-parser.jay" { yyVal = new CollectionOrObjectInitializers ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); - lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } void case_452() diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay index 94d77c5963..90638a1a0b 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay @@ -3182,13 +3182,13 @@ object_or_collection_initializer // TODO: lbag } else { $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); - lbag.AddLocation ($$, GetLocation ($3)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); } } | OPEN_BRACE member_initializer_list COMMA CLOSE_BRACE { $$ = new CollectionOrObjectInitializers ((List) $2, GetLocation ($1)); - lbag.AddLocation ($$, GetLocation ($3), GetLocation ($4)); + lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3), GetLocation ($4)); } ; diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 46f5f2918c..802fd557db 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -1,4 +1,4 @@ - + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} @@ -7,7 +7,6 @@ Library ICSharpCode.NRefactory ICSharpCode.NRefactory - v4.0 Properties 10.0.0 2.0 @@ -17,7 +16,7 @@ 1591,0618 False -Microsoft.Design#CA1026;-Microsoft.Security#CA2104 - True + true ..\ICSharpCode.NRefactory.snk False File @@ -52,11 +51,9 @@ - - + - - + @@ -412,6 +409,8 @@ + + From c373100923f0b4da49553f5e6a17262acf30837e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 15 Aug 2011 12:06:22 +0200 Subject: [PATCH 03/15] Fixed ComplexCollectionInitializer tests. --- .../Expression/ObjectCreateExpressionTests.cs | 26 ++++++++----------- .../Ast/Expressions/NamedExpressionList.cs | 5 ++++ .../CSharp/OutputVisitor/OutputVisitor.cs | 1 - 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs index f2c6468e06..f6bfc0d474 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs @@ -210,27 +210,23 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Type = new SimpleType("Contact"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression("Name", new PrimitiveExpression("Chris")), - new AssignmentExpression( - "PhoneNumbers", - new ArrayInitializerExpression { - Elements = { new PrimitiveExpression("206-555-0101") } - }) + new NamedExpression("Name", new PrimitiveExpression("Chris")), + new NamedExpressionList("PhoneNumbers") { + Expressions = { new PrimitiveExpression("206-555-0101") } + } }}}, new ObjectCreateExpression { Type = new SimpleType("Contact"), Arguments = { new IdentifierExpression("additionalParameter") }, Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression("Name", new PrimitiveExpression("Bob")), - new AssignmentExpression( - "PhoneNumbers", - new ArrayInitializerExpression { - Elements = { - new PrimitiveExpression("650-555-0199"), - new PrimitiveExpression("425-882-8080") - } - }) + new NamedExpression("Name", new PrimitiveExpression("Bob")), + new NamedExpressionList("PhoneNumbers") { + Expressions = { + new PrimitiveExpression("650-555-0199"), + new PrimitiveExpression("425-882-8080") + } + } }}} }}}); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs index 95b5ec1d63..3bac174c83 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs @@ -38,6 +38,11 @@ namespace ICSharpCode.NRefactory.CSharp { } + public NamedExpressionList (string identifier) + { + this.Identifier = identifier; + } + public string Identifier { get { return GetChildByRole (Roles.Identifier).Name; diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index ede6d17974..cec9ec5c2a 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -575,7 +575,6 @@ namespace ICSharpCode.NRefactory.CSharp OpenBrace(style); bool isFirst = true; foreach (AstNode node in elements) { - Console.WriteLine ("expr:"+node.GetType ()); if (isFirst) { isFirst = false; } else { From 3e99fabb2ed9028adede12d14db0e820344ec645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 15 Aug 2011 12:30:13 +0200 Subject: [PATCH 04/15] Fixed object create expression tests /remove named expression lists (was an obsolete node). I tried out the node, but choosed to go with namedexpression + arrayinitializerexpression because it's semantically the same. --- .../Expression/ObjectCreateExpressionTests.cs | 48 +++++----- .../CSharp/Ast/DepthFirstAstVisitor.cs | 5 - .../Ast/Expressions/NamedExpressionList.cs | 91 ------------------- .../CSharp/Ast/IAstVisitor.cs | 1 - .../CSharp/Ast/ObservableAstVisitor.cs | 10 -- .../CSharp/OutputVisitor/OutputVisitor.cs | 11 --- .../CSharp/Parser/CSharpParser.cs | 41 +++++++-- .../CSharp/Parser/mcs/cs-parser.cs | 1 - .../CSharp/Parser/mcs/cs-parser.jay | 1 - .../ICSharpCode.NRefactory.csproj | 1 - 10 files changed, 55 insertions(+), 155 deletions(-) delete mode 100644 ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs index f6bfc0d474..f4796d3fb1 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs @@ -58,8 +58,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Type = new SimpleType("Point"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression("X", new PrimitiveExpression(0)), - new AssignmentExpression("Y", new PrimitiveExpression(1)) + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) } }}); } @@ -73,8 +73,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Type = new SimpleType("Point"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression("X", new PrimitiveExpression(0)), - new AssignmentExpression("Y", new PrimitiveExpression(1)) + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) } }}); } @@ -88,8 +88,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Type = new SimpleType("Point"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression("X", new PrimitiveExpression(0)), - new AssignmentExpression("Y", new PrimitiveExpression(1)) + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) } }}); } @@ -103,24 +103,24 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Type = new SimpleType("Rectangle"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression( + new NamedExpression( "P1", new ObjectCreateExpression { Type = new SimpleType("Point"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression("X", new PrimitiveExpression(0)), - new AssignmentExpression("Y", new PrimitiveExpression(1)) + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) } }}), - new AssignmentExpression( + new NamedExpression( "P2", new ObjectCreateExpression { Type = new SimpleType("Point"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression("X", new PrimitiveExpression(2)), - new AssignmentExpression("Y", new PrimitiveExpression(3)) + new NamedExpression("X", new PrimitiveExpression(2)), + new NamedExpression("Y", new PrimitiveExpression(3)) } }}) }}}); @@ -135,20 +135,20 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Type = new SimpleType("Rectangle"), Initializer = new ArrayInitializerExpression { Elements = { - new AssignmentExpression( + new NamedExpression( "P1", new ArrayInitializerExpression { Elements = { - new AssignmentExpression("X", new PrimitiveExpression(0)), - new AssignmentExpression("Y", new PrimitiveExpression(1)) + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) } }), - new AssignmentExpression( + new NamedExpression( "P2", new ArrayInitializerExpression { Elements = { - new AssignmentExpression("X", new PrimitiveExpression(2)), - new AssignmentExpression("Y", new PrimitiveExpression(3)) + new NamedExpression("X", new PrimitiveExpression(2)), + new NamedExpression("Y", new PrimitiveExpression(3)) } }) }}}); @@ -211,9 +211,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Initializer = new ArrayInitializerExpression { Elements = { new NamedExpression("Name", new PrimitiveExpression("Chris")), - new NamedExpressionList("PhoneNumbers") { - Expressions = { new PrimitiveExpression("206-555-0101") } - } + new NamedExpression("PhoneNumbers", new ArrayInitializerExpression () { + Elements = { new PrimitiveExpression("206-555-0101") } + }) }}}, new ObjectCreateExpression { Type = new SimpleType("Contact"), @@ -221,12 +221,12 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Initializer = new ArrayInitializerExpression { Elements = { new NamedExpression("Name", new PrimitiveExpression("Bob")), - new NamedExpressionList("PhoneNumbers") { - Expressions = { + new NamedExpression("PhoneNumbers", new ArrayInitializerExpression () { + Elements = { new PrimitiveExpression("650-555-0199"), new PrimitiveExpression("425-882-8080") } - } + }) }}} }}}); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs index 347f90b820..89e73063dd 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs @@ -590,11 +590,6 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (namedExpression, data); } - public virtual S VisitNamedExpressionList (NamedExpressionList namedExpressionList, T data) - { - return VisitChildren (namedExpressionList, data); - } - public virtual S VisitEmptyExpression (EmptyExpression emptyExpression, T data) { return VisitChildren (emptyExpression, data); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs deleted file mode 100644 index 3bac174c83..0000000000 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedExpressionList.cs +++ /dev/null @@ -1,91 +0,0 @@ -// -// NamedExpressionList.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2011 Xamarin -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -using System.Collections.Generic; -using System.Linq; - -namespace ICSharpCode.NRefactory.CSharp -{ - /// - /// name = { expression1, ... , expressionN } - /// - public class NamedExpressionList : Expression - { - public NamedExpressionList() - { - } - - public NamedExpressionList (string identifier) - { - this.Identifier = identifier; - } - - public string Identifier { - get { - return GetChildByRole (Roles.Identifier).Name; - } - set { - SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); - } - } - - public Identifier IdentifierToken { - get { - return GetChildByRole (Roles.Identifier); - } - set { - SetChildByRole(Roles.Identifier, value); - } - } - - public CSharpTokenNode AssignToken { - get { return GetChildByRole (Roles.Assign); } - } - - public CSharpTokenNode LBraceToken { - get { return GetChildByRole (Roles.LBrace); } - } - - public AstNodeCollection Expressions { - get { return GetChildrenByRole (Roles.Expression); } - } - - public CSharpTokenNode RBraceToken { - get { return GetChildByRole (Roles.RBrace); } - } - - public override S AcceptVisitor(IAstVisitor visitor, T data) - { - return visitor.VisitNamedExpressionList(this, data); - } - - protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) - { - var o = other as NamedExpressionList; - return o != null && MatchString(this.Identifier, o.Identifier) && this.Expressions.DoMatch(o.Expressions, match); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs index b24358fba8..d18f464a2a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs @@ -46,7 +46,6 @@ namespace ICSharpCode.NRefactory.CSharp S VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, T data); S VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, T data); S VisitNamedExpression(NamedExpression namedExpression, T data); - S VisitNamedExpressionList(NamedExpressionList namedExpressionList, T data); S VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, T data); S VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, T data); S VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs b/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs index 26253be52e..ac8743de6a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs @@ -1131,16 +1131,6 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (namedExpression, data); } - public event Action NamedExpressionListVisited; - - S IAstVisitor.VisitNamedExpressionList (NamedExpressionList namedExpressionList, T data) - { - var handler = NamedExpressionListVisited; - if (handler != null) - handler (namedExpressionList, data); - return VisitChildren (namedExpressionList, data); - } - public event Action EmptyExpressionVisited; S IAstVisitor.VisitEmptyExpression (EmptyExpression emptyExpression, T data) diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index cec9ec5c2a..a6d27c0ee0 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -841,17 +841,6 @@ namespace ICSharpCode.NRefactory.CSharp return EndNode (namedExpression); } - public object VisitNamedExpressionList (NamedExpressionList namedExpressionList, object data) - { - StartNode (namedExpressionList); - WriteIdentifier (namedExpressionList.Identifier); - Space(); - WriteToken("=", NamedArgumentExpression.Roles.Assign); - Space (); - PrintInitializerElements(namedExpressionList.Expressions); - return EndNode (namedExpressionList); - } - public object VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, object data) { StartNode (nullReferenceExpression); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index 6974cc2467..2e6e115df1 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -2333,11 +2333,16 @@ namespace ICSharpCode.NRefactory.CSharp if (minit == null) return null; var init = new ArrayInitializerExpression (); + var braceLocs = LocationsBag.GetLocations (minit); + if (braceLocs != null) + init.AddChild (new CSharpTokenNode (Convert (braceLocs[0]), 1), ArrayInitializerExpression.Roles.LBrace); AddConvertCollectionOrObjectInitializers (init, minit); + if (braceLocs != null) + init.AddChild (new CSharpTokenNode (Convert (braceLocs[1]), 1), ArrayInitializerExpression.Roles.RBrace); return init; } - void AddConvertCollectionOrObjectInitializers (AstNode init, CollectionOrObjectInitializers minit) + void AddConvertCollectionOrObjectInitializers (Expression init, CollectionOrObjectInitializers minit) { var initLoc = LocationsBag.GetLocations (minit); var commaLoc = LocationsBag.GetLocations (minit.Initializers); @@ -2345,27 +2350,43 @@ namespace ICSharpCode.NRefactory.CSharp foreach (var expr in minit.Initializers) { var collectionInit = expr as CollectionElementInitializer; if (collectionInit != null) { - for (int i = 0; i < collectionInit.Arguments.Count; i++) { - var arg = collectionInit.Arguments[i] as CollectionElementInitializer.ElementInitializerArgument; - if (arg == null) - continue; - init.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); - if (curComma >= 0) - init.AddChild (new CSharpTokenNode (Convert (commaLoc[curComma--]), 1), ArrayInitializerExpression.Roles.Comma); + if (collectionInit.Arguments.Count != 1) { + var parent = new ArrayInitializerExpression (); + var braceLocs = LocationsBag.GetLocations (expr); + if (braceLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (braceLocs[0]), 1), ArrayInitializerExpression.Roles.LBrace); + for (int i = 0; i < collectionInit.Arguments.Count; i++) { + var arg = collectionInit.Arguments[i] as CollectionElementInitializer.ElementInitializerArgument; + if (arg == null) + continue; + parent.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); + if (curComma >= 0) + parent.AddChild (new CSharpTokenNode (Convert (commaLoc[curComma--]), 1), ArrayInitializerExpression.Roles.Comma); + } + if (braceLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (braceLocs[1]), 1), ArrayInitializerExpression.Roles.RBrace); + init.AddChild (parent, ArrayInitializerExpression.Roles.Expression); + } else { + var arg = collectionInit.Arguments[0] as CollectionElementInitializer.ElementInitializerArgument; + if (arg != null) + init.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); } + continue; } var eleInit = expr as ElementInitializer; if (eleInit != null) { - var nexpr = eleInit.Source is CollectionOrObjectInitializers ? (ICSharpCode.NRefactory.CSharp.Expression)new NamedExpressionList () : new NamedExpression (); + var nexpr = new NamedExpression (); nexpr.AddChild (Identifier.Create (eleInit.Name, Convert(eleInit.Location)), NamedArgumentExpression.Roles.Identifier); var assignLoc = LocationsBag.GetLocations (eleInit); if (assignLoc != null) nexpr.AddChild (new CSharpTokenNode (Convert (assignLoc[0]), 1), NamedArgumentExpression.Roles.Assign); if (eleInit.Source != null) { if (eleInit.Source is CollectionOrObjectInitializers) { - AddConvertCollectionOrObjectInitializers (nexpr, eleInit.Source as CollectionOrObjectInitializers); + var arrInit = new ArrayInitializerExpression (); + AddConvertCollectionOrObjectInitializers (arrInit, eleInit.Source as CollectionOrObjectInitializers); + nexpr.AddChild (arrInit, NamedArgumentExpression.Roles.Expression); } else { nexpr.AddChild ((Expression)eleInit.Source.Accept (this), NamedArgumentExpression.Roles.Expression); } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs index afe73763df..8c77d55597 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs @@ -5851,7 +5851,6 @@ void case_350() { TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); - lbag.AppendTo (type_args, GetLocation (yyVals[-1+yyTop])); yyVal = type_args; locationListStack.Peek ().Add (GetLocation (yyVals[-1+yyTop])); } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay index 90638a1a0b..2bf89c9b16 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay @@ -2763,7 +2763,6 @@ type_arguments { TypeArguments type_args = (TypeArguments) $1; type_args.Add ((FullNamedExpression) $3); - lbag.AppendTo (type_args, GetLocation ($2)); $$ = type_args; locationListStack.Peek ().Add (GetLocation ($2)); } diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 802fd557db..a50b047eb4 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -410,7 +410,6 @@ - From abbf9d661d483098b96b746c77f0f3ce3953352b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 15 Aug 2011 12:33:51 +0200 Subject: [PATCH 05/15] Used the namedexpression instead of assignment/namedargument expressions. --- .../AnonymousTypeCreateExpressionTests.cs | 2 +- .../CSharp/OutputVisitor/OutputVisitor.cs | 7 +------ .../CSharp/Parser/CSharpParser.cs | 19 +++++++++---------- 3 files changed, 11 insertions(+), 17 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs index 54aa750c50..e0190fd267 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs @@ -31,7 +31,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression "new { Name = \"Test\", Price, Something.Property }", new AnonymousTypeCreateExpression { Initializers = { - new NamedArgumentExpression("Name", new PrimitiveExpression("Test")), + new NamedExpression("Name", new PrimitiveExpression("Test")), new IdentifierExpression("Price"), new IdentifierExpression("Something").Member("Property") }}); diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs index a6d27c0ee0..62ad069cb8 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs @@ -819,12 +819,7 @@ namespace ICSharpCode.NRefactory.CSharp { StartNode (namedArgumentExpression); WriteIdentifier (namedArgumentExpression.Identifier); - if (namedArgumentExpression.Parent is AnonymousTypeCreateExpression) { - Space(); - WriteToken("=", NamedArgumentExpression.Roles.Assign); - } else { - WriteToken(":", NamedArgumentExpression.Roles.Colon); - } + WriteToken(":", NamedArgumentExpression.Roles.Colon); Space (); namedArgumentExpression.Expression.AcceptVisitor (this, data); return EndNode (namedArgumentExpression); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index 2e6e115df1..78d003fe7c 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -200,14 +200,13 @@ namespace ICSharpCode.NRefactory.CSharp } if (attr.NamedArguments != null) { foreach (NamedArgument na in attr.NamedArguments) { - var newArg = new AssignmentExpression (); - newArg.Operator = AssignmentOperatorType.Assign; - newArg.AddChild (new IdentifierExpression (na.Name, Convert (na.Location)), AssignmentExpression.LeftRole); + var newArg = new NamedExpression (); + newArg.AddChild (Identifier.Create (na.Name, Convert (na.Location)), NamedExpression.Roles.Identifier); var argLoc = LocationsBag.GetLocations (na); if (argLoc != null) - newArg.AddChild (new CSharpTokenNode (Convert (argLoc[0]), 1), AssignmentExpression.Roles.Assign); - newArg.AddChild ((Expression)na.Expr.Accept (this), AssignmentExpression.RightRole); + newArg.AddChild (new CSharpTokenNode (Convert (argLoc[0]), 1), NamedExpression.Roles.Assign); + newArg.AddChild ((Expression)na.Expr.Accept (this), NamedExpression.Roles.Expression); result.AddChild (newArg, Attribute.Roles.Argument); } } @@ -2318,11 +2317,11 @@ namespace ICSharpCode.NRefactory.CSharp if (location == null) { result.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); } else { - var namedArgument = new NamedArgumentExpression (); - namedArgument.AddChild (Identifier.Create (par.Name, Convert (par.Location)), AnonymousTypeCreateExpression.Roles.Identifier); - namedArgument.AddChild (new CSharpTokenNode (Convert (location[0]), 1), AnonymousTypeCreateExpression.Roles.Assign); - namedArgument.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); - result.AddChild (namedArgument, AnonymousTypeCreateExpression.Roles.Expression); + var namedExpression = new NamedExpression (); + namedExpression.AddChild (Identifier.Create (par.Name, Convert (par.Location)), AnonymousTypeCreateExpression.Roles.Identifier); + namedExpression.AddChild (new CSharpTokenNode (Convert (location[0]), 1), AnonymousTypeCreateExpression.Roles.Assign); + namedExpression.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); + result.AddChild (namedExpression, AnonymousTypeCreateExpression.Roles.Expression); } } return result; From 769c0ae2e07d608182c06a264f3849e35c0a6825 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 15 Aug 2011 14:18:37 +0200 Subject: [PATCH 06/15] Allow CecilProjectContent to be serialized. Add FastSerializer to NRefactory.Utils. --- .../Parser/TypeSystemConvertVisitorTests.cs | 11 +- .../ICSharpCode.NRefactory.Tests.csproj | 1 + .../TypeSystem/CecilLoaderTests.cs | 2 +- .../TypeSystem/SerializedCecilLoaderTests.cs | 42 + .../TypeSystem/TypeSystemTests.cs | 2 +- .../Documentation/XmlDocumentationProvider.cs | 6 + .../ICSharpCode.NRefactory.csproj | 2 + .../TypeSystem/ArrayType.cs | 2 + .../TypeSystem/ByReferenceType.cs | 2 + .../TypeSystem/CecilLoader.cs | 6 + .../TypeSystem/IAnnotatable.cs | 1 + .../Implementation/AbstractFreezable.cs | 2 + .../Implementation/AbstractMember.cs | 1 + .../TypeSystem/Implementation/AbstractType.cs | 1 + .../Implementation/DefaultAccessor.cs | 1 + .../Implementation/DefaultAttribute.cs | 1 + .../TypeSystem/Implementation/DefaultEvent.cs | 1 + .../TypeSystem/Implementation/DefaultField.cs | 1 + .../Implementation/DefaultMethod.cs | 6 +- .../Implementation/DefaultParameter.cs | 1 + .../Implementation/DefaultProperty.cs | 1 + .../Implementation/DefaultTypeDefinition.cs | 1 + .../Implementation/DefaultTypeParameter.cs | 10 +- .../Implementation/GetClassTypeReference.cs | 3 +- .../Implementation/NestedTypeReference.cs | 1 + .../Implementation/ProxyTypeResolveContext.cs | 1 + .../Implementation/SimpleConstantValue.cs | 1 + .../Implementation/SimpleInterningProvider.cs | 10 +- .../TypeSystem/Implementation/TypeStorage.cs | 35 +- .../Implementation/TypeWithElementType.cs | 1 + .../Implementation/VoidTypeDefinition.cs | 1 + .../TypeSystem/IntersectionType.cs | 1 + .../TypeSystem/ParameterizedType.cs | 2 + .../TypeSystem/PointerType.cs | 2 + .../TypeSystem/SharedTypes.cs | 1 + .../Utils/7BitEncodedInts.cs | 117 ++ ICSharpCode.NRefactory/Utils/BitVector16.cs | 1 + ICSharpCode.NRefactory/Utils/EmptyList.cs | 1 + .../Utils/FastSerializer.cs | 1148 +++++++++++++++++ 39 files changed, 1417 insertions(+), 13 deletions(-) create mode 100644 ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs create mode 100644 ICSharpCode.NRefactory/Utils/7BitEncodedInts.cs create mode 100644 ICSharpCode.NRefactory/Utils/FastSerializer.cs diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index e6b67ae927..96a2899ca0 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -20,6 +20,7 @@ using System; using System.IO; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser @@ -27,10 +28,13 @@ namespace ICSharpCode.NRefactory.CSharp.Parser [TestFixture] public class TypeSystemConvertVisitorTests : TypeSystemTests { - ITypeResolveContext ctx = CecilLoaderTests.Mscorlib; - [TestFixtureSetUp] public void FixtureSetUp() + { + testCasePC = ParseTestCase(); + } + + internal static IProjectContent ParseTestCase() { const string fileName = "TypeSystemTests.TestCase.cs"; @@ -40,10 +44,11 @@ namespace ICSharpCode.NRefactory.CSharp.Parser cu = parser.Parse(s); } - testCasePC = new SimpleProjectContent(); + var testCasePC = new SimpleProjectContent(); ParsedFile parsedFile = new TypeSystemConvertVisitor(testCasePC, fileName).Convert(cu); parsedFile.Freeze(); testCasePC.UpdateProjectContent(null, parsedFile); + return testCasePC; } } } diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index 5b247cae60..614f24eb7e 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -148,6 +148,7 @@ + diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs index c9dc2859c3..0a3746f585 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs @@ -78,7 +78,7 @@ namespace ICSharpCode.NRefactory.TypeSystem IProperty def = c.Properties.Single(p => p.Name == "Default"); ParameterizedType pt = (ParameterizedType)def.ReturnType.Resolve(ctx); Assert.AreEqual("System.Collections.Generic.Comparer", pt.FullName); - Assert.AreSame(c.TypeParameters[0], pt.TypeArguments[0]); + Assert.AreEqual(c.TypeParameters[0], pt.TypeArguments[0]); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs new file mode 100644 index 0000000000..9bbafb8516 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs @@ -0,0 +1,42 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.IO; +using ICSharpCode.NRefactory.Utils; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + [TestFixture] + public class SerializedCecilLoaderTests : TypeSystemTests + { + [TestFixtureSetUp] + public void FixtureSetUp() + { + CecilLoader loader = new CecilLoader() { IncludeInternalMembers = true }; + IProjectContent pc = loader.LoadAssemblyFile(typeof(TestCase.SimplePublicClass).Assembly.Location); + FastSerializer serializer = new FastSerializer(); + using (MemoryStream ms = new MemoryStream()) { + serializer.Serialize(ms, pc); + ms.Position = 0; + testCasePC = (IProjectContent)serializer.Deserialize(ms); + } + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index b65aa16a9c..8146213d65 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -84,7 +84,7 @@ namespace ICSharpCode.NRefactory.TypeSystem public void DynamicType() { ITypeDefinition testClass = testCasePC.GetTypeDefinition(typeof(DynamicTest)); - Assert.AreSame(SharedTypes.Dynamic, testClass.Properties.Single().ReturnType.Resolve(ctx)); + Assert.AreEqual(SharedTypes.Dynamic, testClass.Properties.Single().ReturnType.Resolve(ctx)); Assert.AreEqual(0, testClass.Properties.Single().Attributes.Count); } diff --git a/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs b/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs index bef0dffd81..ef5fc7cac3 100644 --- a/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs +++ b/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs @@ -33,6 +33,7 @@ namespace ICSharpCode.NRefactory.Documentation /// This class first creates an in-memory index of the .xml file, and then uses that to read only the requested members. /// This way, we avoid keeping all the documentation in memory. /// + [Serializable] public class XmlDocumentationProvider : IDocumentationProvider { #region Cache @@ -66,6 +67,7 @@ namespace ICSharpCode.NRefactory.Documentation } #endregion + [Serializable] struct IndexEntry : IComparable { /// @@ -90,7 +92,9 @@ namespace ICSharpCode.NRefactory.Documentation } } + [NonSerialized] readonly XmlDocumentationCache cache = new XmlDocumentationCache(); + readonly string fileName; DateTime lastWriteDate; IndexEntry[] index; // SORTED array of index entries @@ -265,6 +269,8 @@ namespace ICSharpCode.NRefactory.Documentation #endregion #region Save index / Restore from index + // TODO: consider removing this code, we're just using serialization instead + // FILE FORMAT FOR BINARY DOCUMENTATION // long magic = 0x4244636f446c6d58 (identifies file type = 'XmlDocDB') const long magic = 0x4244636f446c6d58; diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index a50b047eb4..0f57ac2975 100644 --- a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj +++ b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj @@ -336,6 +336,7 @@ + @@ -343,6 +344,7 @@ + diff --git a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs index 86dc6884ad..c5a8fb5a8a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents an array type. /// + [Serializable] public sealed class ArrayType : TypeWithElementType { readonly int dimensions; @@ -135,6 +136,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + [Serializable] public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning { ITypeReference elementType; diff --git a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs index 8ae58c6e7c..553341f2f3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs @@ -21,6 +21,7 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { + [Serializable] public sealed class ByReferenceType : TypeWithElementType { public ByReferenceType(IType elementType) : base(elementType) @@ -68,6 +69,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + [Serializable] public class ByReferenceTypeReference : ITypeReference { readonly ITypeReference elementType; diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 02fbb9fa67..0bdb727d61 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -84,6 +84,9 @@ namespace ICSharpCode.NRefactory.TypeSystem { if (createCecilReferences) typeSystemTranslationTable = new Dictionary (); + + // Enable interning by default. + this.InterningProvider = new SimpleInterningProvider(); } #region Load From AssemblyDefinition @@ -164,6 +167,7 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region IProjectContent implementation + [Serializable] sealed class CecilProjectContent : ProxyTypeResolveContext, IProjectContent, ISynchronizedTypeResolveContext, IDocumentationProvider { readonly string assemblyName; @@ -840,8 +844,10 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Read Type Definition + [Serializable] sealed class CecilTypeDefinition : DefaultTypeDefinition { + [NonSerialized] internal TypeDefinition typeDefinition; public CecilTypeDefinition(IProjectContent pc, TypeDefinition typeDefinition) diff --git a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs index 2021496969..ff30f87443 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs @@ -78,6 +78,7 @@ namespace ICSharpCode.NRefactory void RemoveAnnotations(Type type); } + [Serializable] public abstract class AbstractAnnotatable : IAnnotatable { // Annotations: points either null (no annotations), to the single annotation, diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs index b3f5996ee2..7cc8cf63a7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Base class for immutable objects. Provides implementation for IFreezable that reports the /// object as always-frozen. /// + [Serializable] public abstract class Immutable : IFreezable { bool IFreezable.IsFrozen { @@ -38,6 +39,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + [Serializable] public abstract class AbstractFreezable : IFreezable { bool isFrozen; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs index 31521b5ce7..e581c1ec2b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Base class for implementations. /// + [Serializable] public abstract class AbstractMember : AbstractFreezable, IMember { // possible optimizations to reduce the memory usage of AbstractMember: diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs index bc2a300b2b..d070a81471 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs @@ -26,6 +26,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation for IType interface. /// + [Serializable] public abstract class AbstractType : IType { public virtual string FullName { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs index 98df4ba2f8..3be4ba66d5 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public sealed class DefaultAccessor : AbstractFreezable, IAccessor, ISupportsInterning { static readonly DefaultAccessor[] defaultAccessors = CreateDefaultAccessors(); diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs index f14bc057a6..152146d52e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public sealed class DefaultAttribute : AbstractFreezable, IAttribute, ISupportsInterning { ITypeReference attributeType; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs index 6f065d0030..bea77a960f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs @@ -23,6 +23,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public class DefaultEvent : AbstractMember, IEvent { IAccessor addAccessor, removeAccessor, invokeAccessor; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs index 2293e7f6a7..22c33d980d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs @@ -23,6 +23,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public class DefaultField : AbstractMember, IField { IConstantValue constantValue; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs index daa3047ff6..203cd31ff2 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of interface. /// + [Serializable] public class DefaultMethod : AbstractMember, IMethod { IList returnTypeAttributes; @@ -123,7 +124,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation var p = this.Parameters; for (int i = 0; i < p.Count; i++) { if (i > 0) b.Append(", "); - b.Append(p[i].ToString()); + if (p[i] == null) + b.Append("null"); + else + b.Append(p[i].ToString()); } b.Append("):"); b.Append(ReturnType.ToString()); diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs index a9823bc5e6..fc035938fe 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs @@ -26,6 +26,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation for IParameter. /// + [Serializable] public sealed class DefaultParameter : AbstractFreezable, IParameter, ISupportsInterning { string name = string.Empty; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs index 6a2ddf4949..8e3ec666fb 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs @@ -24,6 +24,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public class DefaultProperty : AbstractMember, IProperty { IAccessor getter, setter; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs index f9c3eaa086..34d4b3d79a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -25,6 +25,7 @@ using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + [Serializable] public class DefaultTypeDefinition : AbstractFreezable, ITypeDefinition { readonly IProjectContent projectContent; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs index ca234e5bd1..656e1348ce 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public sealed class DefaultTypeParameter : AbstractFreezable, ITypeParameter, ISupportsInterning { string name; @@ -348,8 +349,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { - constraints = provider.InternList(constraints); - attributes = provider.InternList(attributes); + // protect against cyclic constraints + using (var busyLock = BusyManager.Enter(this)) { + if (busyLock.Success) { + constraints = provider.InternList(constraints); + attributes = provider.InternList(attributes); + } + } } int ISupportsInterning.GetHashCodeForInterning() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs index 83a5cb45d0..c0df2456bd 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs @@ -25,11 +25,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Type Reference used when the fully qualified type name is known. /// + [Serializable] public sealed class GetClassTypeReference : ITypeReference, ISupportsInterning { string nameSpace, name; int typeParameterCount; - //volatile CachedResult v_cachedResult; + // [NonSerialized] volatile CachedResult v_cachedResult; public GetClassTypeReference(string nameSpace, string name, int typeParameterCount) { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs index 11f8749454..04e9385a21 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs @@ -23,6 +23,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Type reference used to reference nested types. /// + [Serializable] public sealed class NestedTypeReference : ITypeReference, ISupportsInterning { ITypeReference declaringTypeRef; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs index 43f1f9fe56..898c98077b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Proxy that forwards calls to another TypeResolveContext. /// Useful as base class for decorators. /// + [Serializable] public class ProxyTypeResolveContext : AbstractAnnotatable, ITypeResolveContext { protected readonly ITypeResolveContext target; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs index 9cba2a5ecc..b378430374 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs @@ -23,6 +23,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// A simple constant value that is independent of the resolve context. /// + [Serializable] public sealed class SimpleConstantValue : Immutable, IConstantValue, ISupportsInterning { ITypeReference type; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs index ca7ef2f7dc..58009843df 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs @@ -104,6 +104,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation Dictionary supportsInternDict = new Dictionary(new InterningComparer()); Dictionary listDict = new Dictionary(new ListComparer()); + int stackDepth = 0; + public T Intern(T obj) where T : class { if (obj == null) @@ -127,6 +129,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation else byValueDict.Add(obj, obj); } + stackDepth--; return obj; } @@ -138,8 +141,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation T oldItem = list[i]; T newItem = Intern(oldItem); if (oldItem != newItem) { - if (list.IsReadOnly) - list = new T[list.Count]; + if (list.IsReadOnly) { + T[] array = new T[list.Count]; + list.CopyTo(array, 0); + list = array; + } list[i] = newItem; } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs index 407390cf55..53eb718cef 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs @@ -19,8 +19,8 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Threading; - using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -31,7 +31,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Concurrent read accesses are thread-safe, but a write access concurrent to any other access is not safe. /// - public sealed class TypeStorage : ITypeResolveContext + [Serializable] + public sealed class TypeStorage : ITypeResolveContext, ISerializable, IDeserializationCallback { #region FullNameAndTypeParameterCount struct FullNameAndTypeParameterCount @@ -362,5 +363,35 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } #endregion + + #region Serialization + /// + /// Creates a new TypeStorage instance. + /// + public TypeStorage() + { + } + + SerializationInfo serializationInfo; + + protected TypeStorage(SerializationInfo info, StreamingContext context) + { + this.serializationInfo = info; + } + + void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("Types", this.GetTypes().ToArray()); + } + + void IDeserializationCallback.OnDeserialization(object sender) + { + if (serializationInfo == null) + return; + foreach (var typeDef in (ITypeDefinition[])serializationInfo.GetValue("Types", typeof(ITypeDefinition[]))) { + UpdateType(typeDef); + } + } + #endregion } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs index 1f86861879..482fcc8acd 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs @@ -20,6 +20,7 @@ using System; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + [Serializable] public abstract class TypeWithElementType : AbstractType { protected readonly IType elementType; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs index e8ec0a12c3..c8b2d8832f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs @@ -24,6 +24,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Special type definition for 'void'. /// + [Serializable] public class VoidTypeDefinition : DefaultTypeDefinition { public VoidTypeDefinition(IProjectContent projectContent) diff --git a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs index 3e0251845a..2e5bf8849a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs @@ -30,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents the intersection of several types. /// + [Serializable] public class IntersectionType : AbstractType { readonly ReadOnlyCollection types; diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs index 9cd4f872e8..862abbc3fb 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -36,6 +36,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// type parameters in the signatures of the members are replaced with /// the type arguments. /// + [Serializable] public sealed class ParameterizedType : Immutable, IType { readonly ITypeDefinition genericType; @@ -327,6 +328,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// ParameterizedTypeReference is a reference to generic class that specifies the type parameters. /// Example: List<string> /// + [Serializable] public sealed class ParameterizedTypeReference : ITypeReference, ISupportsInterning { public static ITypeReference Create(ITypeReference genericType, IEnumerable typeArguments) diff --git a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs index 2b2a54d6d7..07dc29c1a2 100644 --- a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs @@ -22,6 +22,7 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { + [Serializable] public sealed class PointerType : TypeWithElementType { public PointerType(IType elementType) : base(elementType) @@ -69,6 +70,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + [Serializable] public class PointerTypeReference : ITypeReference { readonly ITypeReference elementType; diff --git a/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs b/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs index 62bb562adf..6fc19ae88f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs +++ b/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs @@ -70,6 +70,7 @@ namespace ICSharpCode.NRefactory.TypeSystem * would have to return true even though these are two distinct definitions. */ + [Serializable] sealed class SharedTypeImpl : AbstractType { readonly TypeKind kind; diff --git a/ICSharpCode.NRefactory/Utils/7BitEncodedInts.cs b/ICSharpCode.NRefactory/Utils/7BitEncodedInts.cs new file mode 100644 index 0000000000..b16047c95c --- /dev/null +++ b/ICSharpCode.NRefactory/Utils/7BitEncodedInts.cs @@ -0,0 +1,117 @@ +// Copyright (c) 2011 Daniel Grunwald +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.Utils +{ + /// + /// A binary reader that can read the output of BinaryWriterWith7BitEncodedInts. + /// + public sealed class BinaryReaderWith7BitEncodedInts : BinaryReader + { + public BinaryReaderWith7BitEncodedInts(Stream stream) : base(stream) + { + } + + public override short ReadInt16() + { + return unchecked((short)(ushort)base.Read7BitEncodedInt()); + } + + public override ushort ReadUInt16() + { + return unchecked((ushort)base.Read7BitEncodedInt()); + } + + public override int ReadInt32() + { + return base.Read7BitEncodedInt(); + } + + public override uint ReadUInt32() + { + return unchecked((uint)base.Read7BitEncodedInt()); + } + + public override long ReadInt64() + { + return unchecked((long)this.ReadUInt64()); + } + + public override ulong ReadUInt64() + { + ulong num = 0; + int shift = 0; + while (shift < 64) { + byte b = this.ReadByte(); + num |= (ulong)(b & 127) << shift; + shift += 7; + if ((b & 128) == 0) { + return num; + } + } + throw new FormatException("Invalid 7-bit int64"); + } + } + + /// + /// A binary writer that encodes all integers as 7-bit-encoded-ints. + /// + public sealed class BinaryWriterWith7BitEncodedInts : BinaryWriter + { + public BinaryWriterWith7BitEncodedInts(Stream stream) : base(stream) + { + } + + public override void Write(short value) + { + base.Write7BitEncodedInt(unchecked((ushort)value)); + } + + public override void Write(ushort value) + { + base.Write7BitEncodedInt(value); + } + + public override void Write(int value) + { + base.Write7BitEncodedInt(value); + } + + public override void Write(uint value) + { + base.Write7BitEncodedInt(unchecked((int)value)); + } + + public override void Write(long value) + { + this.Write(unchecked((ulong)value)); + } + + public override void Write(ulong value) + { + while (value >= 128) { + this.Write(unchecked((byte)(value | 128u))); + value >>= 7; + } + this.Write(unchecked((byte)value)); + } + } +} diff --git a/ICSharpCode.NRefactory/Utils/BitVector16.cs b/ICSharpCode.NRefactory/Utils/BitVector16.cs index b5ab44bee8..a8b5122159 100644 --- a/ICSharpCode.NRefactory/Utils/BitVector16.cs +++ b/ICSharpCode.NRefactory/Utils/BitVector16.cs @@ -23,6 +23,7 @@ namespace ICSharpCode.NRefactory.Utils /// /// Holds 16 boolean values. /// + [Serializable] public struct BitVector16 : IEquatable { ushort data; diff --git a/ICSharpCode.NRefactory/Utils/EmptyList.cs b/ICSharpCode.NRefactory/Utils/EmptyList.cs index 4022223a83..f39e6f2916 100644 --- a/ICSharpCode.NRefactory/Utils/EmptyList.cs +++ b/ICSharpCode.NRefactory/Utils/EmptyList.cs @@ -23,6 +23,7 @@ using System.Collections.ObjectModel; namespace ICSharpCode.NRefactory { + [Serializable] sealed class EmptyList : IList, IEnumerator { public static readonly IList Instance = new EmptyList(); diff --git a/ICSharpCode.NRefactory/Utils/FastSerializer.cs b/ICSharpCode.NRefactory/Utils/FastSerializer.cs new file mode 100644 index 0000000000..a823c2db1a --- /dev/null +++ b/ICSharpCode.NRefactory/Utils/FastSerializer.cs @@ -0,0 +1,1148 @@ +// Copyright (c) 2011 Daniel Grunwald +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Reflection.Emit; +using System.Runtime.CompilerServices; +using System.Runtime.Serialization; + +namespace ICSharpCode.NRefactory.Utils +{ + public class FastSerializer + { + #region Serialization + sealed class ReferenceComparer : IEqualityComparer + { + bool IEqualityComparer.Equals(object a, object b) + { + return a == b; + } + + int IEqualityComparer.GetHashCode(object obj) + { + return RuntimeHelpers.GetHashCode(obj); + } + } + + sealed class SerializationContext + { + readonly Dictionary objectToID = new Dictionary(new ReferenceComparer()); + readonly List instances = new List(); // index: object ID + readonly List typeIDs = new List(); // index: object ID + int stringTypeID = -1; + int typeCountForObjects = 0; + + readonly Dictionary typeToID = new Dictionary(); + readonly List types = new List(); // index: type ID + readonly List writers = new List(); // index: type ID + + readonly FastSerializer fastSerializer; + public readonly BinaryWriter writer; + + internal SerializationContext(FastSerializer fastSerializer, BinaryWriter writer) + { + this.fastSerializer = fastSerializer; + this.writer = writer; + instances.Add(null); // use object ID 0 for null + typeIDs.Add(-1); + } + + #region Scanning + /// + /// Marks an instance for future scanning. + /// + public void Mark(object instance) + { + if (instance == null || objectToID.ContainsKey(instance)) + return; + Log(" Mark {0}", instance.GetType().Name); + + objectToID.Add(instance, instances.Count); + instances.Add(instance); + } + + internal void Scan() + { + Log("Scanning..."); + List objectScanners = new List(); // index: type ID + // starting from 1, because index 0 is null + for (int i = 1; i < instances.Count; i++) { + object instance = instances[i]; + ISerializable serializable = instance as ISerializable; + Type type = instance.GetType(); + Log("Scan #{0}: {1}", i, type.Name); + int typeID; + if (!typeToID.TryGetValue(type, out typeID)) { + typeID = types.Count; + typeToID.Add(type, typeID); + types.Add(type); + Log("Registered type %{0}: {1}", typeID, type); + if (type == typeof(string)) { + stringTypeID = typeID; + } + objectScanners.Add(serializable != null ? null : fastSerializer.GetScanner(type)); + writers.Add(serializable != null ? serializationInfoWriter : fastSerializer.GetWriter(type)); + } + typeIDs.Add(typeID); + if (serializable != null) { + SerializationInfo info = new SerializationInfo(type, fastSerializer.formatterConverter); + serializable.GetObjectData(info, fastSerializer.streamingContext); + instances[i] = info; + foreach (SerializationEntry entry in info) { + Mark(entry.Value); + } + } else { + objectScanners[typeID](this, instance); + } + } + } + #endregion + + #region Scan Types + internal void ScanTypes() + { + typeCountForObjects = types.Count; + for (int i = 0; i < types.Count; i++) { + foreach (FieldInfo field in GetSerializableFields(types[i])) { + if (!typeToID.ContainsKey(field.FieldType)) { + typeToID.Add(field.FieldType, types.Count); + types.Add(field.FieldType); + } + } + } + } + #endregion + + #region Writing + public void WriteObjectID(object instance) + { + int id = (instance == null) ? 0 : objectToID[instance]; + if (instances.Count <= ushort.MaxValue) + writer.Write((ushort)id); + else + writer.Write(id); + } + + internal void Write() + { + Log("Writing..."); + // Write out type information + writer.Write(types.Count); + writer.Write(instances.Count); + writer.Write(typeCountForObjects); + writer.Write(stringTypeID); + foreach (Type type in types) { + writer.Write(type.AssemblyQualifiedName); + } + foreach (Type type in types) { + if (type.IsArray || type.IsPrimitive || typeof(ISerializable).IsAssignableFrom(type)) { + writer.Write(byte.MaxValue); + } else { + var fields = GetSerializableFields(type); + if (fields.Count >= byte.MaxValue) + throw new SerializationException("Too many fields."); + writer.Write((byte)fields.Count); + foreach (var field in fields) { + int typeID = typeToID[field.FieldType]; + if (types.Count <= ushort.MaxValue) + writer.Write((ushort)typeID); + else + writer.Write(typeID); + writer.Write(field.Name); + } + } + } + + // Write out information necessary to create the instances + // starting from 1, because index 0 is null + for (int i = 1; i < instances.Count; i++) { + int typeID = typeIDs[i]; + if (types.Count <= ushort.MaxValue) + writer.Write((ushort)typeID); + else + writer.Write(typeID); + if (typeID == stringTypeID) { + // Strings are written to the output immediately + // - we can't create an empty string and fill it later + writer.Write((string)instances[i]); + } else if (types[typeID].IsArray) { + // For arrays, write down the length, because we need that to create the array instance + writer.Write(((Array)instances[i]).Length); + } + } + // Write out information necessary to fill data into the instances + for (int i = 1; i < instances.Count; i++) { + Log("0x{2:x6}, Write #{0}: {1}", i, types[typeIDs[i]].Name, writer.BaseStream.Position); + writers[typeIDs[i]](this, instances[i]); + } + Log("Serialization done."); + } + #endregion + } + + #region Object Scanners + delegate void ObjectScanner(SerializationContext context, object instance); + + static readonly MethodInfo mark = typeof(SerializationContext).GetMethod("Mark", new[] { typeof(object) }); + static readonly FieldInfo writerField = typeof(SerializationContext).GetField("writer"); + + Dictionary scanners = new Dictionary(); + + ObjectScanner GetScanner(Type type) + { + ObjectScanner scanner; + if (!scanners.TryGetValue(type, out scanner)) { + scanner = CreateScanner(type); + scanners.Add(type, scanner); + } + return scanner; + } + + ObjectScanner CreateScanner(Type type) + { + bool isArray = type.IsArray; + if (isArray) { + if (type.GetArrayRank() != 1) + throw new NotImplementedException(); + type = type.GetElementType(); + if (!type.IsValueType) { + return delegate (SerializationContext context, object array) { + foreach (object val in (object[])array) { + context.Mark(val); + } + }; + } + } + for (Type baseType = type; baseType != null; baseType = baseType.BaseType) { + if (!baseType.IsSerializable) + throw new SerializationException("Type " + baseType + " is not [Serializable]."); + } + List fields = GetSerializableFields(type); + fields.RemoveAll(f => !IsReferenceOrContainsReferences(f.FieldType)); + if (fields.Count == 0) { + // The scanner has nothing to do for this object. + return delegate { }; + } + + DynamicMethod dynamicMethod = new DynamicMethod( + (isArray ? "ScanArray_" : "Scan_") + type.Name, + typeof(void), new [] { typeof(SerializationContext), typeof(object) }, + true); + ILGenerator il = dynamicMethod.GetILGenerator(); + + + if (isArray) { + var instance = il.DeclareLocal(type.MakeArrayType()); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Castclass, type.MakeArrayType()); + il.Emit(OpCodes.Stloc, instance); // instance = (type[])arg_1; + + // for (int i = 0; i < instance.Length; i++) scan instance[i]; + var loopStart = il.DefineLabel(); + var loopHead = il.DefineLabel(); + var loopVariable = il.DeclareLocal(typeof(int)); + il.Emit(OpCodes.Ldc_I4_0); + il.Emit(OpCodes.Stloc, loopVariable); // loopVariable = 0 + il.Emit(OpCodes.Br, loopHead); // goto loopHead; + + il.MarkLabel(loopStart); + + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable + il.Emit(OpCodes.Ldelem, type); // &instance[loopVariable] + EmitScanValueType(il, type); + + + il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable + il.Emit(OpCodes.Ldc_I4_1); // loopVariable, 1 + il.Emit(OpCodes.Add); // loopVariable+1 + il.Emit(OpCodes.Stloc, loopVariable); // loopVariable++; + + il.MarkLabel(loopHead); + il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable + il.Emit(OpCodes.Ldloc, instance); // loopVariable, instance + il.Emit(OpCodes.Ldlen); // loopVariable, instance.Length + il.Emit(OpCodes.Conv_I4); + il.Emit(OpCodes.Blt, loopStart); // if (loopVariable < instance.Length) goto loopStart; + } else if (type.IsValueType) { + // boxed value type + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Unbox_Any, type); + EmitScanValueType(il, type); + } else { + // reference type + var instance = il.DeclareLocal(type); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Castclass, type); + il.Emit(OpCodes.Stloc, instance); // instance = (type)arg_1; + + foreach (FieldInfo field in fields) { + EmitScanField(il, instance, field); // scan instance.Field + } + } + il.Emit(OpCodes.Ret); + return (ObjectScanner)dynamicMethod.CreateDelegate(typeof(ObjectScanner)); + } + + /// + /// Emit 'scan instance.Field'. + /// Stack transition: ... => ... + /// + void EmitScanField(ILGenerator il, LocalBuilder instance, FieldInfo field) + { + if (field.FieldType.IsValueType) { + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldfld, field); // instance.field + EmitScanValueType(il, field.FieldType); + } else { + il.Emit(OpCodes.Ldarg_0); // context + il.Emit(OpCodes.Ldloc, instance); // context, instance + il.Emit(OpCodes.Ldfld, field); // context, instance.field + il.Emit(OpCodes.Call, mark); // context.Mark(instance.field); + } + } + + /// + /// Stack transition: ..., value => ... + /// + void EmitScanValueType(ILGenerator il, Type valType) + { + var fieldRef = il.DeclareLocal(valType); + il.Emit(OpCodes.Stloc, fieldRef); + + foreach (FieldInfo field in GetSerializableFields(valType)) { + if (IsReferenceOrContainsReferences(field.FieldType)) { + EmitScanField(il, fieldRef, field); + } + } + } + + static List GetSerializableFields(Type type) + { + List fields = new List(); + for (Type baseType = type; baseType != null; baseType = baseType.BaseType) { + FieldInfo[] declFields = baseType.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.DeclaredOnly); + Array.Sort(declFields, (a,b) => a.Name.CompareTo(b.Name)); + fields.AddRange(declFields); + } + fields.RemoveAll(f => f.IsNotSerialized); + return fields; + } + + static bool IsReferenceOrContainsReferences(Type type) + { + if (!type.IsValueType) + return true; + if (type.IsPrimitive) + return false; + foreach (FieldInfo field in GetSerializableFields(type)) { + if (IsReferenceOrContainsReferences(field.FieldType)) + return true; + } + return false; + } + #endregion + + #region Object Writers + delegate void ObjectWriter(SerializationContext context, object instance); + + static readonly MethodInfo writeObjectID = typeof(SerializationContext).GetMethod("WriteObjectID", new[] { typeof(object) }); + + static readonly MethodInfo writeByte = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(byte) }); + static readonly MethodInfo writeShort = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(short) }); + static readonly MethodInfo writeInt = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(int) }); + static readonly MethodInfo writeLong = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(long) }); + static readonly MethodInfo writeFloat = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(float) }); + static readonly MethodInfo writeDouble = typeof(BinaryWriter).GetMethod("Write", new[] { typeof(double) }); + OpCode callVirt = OpCodes.Callvirt; + + static readonly ObjectWriter serializationInfoWriter = delegate(SerializationContext context, object instance) { + BinaryWriter writer = context.writer; + SerializationInfo info = (SerializationInfo)instance; + writer.Write(info.MemberCount); + foreach (SerializationEntry entry in info) { + writer.Write(entry.Name); + context.WriteObjectID(entry.Value); + } + }; + + Dictionary writers = new Dictionary(); + + ObjectWriter GetWriter(Type type) + { + ObjectWriter writer; + if (!writers.TryGetValue(type, out writer)) { + writer = CreateWriter(type); + writers.Add(type, writer); + } + return writer; + } + + ObjectWriter CreateWriter(Type type) + { + if (type == typeof(string)) { + // String contents are written in the object creation section, + // not into the field value section. + return delegate {}; + } + bool isArray = type.IsArray; + if (isArray) { + if (type.GetArrayRank() != 1) + throw new NotImplementedException(); + type = type.GetElementType(); + if (!type.IsValueType) { + return delegate (SerializationContext context, object array) { + foreach (object val in (object[])array) { + context.WriteObjectID(val); + } + }; + } else if (type == typeof(byte[])) { + return delegate (SerializationContext context, object array) { + context.writer.Write((byte[])array); + }; + } + } + List fields = GetSerializableFields(type); + if (fields.Count == 0) { + // The writer has nothing to do for this object. + return delegate { }; + } + + + DynamicMethod dynamicMethod = new DynamicMethod( + (isArray ? "WriteArray_" : "Write_") + type.Name, + typeof(void), new [] { typeof(SerializationContext), typeof(object) }, + true); + ILGenerator il = dynamicMethod.GetILGenerator(); + + var writer = il.DeclareLocal(typeof(BinaryWriter)); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldfld, writerField); + il.Emit(OpCodes.Stloc, writer); // writer = context.writer; + + if (isArray) { + var instance = il.DeclareLocal(type.MakeArrayType()); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Castclass, type.MakeArrayType()); + il.Emit(OpCodes.Stloc, instance); // instance = (type[])arg_1; + + // for (int i = 0; i < instance.Length; i++) write instance[i]; + + var loopStart = il.DefineLabel(); + var loopHead = il.DefineLabel(); + var loopVariable = il.DeclareLocal(typeof(int)); + il.Emit(OpCodes.Ldc_I4_0); + il.Emit(OpCodes.Stloc, loopVariable); // loopVariable = 0 + il.Emit(OpCodes.Br, loopHead); // goto loopHead; + + il.MarkLabel(loopStart); + + if (type.IsEnum || type.IsPrimitive) { + if (type.IsEnum) { + type = type.GetEnumUnderlyingType(); + } + Debug.Assert(type.IsPrimitive); + il.Emit(OpCodes.Ldloc, writer); // writer + il.Emit(OpCodes.Ldloc, instance); // writer, instance + il.Emit(OpCodes.Ldloc, loopVariable); // writer, instance, loopVariable + switch (Type.GetTypeCode(type)) { + case TypeCode.Boolean: + case TypeCode.SByte: + case TypeCode.Byte: + il.Emit(OpCodes.Ldelem_I1); // writer, instance[loopVariable] + il.Emit(callVirt, writeByte); // writer.Write(instance[loopVariable]); + break; + case TypeCode.Char: + case TypeCode.Int16: + case TypeCode.UInt16: + il.Emit(OpCodes.Ldelem_I2); // writer, instance[loopVariable] + il.Emit(callVirt, writeShort); // writer.Write(instance[loopVariable]); + break; + case TypeCode.Int32: + case TypeCode.UInt32: + il.Emit(OpCodes.Ldelem_I4); // writer, instance[loopVariable] + il.Emit(callVirt, writeInt); // writer.Write(instance[loopVariable]); + break; + case TypeCode.Int64: + case TypeCode.UInt64: + il.Emit(OpCodes.Ldelem_I8); // writer, instance[loopVariable] + il.Emit(callVirt, writeLong); // writer.Write(instance[loopVariable]); + break; + case TypeCode.Single: + il.Emit(OpCodes.Ldelem_R4); // writer, instance[loopVariable] + il.Emit(callVirt, writeFloat); // writer.Write(instance[loopVariable]); + break; + case TypeCode.Double: + il.Emit(OpCodes.Ldelem_R8); // writer, instance[loopVariable] + il.Emit(callVirt, writeDouble); // writer.Write(instance[loopVariable]); + break; + default: + throw new NotSupportedException("Unknown primitive type " + type); + } + } else { + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable + il.Emit(OpCodes.Ldelem, type); // instance[loopVariable] + EmitWriteValueType(il, writer, type); + } + + il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable + il.Emit(OpCodes.Ldc_I4_1); // loopVariable, 1 + il.Emit(OpCodes.Add); // loopVariable+1 + il.Emit(OpCodes.Stloc, loopVariable); // loopVariable++; + + il.MarkLabel(loopHead); + il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable + il.Emit(OpCodes.Ldloc, instance); // loopVariable, instance + il.Emit(OpCodes.Ldlen); // loopVariable, instance.Length + il.Emit(OpCodes.Conv_I4); + il.Emit(OpCodes.Blt, loopStart); // if (loopVariable < instance.Length) goto loopStart; + } else if (type.IsValueType) { + // boxed value type + if (type.IsEnum || type.IsPrimitive) { + il.Emit(OpCodes.Ldloc, writer); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Unbox_Any, type); + WritePrimitiveValue(il, type); + } else { + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Unbox_Any, type); + EmitWriteValueType(il, writer, type); + } + } else { + // reference type + var instance = il.DeclareLocal(type); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Castclass, type); + il.Emit(OpCodes.Stloc, instance); // instance = (type)arg_1; + + foreach (FieldInfo field in fields) { + EmitWriteField(il, writer, instance, field); // write instance.Field + } + } + il.Emit(OpCodes.Ret); + return (ObjectWriter)dynamicMethod.CreateDelegate(typeof(ObjectWriter)); + } + + /// + /// Emit 'write instance.Field'. + /// Stack transition: ... => ... + /// + void EmitWriteField(ILGenerator il, LocalBuilder writer, LocalBuilder instance, FieldInfo field) + { + Type fieldType = field.FieldType; + if (fieldType.IsValueType) { + if (fieldType.IsPrimitive || fieldType.IsEnum) { + il.Emit(OpCodes.Ldloc, writer); // writer + il.Emit(OpCodes.Ldloc, instance); // writer, instance + il.Emit(OpCodes.Ldfld, field); // writer, instance.field + WritePrimitiveValue(il, fieldType); + } else { + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldfld, field); // instance.field + EmitWriteValueType(il, writer, fieldType); + } + } else { + il.Emit(OpCodes.Ldarg_0); // context + il.Emit(OpCodes.Ldloc, instance); // context, instance + il.Emit(OpCodes.Ldfld, field); // context, instance.field + il.Emit(OpCodes.Call, writeObjectID); // context.WriteObjectID(instance.field); + } + } + + /// + /// Writes a primitive value of the specified type. + /// Stack transition: ..., writer, value => ... + /// + void WritePrimitiveValue(ILGenerator il, Type fieldType) + { + if (fieldType.IsEnum) { + fieldType = fieldType.GetEnumUnderlyingType(); + Debug.Assert(fieldType.IsPrimitive); + } + switch (Type.GetTypeCode(fieldType)) { + case TypeCode.Boolean: + case TypeCode.SByte: + case TypeCode.Byte: + il.Emit(callVirt, writeByte); // writer.Write(value); + break; + case TypeCode.Char: + case TypeCode.Int16: + case TypeCode.UInt16: + il.Emit(callVirt, writeShort); // writer.Write(value); + break; + case TypeCode.Int32: + case TypeCode.UInt32: + il.Emit(callVirt, writeInt); // writer.Write(value); + break; + case TypeCode.Int64: + case TypeCode.UInt64: + il.Emit(callVirt, writeLong); // writer.Write(value); + break; + case TypeCode.Single: + il.Emit(callVirt, writeFloat); // writer.Write(value); + break; + case TypeCode.Double: + il.Emit(callVirt, writeDouble); // writer.Write(value); + break; + default: + throw new NotSupportedException("Unknown primitive type " + fieldType); + } + } + + /// + /// Stack transition: ..., value => ... + /// + void EmitWriteValueType(ILGenerator il, LocalBuilder writer, Type valType) + { + Debug.Assert(valType.IsValueType); + Debug.Assert(!(valType.IsEnum || valType.IsPrimitive)); + + var fieldVal = il.DeclareLocal(valType); + il.Emit(OpCodes.Stloc, fieldVal); + + foreach (FieldInfo field in GetSerializableFields(valType)) { + EmitWriteField(il, writer, fieldVal, field); + } + } + #endregion + + StreamingContext streamingContext = new StreamingContext(StreamingContextStates.All); + FormatterConverter formatterConverter = new FormatterConverter(); + + public void Serialize(Stream stream, object instance) + { + Serialize(new BinaryWriter(stream), instance); + } + + public void Serialize(BinaryWriter writer, object instance) + { + SerializationContext context = new SerializationContext(this, writer); + context.Mark(instance); + context.Scan(); + context.ScanTypes(); + context.Write(); + } + + delegate void TypeSerializer(object instance, SerializationContext context); + #endregion + + #region Deserialization + sealed class DeserializationContext + { + public Type[] Types; // index: type ID + public ObjectReader[] ObjectReaders; // index: type ID + + public object[] Objects; // index: object ID + + public BinaryReader Reader; + + public object ReadObject() + { + if (this.Objects.Length <= ushort.MaxValue) + return this.Objects[Reader.ReadUInt16()]; + else + return this.Objects[Reader.ReadInt32()]; + } + + #region DeserializeTypeDescriptions + internal int ReadFieldTypeID() + { + if (this.Types.Length <= ushort.MaxValue) + return Reader.ReadUInt16(); + else + return Reader.ReadInt32(); + } + + internal void DeserializeTypeDescriptions(FastSerializer fastSerializer) + { + for (int i = 0; i < this.Types.Length; i++) { + Type type = this.Types[i]; + bool isCustomSerialization = typeof(ISerializable).IsAssignableFrom(type); + bool typeIsSpecial = type.IsArray || type.IsPrimitive || isCustomSerialization; + + byte serializedFieldCount = Reader.ReadByte(); + if (serializedFieldCount == byte.MaxValue) { + // special type + if (!typeIsSpecial) + throw new SerializationException("Type " + type + " was serialized as special type, but isn't special now."); + } else { + if (typeIsSpecial) + throw new SerializationException("Type " + type.FullName + " wasn't serialized as special type, but is special now."); + + var availableFields = GetSerializableFields(this.Types[i]); + if (availableFields.Count != serializedFieldCount) + throw new SerializationException("Number of fields on " + type.FullName + " has changed."); + for (int j = 0; j < serializedFieldCount; j++) { + int fieldTypeID = ReadFieldTypeID(); + + string fieldName = Reader.ReadString(); + FieldInfo fieldInfo = availableFields[j]; + if (fieldInfo.Name != fieldName) + throw new SerializationException("Field mismatch on type " + type.FullName); + if (fieldInfo.FieldType != this.Types[fieldTypeID]) + throw new SerializationException(type.FullName + "." + fieldName + " was serialized as " + this.Types[fieldTypeID] + ", but now is " + fieldInfo.FieldType); + } + } + + if (i < this.ObjectReaders.Length && !isCustomSerialization) + this.ObjectReaders[i] = fastSerializer.GetReader(type); + } + } + #endregion + } + + delegate void ObjectReader(DeserializationContext context, object instance); + + public object Deserialize(Stream stream) + { + return Deserialize(new BinaryReader(stream)); + } + + public object Deserialize(BinaryReader reader) + { + DeserializationContext context = new DeserializationContext(); + context.Reader = reader; + context.Types = new Type[reader.ReadInt32()]; + context.Objects = new object[reader.ReadInt32()]; + context.ObjectReaders = new ObjectReader[reader.ReadInt32()]; + int stringTypeID = reader.ReadInt32(); + for (int i = 0; i < context.Types.Length; i++) { + string typeName = reader.ReadString(); + Type type = Type.GetType(typeName); + if (type == null) + throw new SerializationException("Could not find " + typeName); + context.Types[i] = type; + } + context.DeserializeTypeDescriptions(this); + int[] typeIDByObjectID = new int[context.Objects.Length]; + for (int i = 1; i < context.Objects.Length; i++) { + int typeID = context.ReadFieldTypeID(); + + object instance; + if (typeID == stringTypeID) { + instance = reader.ReadString(); + } else { + Type type = context.Types[typeID]; + if (type.IsArray) { + int length = reader.ReadInt32(); + instance = Array.CreateInstance(type.GetElementType(), length); + } else { + instance = FormatterServices.GetUninitializedObject(type); + } + } + context.Objects[i] = instance; + typeIDByObjectID[i] = typeID; + } + List customDeserializatons = new List(); + for (int i = 1; i < context.Objects.Length; i++) { + object instance = context.Objects[i]; + int typeID = typeIDByObjectID[i]; + Log("0x{2:x6} Read #{0}: {1}", i, context.Types[typeID].Name, reader.BaseStream.Position); + ISerializable serializable = instance as ISerializable; + if (serializable != null) { + Type type = context.Types[typeID]; + SerializationInfo info = new SerializationInfo(type, formatterConverter); + int count = reader.ReadInt32(); + for (int j = 0; j < count; j++) { + string name = reader.ReadString(); + object val = context.ReadObject(); + info.AddValue(name, val); + } + CustomDeserializationAction action = GetCustomDeserializationAction(type); + customDeserializatons.Add(new CustomDeserialization(instance, info, action)); + } else { + context.ObjectReaders[typeID](context, instance); + } + } + Log("File was read successfully, now running {0} custom deserializations...", customDeserializatons.Count); + foreach (CustomDeserialization customDeserializaton in customDeserializatons) { + customDeserializaton.Run(streamingContext); + } + for (int i = 1; i < context.Objects.Length; i++) { + IDeserializationCallback dc = context.Objects[i] as IDeserializationCallback; + if (dc != null) + dc.OnDeserialization(null); + } + + if (context.Objects.Length <= 1) + return null; + else + return context.Objects[1]; + } + + #region Object Reader + static readonly FieldInfo readerField = typeof(DeserializationContext).GetField("Reader"); + static readonly MethodInfo readObject = typeof(DeserializationContext).GetMethod("ReadObject"); + + static readonly MethodInfo readByte = typeof(BinaryReader).GetMethod("ReadByte"); + static readonly MethodInfo readShort = typeof(BinaryReader).GetMethod("ReadInt16"); + static readonly MethodInfo readInt = typeof(BinaryReader).GetMethod("ReadInt32"); + static readonly MethodInfo readLong = typeof(BinaryReader).GetMethod("ReadInt64"); + static readonly MethodInfo readFloat = typeof(BinaryReader).GetMethod("ReadSingle"); + static readonly MethodInfo readDouble = typeof(BinaryReader).GetMethod("ReadDouble"); + + Dictionary readers = new Dictionary(); + + ObjectReader GetReader(Type type) + { + ObjectReader reader; + if (!readers.TryGetValue(type, out reader)) { + reader = CreateReader(type); + readers.Add(type, reader); + } + return reader; + } + + ObjectReader CreateReader(Type type) + { + if (type == typeof(string)) { + // String contents are written in the object creation section, + // not into the field value section; so there's nothing to read here. + return delegate {}; + } + bool isArray = type.IsArray; + if (isArray) { + if (type.GetArrayRank() != 1) + throw new NotImplementedException(); + type = type.GetElementType(); + if (!type.IsValueType) { + return delegate (DeserializationContext context, object arrayInstance) { + object[] array = (object[])arrayInstance; + for (int i = 0; i < array.Length; i++) { + array[i] = context.ReadObject(); + } + }; + } else if (type == typeof(byte[])) { + return delegate (DeserializationContext context, object arrayInstance) { + byte[] array = (byte[])arrayInstance; + BinaryReader binaryReader = context.Reader; + int pos = 0; + int bytesRead; + do { + bytesRead = binaryReader.Read(array, pos, array.Length - pos); + pos += bytesRead; + } while (bytesRead > 0); + if (pos != array.Length) + throw new EndOfStreamException(); + }; + } + } + var fields = GetSerializableFields(type); + if (fields.Count == 0) { + // The reader has nothing to do for this object. + return delegate { }; + } + + DynamicMethod dynamicMethod = new DynamicMethod( + (isArray ? "ReadArray_" : "Read_") + type.Name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + typeof(void), new [] { typeof(DeserializationContext), typeof(object) }, + type, + true); + ILGenerator il = dynamicMethod.GetILGenerator(); + + var reader = il.DeclareLocal(typeof(BinaryReader)); + + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldfld, readerField); + il.Emit(OpCodes.Stloc, reader); // reader = context.reader; + + if (isArray) { + var instance = il.DeclareLocal(type.MakeArrayType()); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Castclass, type.MakeArrayType()); + il.Emit(OpCodes.Stloc, instance); // instance = (type[])arg_1; + + // for (int i = 0; i < instance.Length; i++) read &instance[i]; + + var loopStart = il.DefineLabel(); + var loopHead = il.DefineLabel(); + var loopVariable = il.DeclareLocal(typeof(int)); + il.Emit(OpCodes.Ldc_I4_0); + il.Emit(OpCodes.Stloc, loopVariable); // loopVariable = 0 + il.Emit(OpCodes.Br, loopHead); // goto loopHead; + + il.MarkLabel(loopStart); + + if (type.IsEnum || type.IsPrimitive) { + if (type.IsEnum) { + type = type.GetEnumUnderlyingType(); + } + Debug.Assert(type.IsPrimitive); + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable + EmitReadValueType(il, reader, type); // instance, loopVariable, value + switch (Type.GetTypeCode(type)) { + case TypeCode.Boolean: + case TypeCode.SByte: + case TypeCode.Byte: + il.Emit(OpCodes.Stelem_I1); // instance[loopVariable] = value; + break; + case TypeCode.Char: + case TypeCode.Int16: + case TypeCode.UInt16: + il.Emit(OpCodes.Stelem_I2); // instance[loopVariable] = value; + break; + case TypeCode.Int32: + case TypeCode.UInt32: + il.Emit(OpCodes.Stelem_I4); // instance[loopVariable] = value; + break; + case TypeCode.Int64: + case TypeCode.UInt64: + il.Emit(OpCodes.Stelem_I8); // instance[loopVariable] = value; + break; + case TypeCode.Single: + il.Emit(OpCodes.Stelem_R4); // instance[loopVariable] = value; + break; + case TypeCode.Double: + il.Emit(OpCodes.Stelem_R8); // instance[loopVariable] = value; + break; + default: + throw new NotSupportedException("Unknown primitive type " + type); + } + } else { + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldloc, loopVariable); // instance, loopVariable + il.Emit(OpCodes.Ldelema, type); // instance[loopVariable] + EmitReadValueType(il, reader, type); + } + + il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable + il.Emit(OpCodes.Ldc_I4_1); // loopVariable, 1 + il.Emit(OpCodes.Add); // loopVariable+1 + il.Emit(OpCodes.Stloc, loopVariable); // loopVariable++; + + il.MarkLabel(loopHead); + il.Emit(OpCodes.Ldloc, loopVariable); // loopVariable + il.Emit(OpCodes.Ldloc, instance); // loopVariable, instance + il.Emit(OpCodes.Ldlen); // loopVariable, instance.Length + il.Emit(OpCodes.Conv_I4); + il.Emit(OpCodes.Blt, loopStart); // if (loopVariable < instance.Length) goto loopStart; + } else if (type.IsValueType) { + // boxed value type + il.Emit(OpCodes.Ldarg_1); // instance + il.Emit(OpCodes.Unbox, type); // &(Type)instance + if (type.IsEnum || type.IsPrimitive) { + if (type.IsEnum) { + type = type.GetEnumUnderlyingType(); + } + Debug.Assert(type.IsPrimitive); + ReadPrimitiveValue(il, reader, type); // &(Type)instance, value + switch (Type.GetTypeCode(type)) { + case TypeCode.Boolean: + case TypeCode.SByte: + case TypeCode.Byte: + il.Emit(OpCodes.Stind_I1); + break; + case TypeCode.Char: + case TypeCode.Int16: + case TypeCode.UInt16: + il.Emit(OpCodes.Stind_I2); + break; + case TypeCode.Int32: + case TypeCode.UInt32: + il.Emit(OpCodes.Stind_I4); + break; + case TypeCode.Int64: + case TypeCode.UInt64: + il.Emit(OpCodes.Stind_I8); + break; + case TypeCode.Single: + il.Emit(OpCodes.Stind_R4); + break; + case TypeCode.Double: + il.Emit(OpCodes.Stind_R8); + break; + default: + throw new NotSupportedException("Unknown primitive type " + type); + } + } else { + EmitReadValueType(il, reader, type); + } + } else { + // reference type + var instance = il.DeclareLocal(type); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Castclass, type); + il.Emit(OpCodes.Stloc, instance); // instance = (type)arg_1; + + foreach (FieldInfo field in fields) { + EmitReadField(il, reader, instance, field); // read instance.Field + } + } + il.Emit(OpCodes.Ret); + return (ObjectReader)dynamicMethod.CreateDelegate(typeof(ObjectReader)); + } + + void EmitReadField(ILGenerator il, LocalBuilder reader, LocalBuilder instance, FieldInfo field) + { + Type fieldType = field.FieldType; + if (fieldType.IsValueType) { + if (fieldType.IsPrimitive || fieldType.IsEnum) { + il.Emit(OpCodes.Ldloc, instance); // instance + ReadPrimitiveValue(il, reader, fieldType); // instance, value + il.Emit(OpCodes.Stfld, field); // instance.field = value; + } else { + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldflda, field); // &instance.field + EmitReadValueType(il, reader, fieldType); + } + } else { + il.Emit(OpCodes.Ldloc, instance); // instance + il.Emit(OpCodes.Ldarg_0); // instance, context + il.Emit(OpCodes.Call, readObject); // instance, context.ReadObject() + il.Emit(OpCodes.Stfld, field); // instance.field = context.ReadObject(); + } + } + + /// + /// Reads a primitive value of the specified type. + /// Stack transition: ... => ..., value + /// + void ReadPrimitiveValue(ILGenerator il, LocalBuilder reader, Type fieldType) + { + if (fieldType.IsEnum) { + fieldType = fieldType.GetEnumUnderlyingType(); + Debug.Assert(fieldType.IsPrimitive); + } + il.Emit(OpCodes.Ldloc, reader); + switch (Type.GetTypeCode(fieldType)) { + case TypeCode.Boolean: + case TypeCode.SByte: + case TypeCode.Byte: + il.Emit(callVirt, readByte); + break; + case TypeCode.Char: + case TypeCode.Int16: + case TypeCode.UInt16: + il.Emit(callVirt, readShort); + break; + case TypeCode.Int32: + case TypeCode.UInt32: + il.Emit(callVirt, readInt); + break; + case TypeCode.Int64: + case TypeCode.UInt64: + il.Emit(callVirt, readLong); + break; + case TypeCode.Single: + il.Emit(callVirt, readFloat); + break; + case TypeCode.Double: + il.Emit(callVirt, readDouble); + break; + default: + throw new NotSupportedException("Unknown primitive type " + fieldType); + } + } + + /// + /// Stack transition: ..., field-ref => ... + /// + void EmitReadValueType(ILGenerator il, LocalBuilder reader, Type valType) + { + Debug.Assert(valType.IsValueType); + Debug.Assert(!(valType.IsEnum || valType.IsPrimitive)); + + var fieldRef = il.DeclareLocal(valType.MakeByRefType()); + il.Emit(OpCodes.Stloc, fieldRef); + + foreach (FieldInfo field in GetSerializableFields(valType)) { + EmitReadField(il, reader, fieldRef, field); + } + } + #endregion + + #region Custom Deserialization + struct CustomDeserialization + { + readonly object instance; + readonly SerializationInfo serializationInfo; + readonly CustomDeserializationAction action; + + public CustomDeserialization(object instance, SerializationInfo serializationInfo, CustomDeserializationAction action) + { + this.instance = instance; + this.serializationInfo = serializationInfo; + this.action = action; + } + + public void Run(StreamingContext context) + { + action(instance, serializationInfo, context); + } + } + + delegate void CustomDeserializationAction(object instance, SerializationInfo info, StreamingContext context); + + Dictionary customDeserializationActions = new Dictionary(); + + CustomDeserializationAction GetCustomDeserializationAction(Type type) + { + CustomDeserializationAction action; + if (!customDeserializationActions.TryGetValue(type, out action)) { + action = CreateCustomDeserializationAction(type); + customDeserializationActions.Add(type, action); + } + return action; + } + + CustomDeserializationAction CreateCustomDeserializationAction(Type type) + { + ConstructorInfo ctor = type.GetConstructor( + BindingFlags.DeclaredOnly | BindingFlags.ExactBinding | BindingFlags.Instance + | BindingFlags.NonPublic | BindingFlags.Public, + null, + new Type [] { typeof(SerializationInfo), typeof(StreamingContext) }, + null); + if (ctor == null) + throw new SerializationException("Could not find deserialization constructor for " + type.FullName); + + DynamicMethod dynamicMethod = new DynamicMethod( + "CallCtor_" + type.Name, + MethodAttributes.Public | MethodAttributes.Static, + CallingConventions.Standard, + typeof(void), new [] { typeof(object), typeof(SerializationInfo), typeof(StreamingContext) }, + type, + true); + ILGenerator il = dynamicMethod.GetILGenerator(); + il.Emit(OpCodes.Ldarg_0); + il.Emit(OpCodes.Ldarg_1); + il.Emit(OpCodes.Ldarg_2); + il.Emit(OpCodes.Call, ctor); + il.Emit(OpCodes.Ret); + return (CustomDeserializationAction)dynamicMethod.CreateDelegate(typeof(CustomDeserializationAction)); + } + #endregion + #endregion + + [Conditional("DEBUG_SERIALIZER")] + static void Log(string format, params object[] args) + { + Debug.WriteLine(format, args); + } + } +} From 36c412d310f6951de01a470b4d053464b1cf997d Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 15 Aug 2011 14:52:12 +0200 Subject: [PATCH 07/15] Allow serializing SimpleProjectContent and parsed C# type references. --- .../Parser/TypeSystemConvertVisitorTests.cs | 15 +++++ .../CSharp/Parser/ParsedFile.cs | 1 + .../Resolver/AliasNamespaceReference.cs | 1 + .../CSharp/Resolver/CSharpAttribute.cs | 2 + .../CSharp/Resolver/ConstantValues.cs | 13 +++++ .../MemberTypeOrNamespaceReference.cs | 1 + .../SimpleTypeOrNamespaceReference.cs | 1 + .../CSharp/Resolver/UsingScope.cs | 1 + .../TypeSystem/CecilLoader.cs | 28 ++++++++++ ICSharpCode.NRefactory/TypeSystem/Error.cs | 31 ++++++----- .../TypeSystem/IAnnotatable.cs | 1 - .../Implementation/ProxyTypeResolveContext.cs | 2 +- .../Implementation/SimpleProjectContent.cs | 55 ++++++++++++++++++- .../TypeSystem/Implementation/TypeStorage.cs | 3 +- 14 files changed, 137 insertions(+), 18 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index 96a2899ca0..a5869b5a27 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -51,4 +51,19 @@ namespace ICSharpCode.NRefactory.CSharp.Parser return testCasePC; } } + + [TestFixture] + public class SerializedTypeSystemConvertVisitorTests : TypeSystemTests + { + [TestFixtureSetUp] + public void FixtureSetUp() + { + FastSerializer serializer = new FastSerializer(); + using (MemoryStream ms = new MemoryStream()) { + serializer.Serialize(ms, TypeSystemConvertVisitorTests.ParseTestCase()); + ms.Position = 0; + testCasePC = (IProjectContent)serializer.Deserialize(ms); + } + } + } } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs b/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs index b009dde7df..12902b4afa 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs @@ -27,6 +27,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Represents a file that was parsed and converted for the type system. /// + [Serializable] public sealed class ParsedFile : AbstractFreezable, IParsedFile { readonly string fileName; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs index 603e47c9e8..6777d8da34 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs @@ -28,6 +28,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// The member lookup performed by the :: operator is handled /// by . /// + [Serializable] public class AliasNamespaceReference : ITypeOrNamespaceReference { readonly UsingScope parentUsingScope; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs index 143cdd3b5d..c3b47e51fc 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs @@ -24,6 +24,7 @@ using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.CSharp.Resolver { + [Serializable] public sealed class CSharpAttribute : Immutable, IAttribute { ITypeReference attributeType; @@ -128,6 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// Type reference used within an attribute. /// Looks up both 'withoutSuffix' and 'withSuffix' and returns the type that exists. /// + [Serializable] public sealed class AttributeTypeReference : ITypeReference, ISupportsInterning { ITypeReference withoutSuffix, withSuffix; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs index 701384519b..d163e8ad53 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs @@ -29,6 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues // Contains representations for constant C# expressions. // We use these instead of storing the full AST to reduce the memory usage. + [Serializable] public sealed class CSharpConstantValue : Immutable, IConstantValue, ISupportsInterning { ConstantExpression expression; @@ -125,6 +126,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// /// Increments an integer by a fixed amount without changing the type. /// + [Serializable] public sealed class IncrementConstantValue : Immutable, IConstantValue, ISupportsInterning { IConstantValue baseValue; @@ -178,6 +180,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public abstract class ConstantExpression { public abstract ResolveResult Resolve(CSharpResolver resolver); @@ -186,6 +189,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// /// C#'s equivalent to the SimpleConstantValue. /// + [Serializable] public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning { ITypeReference type; @@ -233,6 +237,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantCast : ConstantExpression, ISupportsInterning { ITypeReference targetType; @@ -274,6 +279,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantIdentifierReference : ConstantExpression, ISupportsInterning { string identifier; @@ -327,6 +333,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning { ITypeReference targetType; @@ -398,6 +405,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantCheckedExpression : ConstantExpression, ISupportsInterning { bool checkForOverflow; @@ -441,6 +449,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning { ITypeReference type; @@ -474,6 +483,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantUnaryOperator : ConstantExpression, ISupportsInterning { UnaryOperatorType operatorType; @@ -513,6 +523,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantBinaryOperator : ConstantExpression, ISupportsInterning { ConstantExpression left; @@ -559,6 +570,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantConditionalOperator : ConstantExpression, ISupportsInterning { ConstantExpression condition, trueExpr, falseExpr; @@ -614,6 +626,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// /// Represents an array creation (as used within an attribute argument) /// + [Serializable] public sealed class ConstantArrayCreation : ConstantExpression, ISupportsInterning { // type may be null when the element is being inferred diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs index ac1828efed..5ad2ea39e1 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Reference to a qualified type or namespace name. /// + [Serializable] public sealed class MemberTypeOrNamespaceReference : ITypeOrNamespaceReference { readonly ITypeOrNamespaceReference target; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs index e770931df0..631a1fbd5d 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs @@ -25,6 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Represents a simple C# name. (a single non-qualified identifier with an optional list of type arguments) /// + [Serializable] public sealed class SimpleTypeOrNamespaceReference : ITypeOrNamespaceReference { readonly ITypeDefinition parentTypeDefinition; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs b/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs index fa6212b5e0..7a933459d0 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs @@ -28,6 +28,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// Represents a scope that contains "using" statements. /// This is either the file itself, or a namespace declaration. /// + [Serializable] public class UsingScope : AbstractFreezable { readonly IProjectContent projectContent; diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index 0bdb727d61..bee93e7689 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -23,6 +23,7 @@ using System.Diagnostics; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Runtime.Serialization; using System.Threading; using ICSharpCode.NRefactory.TypeSystem.Implementation; using Mono.Cecil; @@ -234,6 +235,33 @@ namespace ICSharpCode.NRefactory.TypeSystem else return null; } + + IEnumerable IAnnotatable.Annotations { + get { return EmptyList.Instance; } + } + + T IAnnotatable.Annotation() + { + return null; + } + + object IAnnotatable.Annotation(Type type) + { + return null; + } + + void IAnnotatable.AddAnnotation(object annotation) + { + throw new NotSupportedException(); + } + + void IAnnotatable.RemoveAnnotations() + { + } + + void IAnnotatable.RemoveAnnotations(Type type) + { + } } #endregion diff --git a/ICSharpCode.NRefactory/TypeSystem/Error.cs b/ICSharpCode.NRefactory/TypeSystem/Error.cs index 1684e8d81c..7487f12fc5 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Error.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Error.cs @@ -1,4 +1,4 @@ -// +// // Error.cs // // Author: @@ -42,22 +42,27 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Descibes an error during parsing. /// + [Serializable] public class Error { + readonly ErrorType errorType; + readonly string message; + readonly DomRegion region; + /// /// The type of the error. /// - public ErrorType ErrorType { get; private set; } + public ErrorType ErrorType { get { return errorType; } } /// /// The error description. /// - public string Message { get; private set; } + public string Message { get { return message; } } /// /// The region of the error. /// - public DomRegion Region { get; private set; } + public DomRegion Region { get { return region; } } /// /// Initializes a new instance of the class. @@ -73,9 +78,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public Error (ErrorType errorType, string message, DomRegion region) { - this.ErrorType = errorType; - this.Message = message; - this.Region = region; + this.errorType = errorType; + this.message = message; + this.region = region; } /// @@ -92,9 +97,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public Error (ErrorType errorType, string message, AstLocation location) { - this.ErrorType = errorType; - this.Message = message; - this.Region = new DomRegion (location, location); + this.errorType = errorType; + this.message = message; + this.region = new DomRegion (location, location); } /// @@ -127,9 +132,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public Error (ErrorType errorType, string message) { - this.ErrorType = errorType; - this.Message = message; - this.Region = DomRegion.Empty; + this.errorType = errorType; + this.message = message; + this.region = DomRegion.Empty; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs index ff30f87443..2021496969 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs @@ -78,7 +78,6 @@ namespace ICSharpCode.NRefactory void RemoveAnnotations(Type type); } - [Serializable] public abstract class AbstractAnnotatable : IAnnotatable { // Annotations: points either null (no annotations), to the single annotation, diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs index 898c98077b..e9612d1f8c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs @@ -26,7 +26,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Useful as base class for decorators. /// [Serializable] - public class ProxyTypeResolveContext : AbstractAnnotatable, ITypeResolveContext + public class ProxyTypeResolveContext : ITypeResolveContext { protected readonly ITypeResolveContext target; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs index e288260245..c00daf635d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs @@ -20,8 +20,8 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; +using System.Runtime.Serialization; using System.Threading; - using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -34,12 +34,22 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Compared with , this class adds support for the IProjectContent interface, /// for partial classes, and for multi-threading. /// - public class SimpleProjectContent : AbstractAnnotatable, IProjectContent + [Serializable] + public class SimpleProjectContent : AbstractAnnotatable, IProjectContent, ISerializable, IDeserializationCallback { readonly TypeStorage types = new TypeStorage(); readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(); readonly Dictionary fileDict = new Dictionary(Platform.FileNameComparer); + #region Constructor + /// + /// Creates a new SimpleProjectContent instance. + /// + public SimpleProjectContent() + { + } + #endregion + #region AssemblyAttributes readonly List assemblyAttributes = new List(); // mutable assembly attribute storage readonly List moduleAttributes = new List(); @@ -284,5 +294,46 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } #endregion + + #region Serialization + SerializationInfo serializationInfo; + + protected SimpleProjectContent(SerializationInfo info, StreamingContext context) + { + this.serializationInfo = info; + assemblyAttributes.AddRange((IAttribute[])info.GetValue("AssemblyAttributes", typeof(IAttribute[]))); + readOnlyAssemblyAttributes = assemblyAttributes.ToArray(); + moduleAttributes.AddRange((IAttribute[])info.GetValue("ModuleAttributes", typeof(IAttribute[]))); + readOnlyModuleAttributes = moduleAttributes.ToArray(); + } + + public virtual void OnDeserialization(object sender) + { + // We need to do this in OnDeserialization because at the time the deserialization + // constructor runs, type.FullName/file.FileName may not be deserialized yet. + if (serializationInfo != null) { + foreach (var typeDef in (ITypeDefinition[])serializationInfo.GetValue("Types", typeof(ITypeDefinition[]))) { + types.UpdateType(typeDef); + } + foreach (IParsedFile file in (IParsedFile[])serializationInfo.GetValue("Files", typeof(IParsedFile[]))) { + fileDict.Add(file.FileName, file); + } + serializationInfo = null; + } + } + + public virtual void GetObjectData(SerializationInfo info, StreamingContext context) + { + readerWriterLock.EnterReadLock(); + try { + info.AddValue("Types", types.GetTypes().ToArray()); + info.AddValue("AssemblyAttributes", readOnlyAssemblyAttributes); + info.AddValue("ModuleAttributes", readOnlyModuleAttributes); + info.AddValue("Files", fileDict.Values.ToArray()); + } finally { + readerWriterLock.ExitReadLock(); + } + } + #endregion } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs index 53eb718cef..93d8d46dfe 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs @@ -374,7 +374,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation SerializationInfo serializationInfo; - protected TypeStorage(SerializationInfo info, StreamingContext context) + private TypeStorage(SerializationInfo info, StreamingContext context) { this.serializationInfo = info; } @@ -391,6 +391,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation foreach (var typeDef in (ITypeDefinition[])serializationInfo.GetValue("Types", typeof(ITypeDefinition[]))) { UpdateType(typeDef); } + serializationInfo = null; } #endregion } From 405e87ef2a91d408810045b2e1e6fc47bb9f86f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Mon, 15 Aug 2011 18:41:03 +0200 Subject: [PATCH 08/15] Fixed location bug. --- ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs | 1 - ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay | 1 - 2 files changed, 2 deletions(-) diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs index 8c77d55597..151d483b2c 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs @@ -4151,7 +4151,6 @@ void case_51() attrs = new Attributes (sect); else attrs.AddAttributes (sect); - lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); yyVal = attrs; } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay index 2bf89c9b16..bda42e60bd 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay +++ b/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay @@ -679,7 +679,6 @@ attribute_sections attrs = new Attributes (sect); else attrs.AddAttributes (sect); - lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); $$ = attrs; } ; From 62b9fce4eaa65308987a62d6f63d6af6cc354223 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mike=20Kr=C3=BCger?= Date: Tue, 16 Aug 2011 10:56:56 +0200 Subject: [PATCH 09/15] Always create ArrayInitializerExpressions. --- .../CSharp/Parser/CSharpParser.cs | 37 +++++++++---------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs index 78d003fe7c..acfa24bbf5 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs @@ -2349,28 +2349,25 @@ namespace ICSharpCode.NRefactory.CSharp foreach (var expr in minit.Initializers) { var collectionInit = expr as CollectionElementInitializer; if (collectionInit != null) { - if (collectionInit.Arguments.Count != 1) { - var parent = new ArrayInitializerExpression (); - var braceLocs = LocationsBag.GetLocations (expr); - if (braceLocs != null) - parent.AddChild (new CSharpTokenNode (Convert (braceLocs[0]), 1), ArrayInitializerExpression.Roles.LBrace); - for (int i = 0; i < collectionInit.Arguments.Count; i++) { - var arg = collectionInit.Arguments[i] as CollectionElementInitializer.ElementInitializerArgument; - if (arg == null) - continue; - parent.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); - if (curComma >= 0) - parent.AddChild (new CSharpTokenNode (Convert (commaLoc[curComma--]), 1), ArrayInitializerExpression.Roles.Comma); - } - if (braceLocs != null) - parent.AddChild (new CSharpTokenNode (Convert (braceLocs[1]), 1), ArrayInitializerExpression.Roles.RBrace); - init.AddChild (parent, ArrayInitializerExpression.Roles.Expression); - } else { - var arg = collectionInit.Arguments[0] as CollectionElementInitializer.ElementInitializerArgument; - if (arg != null) - init.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); + var parent = new ArrayInitializerExpression (); + + var braceLocs = LocationsBag.GetLocations (expr); + if (braceLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (braceLocs[0]), 1), ArrayInitializerExpression.Roles.LBrace); + + for (int i = 0; i < collectionInit.Arguments.Count; i++) { + var arg = collectionInit.Arguments[i] as CollectionElementInitializer.ElementInitializerArgument; + if (arg == null) + continue; + parent.AddChild ((ICSharpCode.NRefactory.CSharp.Expression)arg.Expr.Accept (this), ArrayInitializerExpression.Roles.Expression); + if (curComma >= 0) + parent.AddChild (new CSharpTokenNode (Convert (commaLoc[curComma--]), 1), ArrayInitializerExpression.Roles.Comma); } + + if (braceLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (braceLocs[1]), 1), ArrayInitializerExpression.Roles.RBrace); + init.AddChild (parent, ArrayInitializerExpression.Roles.Expression); continue; } From 87992d3e56fa48ac3f9ebaf61cfa3f946bda3b41 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 15 Aug 2011 17:29:23 +0200 Subject: [PATCH 10/15] Fix build for NRefactory.VB. --- .../Visitors/CSharpToVBConverterVisitor.cs | 28 +++++++++---------- .../Utils/FastSerializer.cs | 4 +-- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs index eee8d06377..60ebaa9fd7 100644 --- a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs +++ b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -418,24 +418,24 @@ namespace ICSharpCode.NRefactory.VB.Visitors public AstNode VisitNamedArgumentExpression(CSharp.NamedArgumentExpression namedArgumentExpression, object data) { - Expression expr; - - if (namedArgumentExpression.Parent is CSharp.ArrayInitializerExpression) { - expr = new FieldInitializerExpression { - IsKey = true, - Identifier = namedArgumentExpression.Identifier, - Expression = (Expression)namedArgumentExpression.Expression.AcceptVisitor(this, data) - }; - } else { - expr = new NamedArgumentExpression { - Identifier = namedArgumentExpression.Identifier, - Expression = (Expression)namedArgumentExpression.Expression.AcceptVisitor(this, data) - }; - } + Expression expr = new NamedArgumentExpression { + Identifier = namedArgumentExpression.Identifier, + Expression = (Expression)namedArgumentExpression.Expression.AcceptVisitor(this, data) + }; return EndNode(namedArgumentExpression, expr); } + public AstNode VisitNamedExpression(CSharp.NamedExpression namedExpression, object data) + { + Expression expr = new FieldInitializerExpression { + IsKey = true, + Identifier = namedExpression.Identifier, + Expression = (Expression)namedExpression.Expression.AcceptVisitor(this, data) + }; + return EndNode(namedExpression, expr); + } + public AstNode VisitNullReferenceExpression(CSharp.NullReferenceExpression nullReferenceExpression, object data) { return EndNode(nullReferenceExpression, new PrimitiveExpression(null)); diff --git a/ICSharpCode.NRefactory/Utils/FastSerializer.cs b/ICSharpCode.NRefactory/Utils/FastSerializer.cs index a823c2db1a..0bd3887c6d 100644 --- a/ICSharpCode.NRefactory/Utils/FastSerializer.cs +++ b/ICSharpCode.NRefactory/Utils/FastSerializer.cs @@ -633,7 +633,7 @@ namespace ICSharpCode.NRefactory.Utils public void Serialize(Stream stream, object instance) { - Serialize(new BinaryWriter(stream), instance); + Serialize(new BinaryWriterWith7BitEncodedInts(stream), instance); } public void Serialize(BinaryWriter writer, object instance) @@ -717,7 +717,7 @@ namespace ICSharpCode.NRefactory.Utils public object Deserialize(Stream stream) { - return Deserialize(new BinaryReader(stream)); + return Deserialize(new BinaryReaderWith7BitEncodedInts(stream)); } public object Deserialize(BinaryReader reader) From a5c93a38e4026d674445772b57374f14338bb2a3 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Tue, 16 Aug 2011 13:50:53 +0200 Subject: [PATCH 11/15] Adjust resolver to object initializer AST changes. --- .../Expression/ArrayCreateExpressionTests.cs | 13 ++ .../Expression/AssignmentExpressionTests.cs | 4 +- .../Expression/ObjectCreateExpressionTests.cs | 38 +++-- .../Expression/PrimitiveExpressionTests.cs | 8 ++ .../GeneralScope/AttributeSectionTests.cs | 6 +- .../CSharp/Resolver/LambdaTests.cs | 16 ++- .../CSharp/Resolver/ObjectCreationTests.cs | 15 ++ .../Expressions/ArrayInitializerExpression.cs | 14 ++ .../Ast/Expressions/AssignmentExpression.cs | 6 - .../CSharp/Resolver/CSharpResolver.cs | 54 +++++++ ICSharpCode.NRefactory/CSharp/Resolver/Log.cs | 12 +- .../CSharp/Resolver/ResolveVisitor.cs | 132 +++++++++++++----- .../Properties/AssemblyInfo.cs | 2 +- 13 files changed, 258 insertions(+), 62 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs index b12feae796..2fb3c1ad7d 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs @@ -121,5 +121,18 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression } }}); } + + [Test] + public void AssignmentInArrayInitializer() + { + ParseUtilCSharp.AssertExpression( + "new [] { a = 10 }", + new ArrayCreateExpression { + Initializer = new ArrayInitializerExpression { + Elements = { + new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(10)) + } + }}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs index f0f06b23c4..29156a15b5 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs @@ -105,7 +105,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { ParseUtilCSharp.AssertExpression( "a = b = c", - new AssignmentExpression("a", new AssignmentExpression("b", new IdentifierExpression("c")))); + new AssignmentExpression( + new IdentifierExpression("a"), + new AssignmentExpression(new IdentifierExpression("b"), new IdentifierExpression("c")))); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs index f4796d3fb1..768ae9f395 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs @@ -163,9 +163,9 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression Type = new SimpleType("List", new PrimitiveType("int")), Initializer = new ArrayInitializerExpression { Elements = { - new PrimitiveExpression(0), - new PrimitiveExpression(1), - new PrimitiveExpression(2) + new ArrayInitializerExpression(new PrimitiveExpression(0)), + new ArrayInitializerExpression(new PrimitiveExpression(1)), + new ArrayInitializerExpression(new PrimitiveExpression(2)) }}}); } @@ -204,17 +204,18 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression }", new ObjectCreateExpression { Type = new SimpleType("List", new SimpleType("Contact")), - Initializer = new ArrayInitializerExpression { - Elements = { + Initializer = new ArrayInitializerExpression( + new ArrayInitializerExpression( new ObjectCreateExpression { Type = new SimpleType("Contact"), Initializer = new ArrayInitializerExpression { Elements = { new NamedExpression("Name", new PrimitiveExpression("Chris")), new NamedExpression("PhoneNumbers", new ArrayInitializerExpression () { - Elements = { new PrimitiveExpression("206-555-0101") } + Elements = { new ArrayInitializerExpression(new PrimitiveExpression("206-555-0101")) } }) - }}}, + }}}), + new ArrayInitializerExpression( new ObjectCreateExpression { Type = new SimpleType("Contact"), Arguments = { new IdentifierExpression("additionalParameter") }, @@ -223,11 +224,28 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression new NamedExpression("Name", new PrimitiveExpression("Bob")), new NamedExpression("PhoneNumbers", new ArrayInitializerExpression () { Elements = { - new PrimitiveExpression("650-555-0199"), - new PrimitiveExpression("425-882-8080") + new ArrayInitializerExpression(new PrimitiveExpression("650-555-0199")), + new ArrayInitializerExpression(new PrimitiveExpression("425-882-8080")) } }) - }}} + }}}) + )}); + } + + [Test] + public void AssignmentInCollectionInitializer() + { + ParseUtilCSharp.AssertExpression( + @"new List { { a = 1 } }", + new ObjectCreateExpression { + Type = new SimpleType("List", new PrimitiveType("int")), + Initializer = new ArrayInitializerExpression { + Elements = { + new ArrayInitializerExpression { + Elements = { + new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(1)) + } + } }}}); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs index a2b588c3f5..f91d8ea49e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs @@ -214,5 +214,13 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression CheckLiteral(@"'\x0041'", '\x0041'); CheckLiteral(@"'\U00000041'", '\U00000041'); } + + [Test, Ignore(@"Parser includes \r in integer literal")] + public void TestPositionOfIntegerAtEndOfLine() + { + var pe = ParseUtilCSharp.ParseExpression("0\r\n"); + Assert.AreEqual(new AstLocation(1, 1), pe.StartLocation); + Assert.AreEqual(new AstLocation(1, 2), pe.EndLocation); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs index 346f6d484d..4d2759dc51 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs @@ -154,7 +154,7 @@ public class Form1 { // TODO: Tests for other contexts where attributes can appear - [Test, Ignore("Parser doesn't support named arguments in attributes")] + [Test, Ignore("Parser does not support NamedArgumentExpression in attributes")] public void AttributeWithNamedArguments() { ParseUtilCSharp.AssertTypeMember( @@ -168,8 +168,8 @@ public class Form1 { Type = new SimpleType("A"), Arguments = { new PrimitiveExpression(0), - new NamedArgumentExpression { Identifier = "a", Expression = new PrimitiveExpression(1) }, - new AssignmentExpression(new IdentifierExpression("b"), new PrimitiveExpression(2)) + new NamedArgumentExpression("a", new PrimitiveExpression(1)), + new NamedExpression("b", new PrimitiveExpression(2)) } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 08d844b653..5abde3da4c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -206,7 +206,7 @@ class TestClass { } #endregion - [Test, Ignore("Parser doesn't support object initializers yet")] + [Test] public void LambdaInObjectInitializerTest() { string program = @"using System; @@ -238,6 +238,20 @@ static class TestClass { Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } + [Test] + public void LambdaExpressionInDelegateCreateExpression() + { + string program = @"using System; +static class TestClass { + static void Main(string[] args) { + var f = new Func( i => $i$ ); + } + public delegate R Func(T arg); +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + [Test] public void LambdaExpressionInReturnStatement() { diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs index ee675a179d..bf889c6544 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs @@ -141,5 +141,20 @@ class C : B { mrr = Resolve(program, "this(0)"); Assert.AreEqual("C..ctor", mrr.Member.FullName); } + + [Test] + public void FieldReferenceInObjectInitializer() + { + string program = @"class A { + public int Property; +} +class B { + void Method() { + var x = new A() { $Property = 0$ }; + } +}"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("A.Property", result.Member.FullName); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs index 3c33d4d7b1..92afafe856 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs @@ -33,6 +33,20 @@ namespace ICSharpCode.NRefactory.CSharp /// public class ArrayInitializerExpression : Expression { + public ArrayInitializerExpression() + { + } + + public ArrayInitializerExpression(IEnumerable elements) + { + this.Elements.AddRange(elements); + } + + public ArrayInitializerExpression(params Expression[] elements) + { + this.Elements.AddRange(elements); + } + #region Null public new static readonly ArrayInitializerExpression Null = new NullArrayInitializerExpression (); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs index ae3383fedc..998ab78fb4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs +++ b/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs @@ -48,12 +48,6 @@ namespace ICSharpCode.NRefactory.CSharp this.Right = right; } - public AssignmentExpression(string left, Expression right) - { - this.Left = new IdentifierExpression(left); - this.Right = right; - } - public AssignmentExpression(Expression left, AssignmentOperatorType op, Expression right) { this.Left = left; diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs index 1d073138a6..3a63e9b9d9 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs @@ -269,6 +269,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion + #region Object Initializer Context + sealed class ObjectInitializerContext + { + internal readonly IType type; + internal readonly ObjectInitializerContext prev; + + public ObjectInitializerContext(IType type, CSharpResolver.ObjectInitializerContext prev) + { + this.type = type; + this.prev = prev; + } + } + + ObjectInitializerContext objectInitializerStack; + + /// + /// Pushes the type of the object that is currently being initialized. + /// + public void PushInitializerType(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + objectInitializerStack = new ObjectInitializerContext(type, objectInitializerStack); + } + + public void PopInitializerType() + { + if (objectInitializerStack == null) + throw new InvalidOperationException(); + objectInitializerStack = objectInitializerStack.prev; + } + + /// + /// Gets the type of the object currently being initialized. + /// Returns SharedTypes.Unknown if no object initializer is currently open (or if the object initializer + /// has unknown type). + /// + public IType CurrentObjectInitializerType { + get { return objectInitializerStack != null ? objectInitializerStack.type : SharedTypes.UnknownType; } + } + #endregion + #region Clone /// /// Creates a copy of this CSharp resolver. @@ -2073,6 +2115,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion + #region ResolveIdentifierInObjectInitializer + public ResolveResult ResolveIdentifierInObjectInitializer(string identifier) + { + MemberLookup memberLookup = CreateMemberLookup(); + ResolveResult target = new ResolveResult(this.CurrentObjectInitializerType); + return memberLookup.Lookup(target, identifier, EmptyList.Instance, false); + } + #endregion + #region GetExtensionMethods /// /// Gets the extension methods that are called 'name' @@ -2377,6 +2428,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { cancellationToken.ThrowIfCancellationRequested(); + if (type.Kind == TypeKind.Delegate && arguments.Length == 1) { + return Convert(arguments[0], type); + } OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, new IType[0]); MemberLookup lookup = CreateMemberLookup(); bool allowProtectedAccess = lookup.IsProtectedAccessAllowed(type); diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/Log.cs b/ICSharpCode.NRefactory/CSharp/Resolver/Log.cs index fe0a58bc02..c3d43c2f4d 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/Log.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/Log.cs @@ -35,19 +35,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// static class Log { - [Conditional("DEBUG")] + const bool logEnabled = false; + + [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] internal static void WriteLine(string text) { Debug.WriteLine(text); } - [Conditional("DEBUG")] + [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] internal static void WriteLine(string format, params object[] args) { Debug.WriteLine(format, args); } - [Conditional("DEBUG")] + [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] internal static void WriteCollection(string text, IEnumerable lines) { #if DEBUG @@ -63,13 +65,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endif } - [Conditional("DEBUG")] + [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] public static void Indent() { Debug.Indent(); } - [Conditional("DEBUG")] + [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] public static void Unindent() { Debug.Unindent(); diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs index 76fafc807c..91389da3c3 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -221,6 +221,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver protected override ResolveResult VisitChildren(AstNode node, object data) { + Log.WriteLine("ResolveVisitor: unhandled node " + node.GetType().Name); ScanChildren(node); return null; } @@ -369,7 +370,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver resolver.UsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation); } ScanChildren(namespaceDeclaration); - return new NamespaceResolveResult(resolver.UsingScope.NamespaceName); + if (resolver.UsingScope != null) + return new NamespaceResolveResult(resolver.UsingScope.NamespaceName); + else + return null; } finally { resolver.UsingScope = previousUsingScope; } @@ -751,8 +755,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr) { - if (expr is NamedArgumentExpression) { - var namedArgExpr = (NamedArgumentExpression)expr; + if (expr is NamedExpression) { + var namedArgExpr = (NamedExpression)expr; resolveExpr = namedArgExpr.Expression; return namedArgExpr.Identifier; } @@ -771,29 +775,35 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) { - ScanChildren(anonymousTypeCreateExpression); // 7.6.10.6 Anonymous object creation expressions - var anonymousType = new DefaultTypeDefinition(resolver.CurrentTypeDefinition, "$Anonymous$"); + if (resolver.UsingScope == null) { + ScanChildren(anonymousTypeCreateExpression); + return errorResult; + } + var anonymousType = new DefaultTypeDefinition(resolver.UsingScope.ProjectContent, string.Empty, "$Anonymous$"); anonymousType.IsSynthetic = true; + resolver.PushInitializerType(anonymousType); foreach (var expr in anonymousTypeCreateExpression.Initializers) { Expression resolveExpr; var name = GetAnonymousTypePropertyName(expr, out resolveExpr); - if (string.IsNullOrEmpty(name)) - continue; - - var property = new DefaultProperty(anonymousType, name) { - Accessibility = Accessibility.Public, - ReturnType = new VarTypeReference(this, resolver.Clone(), resolveExpr, false) - }; - anonymousType.Properties.Add(property); + if (!string.IsNullOrEmpty(name)) { + var property = new DefaultProperty(anonymousType, name) { + Accessibility = Accessibility.Public, + ReturnType = new VarTypeReference(this, resolver.Clone(), resolveExpr, false) + }; + anonymousType.Properties.Add(property); + } + Scan(expr); } + ScanChildren(anonymousTypeCreateExpression); + resolver.PopInitializerType(); return new ResolveResult(anonymousType); } public override ResolveResult VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) { - ScanChildren(arrayCreateExpression); if (!resolverEnabled) { + ScanChildren(arrayCreateExpression); return null; } @@ -973,15 +983,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return null; } + // NamedArgumentExpression is "identifier: Expression" public override ResolveResult VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) { - // Usually, the parent expression takes care of handling NamedArgumentExpressions + // The parent expression takes care of handling NamedArgumentExpressions // by calling GetArguments(). - if (resolverEnabled) { - return Resolve(namedArgumentExpression.Expression); + // This method gets called only when scanning, or when the named argument is used + // in an invalid context. + Scan(namedArgumentExpression.Expression); + return errorResult; + } + + // NamedExpression is "identifier = Expression" in object initializers and attributes + public override ResolveResult VisitNamedExpression(NamedExpression namedExpression, object data) + { + Expression rhs = namedExpression.Expression; + if (rhs is ArrayInitializerExpression) { + throw new NotImplementedException(); } else { - Scan(namedArgumentExpression.Expression); - return null; + if (resolverEnabled) { + ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier); + ResolveAndProcessConversion(rhs, result.Type); + return result; + } else { + ScanChildren(namedExpression); + return null; + } } } @@ -996,14 +1023,38 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public override ResolveResult VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) { - if (resolverEnabled) { + if (resolverEnabled || !objectCreateExpression.Initializer.IsNull) { IType type = ResolveType(objectCreateExpression.Type); - string[] argumentNames; - ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames); - Scan(objectCreateExpression.Initializer); // TODO + var initializer = objectCreateExpression.Initializer; + if (!initializer.IsNull) { + resolver.PushInitializerType(type); + foreach (Expression element in initializer.Elements) { + if (element is NamedExpression) { + // assignment in object initializer + Scan(element); + } else if (element is ArrayInitializerExpression) { + // constructor argument list in collection initializer + throw new NotImplementedException(); + } else { + // element in collection initializer + throw new NotImplementedException(); + } + } + resolver.PopInitializerType(); + } - return resolver.ResolveObjectCreation(type, arguments, argumentNames); + if (resolverEnabled) { + string[] argumentNames; + ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames); + + return resolver.ResolveObjectCreation(type, arguments, argumentNames); + } else { + foreach (AstNode node in objectCreateExpression.Arguments) { + Scan(node); + } + return null; + } } else { ScanChildren(objectCreateExpression); return null; @@ -2096,6 +2147,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion + #region Other statements + public override ResolveResult VisitExpressionStatement(ExpressionStatement expressionStatement, object data) + { + ScanChildren(expressionStatement); + return voidResult; + } + #endregion + #region Local Variable Type Inference /// /// Creates a type reference for the specified type node. @@ -2221,23 +2280,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #region Attributes public override ResolveResult VisitAttribute(Attribute attribute, object data) { + var type = ResolveType(attribute.Type); + + // Separate arguments into ctor arguments and non-ctor arguments: + var constructorArguments = attribute.Arguments.Where(a => !(a is NamedExpression)); + var nonConstructorArguments = attribute.Arguments.Where(a => a is NamedExpression); + + // Scan the non-constructor arguments + resolver.PushInitializerType(type); + foreach (var arg in nonConstructorArguments) + Scan(arg); + resolver.PopInitializerType(); + if (resolverEnabled) { - var type = ResolveType(attribute.Type); - - // Separate arguments into ctor arguments and non-ctor arguments: - var constructorArguments = attribute.Arguments.Where(a => !(a is AssignmentExpression)); - var nonConstructorArguments = attribute.Arguments.Where(a => a is AssignmentExpression); - - // Scan the non-constructor arguments - foreach (var arg in nonConstructorArguments) - Scan(arg); // TODO: handle these like object initializers - // Resolve the ctor arguments and find the matching ctor overload string[] argumentNames; ResolveResult[] arguments = GetArguments(constructorArguments, out argumentNames); return resolver.ResolveObjectCreation(type, arguments, argumentNames); } else { - ScanChildren(attribute); + foreach (var node in constructorArguments) + Scan(node); return null; } } diff --git a/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs b/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs index 8d09b80760..41f69eccd2 100644 --- a/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs +++ b/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs @@ -28,4 +28,4 @@ using System.Runtime.InteropServices; // // You can specify all the values or you can use the default the Revision and // Build Numbers by using the '*' as shown below: -[assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("5.0.0.0")] From 12d7961e39dd0ff9794184572d209ac5d6d58707 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Wed, 17 Aug 2011 16:53:05 +0200 Subject: [PATCH 12/15] Add SerializationBinder-support to FastSerializer. --- .../CSharp/OutputVisitorTests.cs | 53 ++++ .../ICSharpCode.NRefactory.Tests.csproj | 1 + .../Utils/FastSerializer.cs | 293 ++++++++++++++---- 3 files changed, 283 insertions(+), 64 deletions(-) create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/OutputVisitorTests.cs diff --git a/ICSharpCode.NRefactory.Tests/CSharp/OutputVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/OutputVisitorTests.cs new file mode 100644 index 0000000000..ab1eaf7d9b --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/OutputVisitorTests.cs @@ -0,0 +1,53 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.IO; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp +{ + [TestFixture] + public class OutputVisitorTests + { + void AssertOutput(string expected, Expression expr, CSharpFormattingOptions policy = null) + { + if (policy == null) + policy = new CSharpFormattingOptions();; + StringWriter w = new StringWriter(); + w.NewLine = "\n"; + expr.AcceptVisitor(new OutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "\t" }, policy), null); + Assert.AreEqual(expected.Replace("\r", ""), w.ToString()); + } + + [Test, Ignore("Incorrect whitespace")] + public void AssignmentInCollectionInitialize() + { + Expression expr = new ObjectCreateExpression { + Type = new SimpleType("List"), + Initializer = new ArrayInitializerExpression( + new ArrayInitializerExpression( + new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(1)) + ) + ) + }; + + AssertOutput("new List {\n {\n a = 1\n }\n}", expr); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index 614f24eb7e..d859360338 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -57,6 +57,7 @@ + diff --git a/ICSharpCode.NRefactory/Utils/FastSerializer.cs b/ICSharpCode.NRefactory/Utils/FastSerializer.cs index 0bd3887c6d..9622b887c4 100644 --- a/ICSharpCode.NRefactory/Utils/FastSerializer.cs +++ b/ICSharpCode.NRefactory/Utils/FastSerializer.cs @@ -30,6 +30,24 @@ namespace ICSharpCode.NRefactory.Utils { public class FastSerializer { + #region Properties + /// + /// Gets/Sets the serialization binder that is being used. + /// The default value is null, which will cause the FastSerializer to use the + /// full assembly and type names. + /// + public SerializationBinder SerializationBinder { get; set; } + #endregion + + #region Constants + const int magic = 0x71D18A5D; + + const byte Type_ReferenceType = 1; + const byte Type_ValueType = 2; + const byte Type_SZArray = 3; + const byte Type_ParameterizedType = 4; + #endregion + #region Serialization sealed class ReferenceComparer : IEqualityComparer { @@ -44,17 +62,35 @@ namespace ICSharpCode.NRefactory.Utils } } + sealed class SerializationType + { + public readonly int ID; + public readonly Type Type; + + public SerializationType(int iD, Type type) + { + this.ID = iD; + this.Type = type; + } + + public ObjectScanner Scanner; + public ObjectWriter Writer; + public string TypeName; + public int AssemblyNameID; + } + sealed class SerializationContext { readonly Dictionary objectToID = new Dictionary(new ReferenceComparer()); readonly List instances = new List(); // index: object ID - readonly List typeIDs = new List(); // index: object ID - int stringTypeID = -1; - int typeCountForObjects = 0; + readonly List objectTypes = new List(); // index: object ID + SerializationType stringType; - readonly Dictionary typeToID = new Dictionary(); - readonly List types = new List(); // index: type ID - readonly List writers = new List(); // index: type ID + readonly Dictionary typeMap = new Dictionary(); + readonly List types = new List(); + + readonly Dictionary assemblyNameToID = new Dictionary(); + readonly List assemblyNames = new List(); readonly FastSerializer fastSerializer; public readonly BinaryWriter writer; @@ -64,7 +100,7 @@ namespace ICSharpCode.NRefactory.Utils this.fastSerializer = fastSerializer; this.writer = writer; instances.Add(null); // use object ID 0 for null - typeIDs.Add(-1); + objectTypes.Add(null); } #region Scanning @@ -84,26 +120,14 @@ namespace ICSharpCode.NRefactory.Utils internal void Scan() { Log("Scanning..."); - List objectScanners = new List(); // index: type ID // starting from 1, because index 0 is null for (int i = 1; i < instances.Count; i++) { object instance = instances[i]; ISerializable serializable = instance as ISerializable; Type type = instance.GetType(); Log("Scan #{0}: {1}", i, type.Name); - int typeID; - if (!typeToID.TryGetValue(type, out typeID)) { - typeID = types.Count; - typeToID.Add(type, typeID); - types.Add(type); - Log("Registered type %{0}: {1}", typeID, type); - if (type == typeof(string)) { - stringTypeID = typeID; - } - objectScanners.Add(serializable != null ? null : fastSerializer.GetScanner(type)); - writers.Add(serializable != null ? serializationInfoWriter : fastSerializer.GetWriter(type)); - } - typeIDs.Add(typeID); + SerializationType sType = MarkType(type); + objectTypes.Add(sType); if (serializable != null) { SerializationInfo info = new SerializationInfo(type, fastSerializer.formatterConverter); serializable.GetObjectData(info, fastSerializer.streamingContext); @@ -111,23 +135,74 @@ namespace ICSharpCode.NRefactory.Utils foreach (SerializationEntry entry in info) { Mark(entry.Value); } + sType.Writer = serializationInfoWriter; } else { - objectScanners[typeID](this, instance); + ObjectScanner objectScanner = sType.Scanner; + if (objectScanner == null) { + objectScanner = fastSerializer.GetScanner(type); + sType.Scanner = objectScanner; + sType.Writer = fastSerializer.GetWriter(type); + } + objectScanner(this, instance); } } } #endregion #region Scan Types + SerializationType MarkType(Type type) + { + SerializationType sType; + if (!typeMap.TryGetValue(type, out sType)) { + string assemblyName = null; + string typeName = null; + if (type.HasElementType) { + MarkType(type.GetElementType()); + } else if (type.IsGenericType && !type.IsGenericTypeDefinition) { + MarkType(type.GetGenericTypeDefinition()); + foreach (Type typeArg in type.GetGenericArguments()) + MarkType(typeArg); + } else if (type.IsGenericParameter) { + throw new NotSupportedException(); + } else { + var serializationBinder = fastSerializer.SerializationBinder; + if (serializationBinder != null) { + serializationBinder.BindToName(type, out assemblyName, out typeName); + } else { + assemblyName = type.Assembly.FullName; + typeName = type.FullName; + Debug.Assert(typeName != null); + } + } + + sType = new SerializationType(typeMap.Count, type); + sType.TypeName = typeName; + if (assemblyName != null) { + if (!assemblyNameToID.TryGetValue(assemblyName, out sType.AssemblyNameID)) { + sType.AssemblyNameID = assemblyNames.Count; + assemblyNameToID.Add(assemblyName, sType.AssemblyNameID); + assemblyNames.Add(assemblyName); + Log("Registered assembly #{0}: {1}", sType.AssemblyNameID, assemblyName); + } + } + typeMap.Add(type, sType); + types.Add(sType); + Log("Registered type %{0}: {1}", sType.ID, type); + if (type == typeof(string)) { + stringType = sType; + } + } + return sType; + } + internal void ScanTypes() { - typeCountForObjects = types.Count; for (int i = 0; i < types.Count; i++) { - foreach (FieldInfo field in GetSerializableFields(types[i])) { - if (!typeToID.ContainsKey(field.FieldType)) { - typeToID.Add(field.FieldType, types.Count); - types.Add(field.FieldType); - } + Type type = types[i].Type; + if (type.IsGenericTypeDefinition || type.HasElementType) + continue; + foreach (FieldInfo field in GetSerializableFields(type)) { + MarkType(field.FieldType); } } } @@ -143,19 +218,65 @@ namespace ICSharpCode.NRefactory.Utils writer.Write(id); } + void WriteTypeID(Type type) + { + Debug.Assert(typeMap.ContainsKey(type)); + int typeID = typeMap[type].ID; + if (types.Count <= ushort.MaxValue) + writer.Write((ushort)typeID); + else + writer.Write(typeID); + } + internal void Write() { Log("Writing..."); + writer.Write(magic); // Write out type information - writer.Write(types.Count); writer.Write(instances.Count); - writer.Write(typeCountForObjects); - writer.Write(stringTypeID); - foreach (Type type in types) { - writer.Write(type.AssemblyQualifiedName); + writer.Write(types.Count); + writer.Write(assemblyNames.Count); + + foreach (string assemblyName in assemblyNames) { + writer.Write(assemblyName); } - foreach (Type type in types) { - if (type.IsArray || type.IsPrimitive || typeof(ISerializable).IsAssignableFrom(type)) { + + foreach (SerializationType sType in types) { + Type type = sType.Type; + if (type.HasElementType) { + if (type.IsArray) { + if (type.GetArrayRank() == 1) + writer.Write(Type_SZArray); + else + throw new NotSupportedException(); + } else { + throw new NotSupportedException(); + } + WriteTypeID(type.GetElementType()); + } else if (type.IsGenericType && !type.IsGenericTypeDefinition) { + writer.Write(Type_ParameterizedType); + WriteTypeID(type.GetGenericTypeDefinition()); + foreach (Type typeArg in type.GetGenericArguments()) { + WriteTypeID(typeArg); + } + } else { + if (type.IsValueType) { + writer.Write(Type_ValueType); + } else { + writer.Write(Type_ReferenceType); + } + if (assemblyNames.Count <= ushort.MaxValue) + writer.Write((ushort)sType.AssemblyNameID); + else + writer.Write(sType.AssemblyNameID); + writer.Write(sType.TypeName); + } + } + foreach (SerializationType sType in types) { + Type type = sType.Type; + if (type.IsGenericTypeDefinition || type.HasElementType) + continue; + if (type.IsPrimitive || typeof(ISerializable).IsAssignableFrom(type)) { writer.Write(byte.MaxValue); } else { var fields = GetSerializableFields(type); @@ -163,11 +284,7 @@ namespace ICSharpCode.NRefactory.Utils throw new SerializationException("Too many fields."); writer.Write((byte)fields.Count); foreach (var field in fields) { - int typeID = typeToID[field.FieldType]; - if (types.Count <= ushort.MaxValue) - writer.Write((ushort)typeID); - else - writer.Write(typeID); + WriteTypeID(field.FieldType); writer.Write(field.Name); } } @@ -176,24 +293,24 @@ namespace ICSharpCode.NRefactory.Utils // Write out information necessary to create the instances // starting from 1, because index 0 is null for (int i = 1; i < instances.Count; i++) { - int typeID = typeIDs[i]; + SerializationType sType = objectTypes[i]; if (types.Count <= ushort.MaxValue) - writer.Write((ushort)typeID); + writer.Write((ushort)sType.ID); else - writer.Write(typeID); - if (typeID == stringTypeID) { + writer.Write(sType.ID); + if (sType == stringType) { // Strings are written to the output immediately // - we can't create an empty string and fill it later writer.Write((string)instances[i]); - } else if (types[typeID].IsArray) { + } else if (sType.Type.IsArray) { // For arrays, write down the length, because we need that to create the array instance writer.Write(((Array)instances[i]).Length); } } // Write out information necessary to fill data into the instances for (int i = 1; i < instances.Count; i++) { - Log("0x{2:x6}, Write #{0}: {1}", i, types[typeIDs[i]].Name, writer.BaseStream.Position); - writers[typeIDs[i]](this, instances[i]); + Log("0x{2:x6}, Write #{0}: {1}", i, objectTypes[i].Type.Name, writer.BaseStream.Position); + objectTypes[i].Writer(this, instances[i]); } Log("Serialization done."); } @@ -652,7 +769,6 @@ namespace ICSharpCode.NRefactory.Utils sealed class DeserializationContext { public Type[] Types; // index: type ID - public ObjectReader[] ObjectReaders; // index: type ID public object[] Objects; // index: object ID @@ -667,7 +783,7 @@ namespace ICSharpCode.NRefactory.Utils } #region DeserializeTypeDescriptions - internal int ReadFieldTypeID() + internal int ReadTypeID() { if (this.Types.Length <= ushort.MaxValue) return Reader.ReadUInt16(); @@ -679,8 +795,10 @@ namespace ICSharpCode.NRefactory.Utils { for (int i = 0; i < this.Types.Length; i++) { Type type = this.Types[i]; + if (type.IsGenericTypeDefinition || type.HasElementType) + continue; bool isCustomSerialization = typeof(ISerializable).IsAssignableFrom(type); - bool typeIsSpecial = type.IsArray || type.IsPrimitive || isCustomSerialization; + bool typeIsSpecial = type.IsPrimitive || isCustomSerialization; byte serializedFieldCount = Reader.ReadByte(); if (serializedFieldCount == byte.MaxValue) { @@ -695,7 +813,7 @@ namespace ICSharpCode.NRefactory.Utils if (availableFields.Count != serializedFieldCount) throw new SerializationException("Number of fields on " + type.FullName + " has changed."); for (int j = 0; j < serializedFieldCount; j++) { - int fieldTypeID = ReadFieldTypeID(); + int fieldTypeID = ReadTypeID(); string fieldName = Reader.ReadString(); FieldInfo fieldInfo = availableFields[j]; @@ -705,9 +823,6 @@ namespace ICSharpCode.NRefactory.Utils throw new SerializationException(type.FullName + "." + fieldName + " was serialized as " + this.Types[fieldTypeID] + ", but now is " + fieldInfo.FieldType); } } - - if (i < this.ObjectReaders.Length && !isCustomSerialization) - this.ObjectReaders[i] = fastSerializer.GetReader(type); } } #endregion @@ -722,23 +837,67 @@ namespace ICSharpCode.NRefactory.Utils public object Deserialize(BinaryReader reader) { + if (reader.ReadInt32() != magic) + throw new SerializationException("The data cannot be read by FastSerializer (unknown magic value)"); + DeserializationContext context = new DeserializationContext(); context.Reader = reader; - context.Types = new Type[reader.ReadInt32()]; context.Objects = new object[reader.ReadInt32()]; - context.ObjectReaders = new ObjectReader[reader.ReadInt32()]; - int stringTypeID = reader.ReadInt32(); + context.Types = new Type[reader.ReadInt32()]; + string[] assemblyNames = new string[reader.ReadInt32()]; + + for (int i = 0; i < assemblyNames.Length; i++) { + assemblyNames[i] = reader.ReadString(); + } + int stringTypeID = -1; for (int i = 0; i < context.Types.Length; i++) { - string typeName = reader.ReadString(); - Type type = Type.GetType(typeName); - if (type == null) - throw new SerializationException("Could not find " + typeName); - context.Types[i] = type; + byte typeKind = reader.ReadByte(); + switch (typeKind) { + case Type_ReferenceType: + case Type_ValueType: + int assemblyID; + if (assemblyNames.Length <= ushort.MaxValue) + assemblyID = reader.ReadUInt16(); + else + assemblyID = reader.ReadInt32(); + string assemblyName = assemblyNames[assemblyID]; + string typeName = reader.ReadString(); + Type type; + if (SerializationBinder != null) { + type = SerializationBinder.BindToType(assemblyName, typeName); + } else { + type = Assembly.Load(assemblyName).GetType(typeName); + } + if (type == null) + throw new SerializationException("Could not find '" + typeName + "' in '" + assemblyName + "'"); + if (typeKind == Type_ValueType && !type.IsValueType) + throw new SerializationException("Expected '" + typeName + "' to be a value type, but it is reference type"); + if (typeKind == Type_ReferenceType && type.IsValueType) + throw new SerializationException("Expected '" + typeName + "' to be a reference type, but it is value type"); + context.Types[i] = type; + if (type == typeof(string)) + stringTypeID = i; + break; + case Type_SZArray: + context.Types[i] = context.Types[context.ReadTypeID()].MakeArrayType(); + break; + case Type_ParameterizedType: + Type genericType = context.Types[context.ReadTypeID()]; + int typeParameterCount = genericType.GetGenericArguments().Length; + Type[] typeArguments = new Type[typeParameterCount]; + for (int j = 0; j < typeArguments.Length; j++) { + typeArguments[j] = context.Types[context.ReadTypeID()]; + } + context.Types[i] = genericType.MakeGenericType(typeArguments); + break; + default: + throw new SerializationException("Unknown type kind"); + } } context.DeserializeTypeDescriptions(this); int[] typeIDByObjectID = new int[context.Objects.Length]; for (int i = 1; i < context.Objects.Length; i++) { - int typeID = context.ReadFieldTypeID(); + int typeID = context.ReadTypeID(); object instance; if (typeID == stringTypeID) { @@ -756,6 +915,7 @@ namespace ICSharpCode.NRefactory.Utils typeIDByObjectID[i] = typeID; } List customDeserializatons = new List(); + ObjectReader[] objectReaders = new ObjectReader[context.Types.Length]; // index: type ID for (int i = 1; i < context.Objects.Length; i++) { object instance = context.Objects[i]; int typeID = typeIDByObjectID[i]; @@ -773,7 +933,12 @@ namespace ICSharpCode.NRefactory.Utils CustomDeserializationAction action = GetCustomDeserializationAction(type); customDeserializatons.Add(new CustomDeserialization(instance, info, action)); } else { - context.ObjectReaders[typeID](context, instance); + ObjectReader objectReader = objectReaders[typeID]; + if (objectReader == null) { + objectReader = GetReader(context.Types[typeID]); + objectReaders[typeID] = objectReader; + } + objectReader(context, instance); } } Log("File was read successfully, now running {0} custom deserializations...", customDeserializatons.Count); From da92bc45f2854767cfff5b07b15935f5cc04288a Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 21 Aug 2011 23:23:53 +0200 Subject: [PATCH 13/15] Fix crash when serializing SimpleProjectContent. Add failing unit test for an attribute section with two attributes. --- .../GeneralScope/AttributeSectionTests.cs | 48 ++++++++----------- .../Utils/FastSerializer.cs | 3 ++ 2 files changed, 24 insertions(+), 27 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs index 4d2759dc51..c1a7571a21 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope public class AttributeSectionTests { [Test] - public void GlobalAttributeCSharp() + public void AttributesUsingNamespaceAlias() { string program = @"[global::Microsoft.VisualBasic.CompilerServices.DesignerGenerated()] [someprefix::DesignerGenerated()] @@ -45,7 +45,7 @@ public class Form1 { } [Test] - public void AssemblyAttributeCSharp() + public void AssemblyAttribute() { string program = @"[assembly: System.Attribute()]"; AttributeSection decl = ParseUtilCSharp.ParseGlobal(program); @@ -53,30 +53,8 @@ public class Form1 { Assert.AreEqual("assembly", decl.AttributeTarget); } - [Test, Ignore("assembly/module attributes are broken")] - public void AssemblyAttributeCSharpWithNamedArguments() - { - string program = @"[assembly: Foo(1, namedArg: 2, prop = 3)]"; - AttributeSection decl = ParseUtilCSharp.ParseGlobal(program); - Assert.AreEqual("assembly", decl.AttributeTarget); - var a = decl.Attributes.Single(); - Assert.AreEqual("Foo", a.Type); - Assert.AreEqual(3, a.Arguments.Count()); - - Assert.IsTrue(a.Arguments.ElementAt(0).IsMatch(new PrimitiveExpression(1))); - Assert.IsTrue(a.Arguments.ElementAt(1).IsMatch(new NamedArgumentExpression { - Identifier = "namedArg", - Expression = new PrimitiveExpression(2) - })); - Assert.IsTrue(a.Arguments.ElementAt(2).IsMatch(new AssignmentExpression { - Left = new IdentifierExpression("prop"), - Operator = AssignmentOperatorType.Assign, - Right = new PrimitiveExpression(3) - })); - } - - [Test, Ignore("assembly/module attributes are broken")] - public void ModuleAttributeCSharp() + [Test] + public void ModuleAttribute() { string program = @"[module: System.Attribute()]"; AttributeSection decl = ParseUtilCSharp.ParseGlobal(program); @@ -85,7 +63,7 @@ public class Form1 { } [Test] - public void TypeAttributeCSharp() + public void TypeAttribute() { string program = @"[type: System.Attribute()] class Test {}"; TypeDeclaration type = ParseUtilCSharp.ParseGlobal(program); @@ -94,6 +72,22 @@ public class Form1 { Assert.AreEqual("type", decl.AttributeTarget); } + [Test] + public void TwoAttributesInSameSection() + { + ParseUtilCSharp.AssertGlobal( + @"[A, B] class Test {}", + new TypeDeclaration { + Name = "Test", + Attributes = { + new AttributeSection { + Attributes = { + new Attribute { Type = new SimpleType("A") }, + new Attribute { Type = new SimpleType("B") } + } + }}}); + } + [Test, Ignore("Parser doesn't support attributes on type parameters")] public void AttributesOnTypeParameter() { diff --git a/ICSharpCode.NRefactory/Utils/FastSerializer.cs b/ICSharpCode.NRefactory/Utils/FastSerializer.cs index 9622b887c4..1fd1053f22 100644 --- a/ICSharpCode.NRefactory/Utils/FastSerializer.cs +++ b/ICSharpCode.NRefactory/Utils/FastSerializer.cs @@ -157,6 +157,7 @@ namespace ICSharpCode.NRefactory.Utils string assemblyName = null; string typeName = null; if (type.HasElementType) { + Debug.Assert(type.IsArray); MarkType(type.GetElementType()); } else if (type.IsGenericType && !type.IsGenericTypeDefinition) { MarkType(type.GetGenericTypeDefinition()); @@ -201,6 +202,8 @@ namespace ICSharpCode.NRefactory.Utils Type type = types[i].Type; if (type.IsGenericTypeDefinition || type.HasElementType) continue; + if (typeof(ISerializable).IsAssignableFrom(type)) + continue; foreach (FieldInfo field in GetSerializableFields(type)) { MarkType(field.FieldType); } From 9d0e6ae0f8d81c5823cb6adec588e4dc8ece5bc2 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 21 Aug 2011 23:49:30 +0200 Subject: [PATCH 14/15] Resolver: added support for collection initializers and nested object initializers. --- .../CSharp/Resolver/LambdaTests.cs | 7 +-- .../CSharp/Resolver/ObjectCreationTests.cs | 40 +++++++++++++ .../CSharp/Resolver/CSharpResolver.cs | 5 +- .../CSharp/Resolver/ResolveVisitor.cs | 57 ++++++++++++++----- 4 files changed, 89 insertions(+), 20 deletions(-) diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 5abde3da4c..e3472e8b43 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -159,7 +159,7 @@ class TestClass { #endregion #region Lambda In Collection Initializer - [Test, Ignore("Parser doesn't support collection initializers yet")] + [Test] public void LambdaInCollectionInitializer1() { string program = @"using System; using System.Collections.Generic; @@ -174,7 +174,7 @@ class TestClass { Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } - [Test, Ignore("Parser doesn't support collection initializers yet")] + [Test] public void LambdaInCollectionInitializer2() { string program = @"using System; using System.Collections.Generic; @@ -189,8 +189,7 @@ class TestClass { Assert.AreEqual("System.Char", lrr.Type.ReflectionName); } - - [Test, Ignore("Parser doesn't support collection initializers yet")] + [Test] public void LambdaInCollectionInitializer3() { string program = @"using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs index bf889c6544..9b69e10c8f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs @@ -156,5 +156,45 @@ class B { MemberResolveResult result = Resolve(program); Assert.AreEqual("A.Property", result.Member.FullName); } + + [Test] + public void FieldReferenceInNestedObjectInitializer() + { + string program = @"class Point { public float X, Y; } +class Rect { public Point TopLeft, BottomRight; } +class B { + void Method() { + var x = new Rect() { TopLeft = { $X = 1$ } }; + } +}"; + MemberResolveResult result = Resolve(program); + Assert.AreEqual("Point.X", result.Member.FullName); + } + + [Test, Ignore("Parser returns incorrect positions")] + public void CollectionInitializerTest() + { + string program = @"using System.Collections.Generic; +class B { + void Method() { + var x = new List() { ${ 0 }$ }; + } +}"; + InvocationResolveResult result = Resolve(program); + Assert.AreEqual("System.Collections.Generic.List.Add", result.Member.FullName); + } + + [Test, Ignore("Parser returns incorrect positions")] + public void DictionaryInitializerTest() + { + string program = @"using System.Collections.Generic; +class B { + void Method() { + var x = new Dictionary() { ${ 'a', 0 }$ }; + } +}"; + InvocationResolveResult result = Resolve(program); + Assert.AreEqual("System.Collections.Generic.Dictionary.Add", result.Member.FullName); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs index 3a63e9b9d9..7e6e362455 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs @@ -2109,7 +2109,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return ErrorResult; } - MemberLookup CreateMemberLookup() + /// + /// Creates a MemberLookup instance using this resolver's settings. + /// + public MemberLookup CreateMemberLookup() { return new MemberLookup(context, this.CurrentTypeDefinition, this.UsingScope != null ? this.UsingScope.ProjectContent : null); } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs index 91389da3c3..d69b6b1c28 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs @@ -999,7 +999,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { Expression rhs = namedExpression.Expression; if (rhs is ArrayInitializerExpression) { - throw new NotImplementedException(); + ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier); + HandleObjectInitializer(result.Type, (ArrayInitializerExpression)rhs); + return result; } else { if (resolverEnabled) { ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier); @@ -1028,20 +1030,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver var initializer = objectCreateExpression.Initializer; if (!initializer.IsNull) { - resolver.PushInitializerType(type); - foreach (Expression element in initializer.Elements) { - if (element is NamedExpression) { - // assignment in object initializer - Scan(element); - } else if (element is ArrayInitializerExpression) { - // constructor argument list in collection initializer - throw new NotImplementedException(); - } else { - // element in collection initializer - throw new NotImplementedException(); - } - } - resolver.PopInitializerType(); + HandleObjectInitializer(type, initializer); } if (resolverEnabled) { @@ -1061,6 +1050,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + void HandleObjectInitializer(IType type, ArrayInitializerExpression initializer) + { + resolver.PushInitializerType(type); + foreach (Expression element in initializer.Elements) { + ArrayInitializerExpression aie = element as ArrayInitializerExpression; + if (aie != null) { + if (resolveResultCache.ContainsKey(aie)) { + // Don't resolve the add call again if we already did so + continue; + } + StoreState(aie, resolver.Clone()); + // constructor argument list in collection initializer + ResolveResult[] addArguments = new ResolveResult[aie.Elements.Count]; + int i = 0; + foreach (var addArgument in aie.Elements) { + addArguments[i++] = Resolve(addArgument); + } + MemberLookup memberLookup = resolver.CreateMemberLookup(); + ResolveResult targetResult = new ResolveResult(type); + var addRR = memberLookup.Lookup(targetResult, "Add", EmptyList.Instance, true); + var mgrr = addRR as MethodGroupResolveResult; + if (mgrr != null) { + OverloadResolution or = mgrr.PerformOverloadResolution(resolver.Context, addArguments, null, false, false); + var invocationRR = new InvocationResolveResult(targetResult, or, resolver.Context); + StoreResult(aie, invocationRR); + ProcessConversionsInResult(invocationRR); + } else { + StoreResult(aie, addRR); + } + } else { + // assignment in object initializer (NamedExpression), + // or some unknown kind of expression + Scan(element); + } + } + resolver.PopInitializerType(); + } + public override ResolveResult VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) { if (resolverEnabled) { From b1804fd9df13d063830207a14cb4a1f0902c06a3 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Mon, 22 Aug 2011 12:01:07 +0200 Subject: [PATCH 15/15] Add position-checking unit test to NRefactory. --- .../CSharp/Parser/ParseSelfTests.cs | 119 ++++++++++++++++++ .../ICSharpCode.NRefactory.Tests.csproj | 5 + 2 files changed, 124 insertions(+) create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs new file mode 100644 index 0000000000..1f00584ad6 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs @@ -0,0 +1,119 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.IO; +using ICSharpCode.Editor; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser +{ + /// + /// Test fixture that parses NRefactory itself, + /// ensures that there are no parser crashes while doing so, + /// and that the returned positions are consistent. + /// + [TestFixture] + public class ParseSelfTests + { + string[] fileNames; + + [TestFixtureSetUp] + public void SetUp() + { + string path = Path.GetFullPath(@"..\..\.."); + if (!File.Exists(Path.Combine(path, "NRefactory.sln"))) + throw new InvalidOperationException("Test cannot find the NRefactory source code in " + path); + fileNames = Directory.GetFiles(path, "*.cs", SearchOption.AllDirectories); + } + + [Test] + public void GenerateTypeSystem() + { + SimpleProjectContent pc = new SimpleProjectContent(); + CSharpParser parser = new CSharpParser(); + parser.GenerateTypeSystemMode = true; + foreach (string fileName in fileNames) { + CompilationUnit cu; + using (var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read, 4096, FileOptions.SequentialScan)) { + cu = parser.Parse(fs); + } + TypeSystemConvertVisitor cv = new TypeSystemConvertVisitor(pc, fileName); + pc.UpdateProjectContent(null, cv.Convert(cu)); + } + } + + #region ParseAndCheckPositions + string currentFileName; + ReadOnlyDocument currentDocument; + + [Test] + public void ParseAndCheckPositions() + { + CSharpParser parser = new CSharpParser(); + foreach (string fileName in fileNames) { + this.currentDocument = new ReadOnlyDocument(File.ReadAllText(fileName)); + CompilationUnit cu = parser.Parse(currentDocument.CreateReader()); + this.currentFileName = fileName; + CheckPositionConsistency(cu); + CheckMissingTokens(cu); + } + } + + void CheckPositionConsistency(AstNode node) + { + string comment = "(" + node.GetType().Name + " at " + node.StartLocation + " in " + currentFileName + ")"; + Assert.IsTrue(node.StartLocation <= node.EndLocation, "StartLocation must be before EndLocation " + comment); + var prevNodeEnd = node.StartLocation; + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + Assert.IsTrue(child.StartLocation >= prevNodeEnd, "Child must start after previous sibling " + comment); + CheckPositionConsistency(child); + prevNodeEnd = child.EndLocation; + } + Assert.IsTrue(prevNodeEnd <= node.EndLocation, "Last child must end before parent node ends " + comment); + } + + void CheckMissingTokens(AstNode node) + { + if (node is IRelocatable) { + Assert.IsNull(node.FirstChild, "Token nodes should not have children"); + } else { + var prevNodeEnd = node.StartLocation; + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + CheckWhitespace(prevNodeEnd, child.StartLocation); + CheckMissingTokens(child); + prevNodeEnd = child.EndLocation; + } + CheckWhitespace(prevNodeEnd, node.EndLocation); + } + } + + void CheckWhitespace(AstLocation whitespaceStart, AstLocation whitespaceEnd) + { + if (whitespaceStart == whitespaceEnd) + return; + int start = currentDocument.GetOffset(whitespaceStart.Line, whitespaceStart.Column); + int end = currentDocument.GetOffset(whitespaceEnd.Line, whitespaceEnd.Column); + string text = currentDocument.GetText(start, end - start); + Assert.IsTrue(string.IsNullOrWhiteSpace(text), "Expected whitespace between " + whitespaceStart + " and " + whitespaceEnd + + ", but got '" + text + "' (in " + currentFileName + ")"); + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index d859360338..3dfd96dd5f 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -64,6 +64,7 @@ + @@ -161,6 +162,10 @@ + + {F054A788-B591-4561-A8BA-AE745BBEB817} + ICSharpCode.Editor + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} ICSharpCode.NRefactory