From 88ebd0b9596edab0e916ff28ae53f6febbdff032 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 17 Sep 2011 15:15:30 +0200 Subject: [PATCH] Squashed 'NRefactory/' changes from 9675caf..a73d7ba MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit a73d7ba Added async/await support to the resolver. d0e9ce0 CodeDomConvertVisitor: choose between CodeIndexerExpression and CodeArrayIndexerExpression. DefaultParameter: fixed bug in interning - two parameters with different names were considered equal for interning. 7ff012f Fixed some issues in the CodeDomConvertVisitor. fd8f8cf Adjust AST for async/await. e4d1f54 Add CodeDomConvertVisitor. af5ae57 Added type case for resolvenode at location. 770b5c6 fixed possible null ref. ddaaaaf added some more attributed nodes. abd8372 fixed some attributed node formattings. 6ef3944 Implemented attribute section formatting. 2e67d54 Now all formatting tests are green! a1a80b6 Fix StackOverflowException when subtyping does not terminate due to expansive inheritance. a48acf0 put variable initializer assign into the right node. cc9cea0 Fixed missing commas. a9bae21 fixed 'params' location. 84135f5 Fixed lambda parameter commas. 9e909e1 Found wrong indexer pos. 994f931 fixed dot location. fbb77b7 fixed indexer locations. 8d630fd Fixed array initializer brace position. bb59175 Fixed constraint commas. 8680670 Fixed endif position. 9d55421 Fixed attribute argument commas. f6de4e3 improved error msg. c133a2a Handled #if values. 72b2ff1 Added labeled statement colon. 7f141c0 fixed goto location. d63f1fa Fixed named argument expression. 6043039 Fixed base type comma order. 618cb98 Fixed initializer comma locations. aee84bd Fixed nullable position. 3147a3a Fixed enum positions. 0fb1105 Fixed attribute section locations. 2ba4a18 Location of global attributes was wrong. Fixed for tests - should be inserted like the comments for the real fix. e07b8fa Fixed some dot locations. 0dd3117 Fixed empty statement end location. 7ed3af2 Updated mcs (fixed char posititions). cff7997 Fixed some declarator assign token locations. 8fb218b Handled pre processor directives - fist approach. 9d3c076 Fixed some issues with comment insertion. d683689 added serializable attributes. 61c9894 removed debug message. 22a97b5 Added 'default' section keywords. a2a077f added enum member assign token & case label colon token. 71f47a6 Added more debug output. 2cad4e3 fixed location bug. 50f95d3 Updated mcs. d1db72b Added missing "new" keyword. 382f695 Fixed some locations in array create expression. 14d0638 Fixed implicit/explicit operator locations. 03babc6 Corrected constructor locations. 0d6d9ac Added type parameter variances & tokens. 76249ec Added explicit interface dot. babe656 Fixed some dot locations inside member type names. c671230 Fixed type argument commas. 1b21681 Fixed literal values of bools. 99b1a32 Added debug message. 42e49ce Fixed operator declaration operator location. 15b30e9 Corrected comma locations. 2e6b746 Improved error messages a bit. a1a649e Remove ITextEditorAdapter and use IDocument instead. 0413ce9 Added completion engine stub. eb6c399 Moved to completion namespace. c82538e Added basic code completion interfaces. 42aa01a Improved error message. 74bc8b2 Fixed chevron & constraints locations. 64b7dff Removed more target framework profiles. 20ba899 Improved error message. 3303c99 Corrected constraint locations. 2fc0c7c Fixed bug with class keyword. 5e8e124 Removed client target framework profile. 65d8773 added dots in using declaration. eddd015 Fixed enum member commas. b1fa379 Fixed location bug. ea6e15c Fixed method/operator semicolons. ab28842 Added base type comma tokens. 9b28b28 Fixed colon / optional commas in type delcarations. 96195ac fixed +-1 issue. 0ee8198 * Log.cs: * ICSharpCode.NRefactory.csproj: * CSharpParser.cs: bd01cad Fixed parameter comma locations. f302311 Fixed positioning error. 9de8c14 Fixed resolving event declarations. dfc9860 Move ICSharpCode.Editor into NRefactory. b7a17c2 Adjust unit tests to InvocationResolveResult changes. b5b2408 Move NRefactory.CSharp to separate assembly. e37dc4b Move ResolveResults to NR.Semantics 8e78ca4 Use path combine. 447558f Fixed parser test set up for non windows systems. 611c310 Change IConstantValue API to use ResolveResult. 6bc485f Merge NRefactory changes from SharpDevelop into NRefactory repository. ea42e63 Fix bug that caused the wrong part to be removed from a compound class. e73c078 Make Find References multi-threaded. e7d9bf6 Fixed attribute section tests. 957c48e Fixed query expression tests. 02fe3e3 Fixed array create expression tests. e926745 Fixed resolver bugs that caused unit test errors. bb03113 Allow recursive synchronization (e.g. for calling GetTypes() on a single project content while a composite project content is synchronized) 683d353 Implemented "Find references" a06110c Rename ParsedFile to CSharpParsedFile. 8885484 Add IndexOf() method to ITextSource. be53547 Merge branch '4.1' into newNR 558e158 Fix resolver crashes 46676a4 Add GetInterestingFileNames to FindReferences. Fixed a few resolver issues related to find references. 7f11fe3 Fixed bugs that caused some nodes not to be resolved in a "resolve all" run. 42bc87b Change ResolveVisitor to report the location of conversions. 4cc64bb Fixed resolving LINQ group joins. 5b17740 Use explicit interface implementation in ResolveVisitor to make it clear what the public API is supposed to be. f807e61 TypeSystemAstBuilder: when a type reference cannot be resolved but is a C# type reference, output the original C# code that was used to created the type reference. 023e13b Merge changes from SharpDevelop into the main NRefactory repository. b193dc9 FastSerializer: Add support for 'Fixed Instances', e.g. for serializing object graphs that have references to a singleton. a5865bd Implemented "Find References". 33abc64 Replace AstNode.GetResolvableNodeAt() with the ResolveAtLocation helper class. a93fd14 Adjust unit tests and fix bugs introduced by caching. 2b3d669 Add ITypeResolveContext.GetKnownTypeDefinition() for efficiently retrieving built-in types. 8a05ada Don't keep the per-using scope and per-type definiton caches around longer than necessary. ecdf195 Cache simple name lookups more aggressively. 50f7041 Cache resolved CSharpConstantValue. 47eb183 Reuse Conversions instance across multiple files by storing it in the CacheManager. 82fad4e Use 'UsingScopeCache' instance for caching the extension methods. 2be1569 Add cache for implicit conversions for 25% performance boost. Also did some improvements to interning. 391a6bc Cache resolved SimpleTypeOrNamespaceReference/MemberTypeOrNamespaceReference, and intern those references. 3fdf0ee Implemented resolver for LINQ queries. 3bbc3f6 Fixed NullReferenceException in MethodGroupResolveResult.ResolveInvocation(). Implemented resolving local variables that are declared as 'const'. fb8d152 Fixed deserialization of XmlDocumentationProvider. dafc2c6 Add back ResolverService.Resolve(); and use it to implement tool tips. f7fe227 Add AssemblyName to IProjectContent. b1804fd Add position-checking unit test to NRefactory. 9d0e6ae Resolver: added support for collection initializers and nested object initializers. da92bc4 Fix crash when serializing SimpleProjectContent. Add failing unit test for an attribute section with two attributes. f4bd875 Initial implementation of CSharpAmbience. fa7e478 newNR: fixed build errors in AvalonEdit.AddIn and CSharpBinding. 12d7961 Add SerializationBinder-support to FastSerializer. a5c93a3 Adjust resolver to object initializer AST changes. 87992d3 Fix build for NRefactory.VB. 62b9fce Always create ArrayInitializerExpressions. 405e87e Fixed location bug. 36c412d Allow serializing SimpleProjectContent and parsed C# type references. 769c0ae Allow CecilProjectContent to be serialized. Add FastSerializer to NRefactory.Utils. abbf9d6 Used the namedexpression instead of assignment/namedargument expressions. 3e99fab 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. c373100 Fixed ComplexCollectionInitializer tests. 3763397 Introduced namedexpression/namedexpressionlist to handle the collection initializers better. 0ecf1fc Fixed collection initializer parsing. c76dd64 WIP 59c4e5c WIP: new NRefactory 06b143b Member lookup: Fix IsAccessible bug for protected static members. Make CSharpResolver.ResolveMemberType() return a non-parameterized type when all type arguments are UnboundTypeArgument. ea3e312 Implemented grouping overloads by declared type. Return overrides in most-derived class (necessary for determining the correct parameter names/IsOptional value), but keep them in the group where the virtual/abstract base method was. 7a2c59a Add GetMemberOptions. f79b0a7 Resolver: array create expressions 2c49c71 Report resolve results back to the navigator. 69ae15a Add support for partial classes. c9c2044 Fix type inference and overload resolution when a class type parameter gets substituted by a method type parameter. 5c585e1 Apply license header to unit tests. Add parser unit tests for ObjectCreateExpression. a1f613e ResolveVisitor: skip tokens and comments Make the resolver's debug output more readable. 4372b61 Fixed lambda type inference for nested (curried) lambdas. b52a348 More work on lambda expressions. cd99dce Fix bugs caused by the introduction of user-defined operators. 43b5897 Add support for user-defined operators. 37626e1 Expose conversions as part of the ResolveResult. f86a014 Put MIT license into the file headers. e51e3a9 Add InvocationResolveResult. 8c8caf7 Implemented type inference for implicitly typed lambdas. 6792a0c Report which kind of conversion was found. d59fd2b C# Resolver: preparations for lambda support e17ba74 Add unit tests for TypeSystemAstBuilder. fd8050a Merge changes from SharpDevelop into the main NRefactory repository. b97543a A few small API changes for NRefactory. a9a6e16 Add ID string provider + a few resolver bugfixes 77c7d08 Implemented disambiguation for identical simple names and type names. (e.g. "public Color Color;") 21d2121 CecilLoader: add support for reading module attributes, security declarations and marshal information. 18fb49c Add TypeKind enum. bb2f93a NRefactory bug fixes: - Use IType.Equals() instead of == operator - Change handling of partially parameterized types in IType.GetNestedTypes so that we don't leak type parameters from the wrong context - Add support for unbound types to C# resolver (e.g. in attribute arguments) - C# Parser: preserve variance modifier - Ensure all interface members are marked as 'abstract' - Add support for [TypeForwardedTo] and [ComImport] to CecilLoader. 3e75554 gitignore for ICSharpCode.Editor 849ed04 Merge NRefactory changes from ILSpy into the main NRefactory repository. 89ba05f C# calls indexers "Item", not "Items". 811784e Re-implemented IType.GetMembers() to avoid redundant specialization. 877ebf8 Remove operator == from AstNodeCollection. c15615d fix bug in remove braces action. 2ce741b Keep ITextEditor in the IDE (comment out the copy in ICSharpCode.Editor) 3ba9118 fixed bug where parameter is null. 58b8d06 Visit empty expressions. 6abb0a1 IDocument now derives from IServiceProvider. cb70bce Add strong-name to NRefactory; small API changes for ICSharpCode.Editor. fa6afb2 Fix ResolveVisitor.VisitArrayCreateExpression. b0819ac Supporting installing a NuGet package into selected projects in one step. c428246 use Is/IsNot for reference equality checks; add extension attribute for extension methods 0346512 remove shared modifier from module members fbc8b85 convert static classes to modules e3a301e fix output of Inherits/Implements clauses ebeef27 convert increment/decrement operator overloads to op_Increment/op_Decrement methods 1d8a294 map true/false operator to IsTrue/IsFalse 4c8a11c improve conversion of special characters in string literals 04d816c fix bug in checked statement handling 610924e fix InvalidCastException in For-Next detection 5a00a6c Mark ICSharpCode.NRefactory.VB as AnyCPU. 1d904e1 add folding 3265ddc implement conversion of attribute targets d4eabd0 relicense NR.VB under MIT X11 license e90fa22 implement query expression AST 93cf054 Merge branch 'master' of github.com:icsharpcode/ILSpy into vb f7fcc9d implemented AnonymousObjectCreationExpression 46b5f43 add EmptyExpression conversion, improve fixed-Statement conversion e7dd90c implemented unchecked/checked expression, pointer access and so on c007a2a implemented fixed using GCHandle c431176 convert C#ˈs undocumented expressions to method calls 12eb661 convert anonymous methods to multiline sub lambdas 354aefa add conversion of DllImports to ExternalMethodDeclarations 2639711 convert dtor to Finalize Sub da4b1ba improve conversion of event declarations eab1ac6 add ContinueStatement 95db1eb added conversion to VB ForStatement d46401c Added missing predicate parameter. 2e3d9fa started implementation of QueryExpression d340669 make AddressOfExpression a UnaryOperatorExpression, move expressions to separate files, implement LambdaExpression 3d5b284 fixed bug in anonymous array create expression resolving. bf89db8 implement GoToStatement 3531735 implemented DoLoopStatement and UsingStatement 04ecdd7 Added support for anonymous arrays. a3d75db implement conversion of switch to Select Case 0a9b6c7 Implemented simple array create expression resolving. 3be8d6c Fixed bug with GetElementType. ArrayType yields System.Collections.IEnumerable as base type before the more specific System.Colloctions.Generic.IEnumerable. 5cf130c correctly implement ForEachStatement and ForStatement; add output for ForStatement fa4694e implement VB 11 Iterators 8137e58 Merge NRefactory 9675caf1e9276391f17536b488148cb668a6cc44 57d92d1 add support for OperatorDeclaration and some more statements 84b283b add ConditionalExpression and WhileStatement 1c8d2aa split Statements into single files 9ff6e73 reimplement some helper methods 024348d implement NamedArgumentExpression and FieldInitializerExpression 1bb5b83 implement conversion of AsExpression to TryCast, improve conversion of string literals, add UnaryOperatorExpression 3381b04 implement ArrayCreateExpression and CastExpression 41578d4 Merge branch '1.0' 0169874 - Reverted changes to display decimal.MinValue and decimal.MaxValue - Altered InitializerTests to use constant literals instead of decimal.MinValue and decimal.MaxValue 5c3be8f - Modified the InitializerPeepholeTransforms' Array Initializers to do a forward scan of the block instead of just checking the next instruction. The next-instruction thing breaks down under the case where you have an array-of-arrays (int[][]) - Added to the InitializerPeepholeTransforms' Array Initializers to detect the creation of a multi-dimensional array (int[,]) - Modified the ILCode.InitArray contract to take an ArrayType instead of just the element type, and passing with the ArrayType.Dimensions set accordingly. - AstMethodBodyBuilder now used the ArrayType.Dimensions info to build a tree of ArrayInitializerExpressions from the raw, element-by-element list. - Fixed OutputVisitor not calling StartNode for EmptyExpressions c1d27c7 - Made the InitializerTests pass, through three changes: * Added new-lines as needed to make the source formatting match what the actual output was. * Added code to CodeAssert to make it ignore #regions * Added code to output decimal.MinValue and decimal.MaxValue as appropriate 591d874 Merge branch 'master' of https://github.com/icsharpcode/ILSpy into Debugger a29b397 Merge branch 'master' of https://github.com/icsharpcode/ILSpy into Debugger 91c563b Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Iconbar e434783 get AST nodes locally a7f45f6 add icon margin & bookmarks 48774e4 add support for EventDeclaration and some more binary operators 1e2bce6 do not print method bodies in Interfaces d83c0e6 add support for comments 0f33774 output ThrowStatement 8cb9d38 add ArrayInitializerExpression and ObjectCreationExpression d523549 fix indentation in Accessor blocks 7ed36c0 convert default(T) to Nothing and typeof() to GetType() 032f217 implemented IfElseStatement and some more expressions 56e7557 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 82c6419 implement translation of EnumDeclaration d217418 implement PropertyDeclaration; add Inherits/Implements to TypeDeclaration; implement output for DelegateDeclaration e0bfac9 implement proper conversion of FieldDeclaration 43cf583 add MethodDeclaration, ConstructorDeclaration; EventMemberSpecifier, InterfaceMemberSpecifier for Handles and Implements clauses 3a26819 add GetTypeExpression, GetXmlNamespaceExpression, MemberAccessExpression, TypeOfIsExpression and TypeReferenceExpression b3ec92a implement AddressOfExpression, InstanceExpression, ParenthesizedExpression and SimpleNameExpression b9dc346 implement Attribute conversion 5f5a38c add support for Imports and Namespaces e8cde13 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger bcc40ee Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 7f49b56 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger bdb2c57 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger af56cbe Implement new methods in NotImplementedAstVisitor. d12f5b2 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 01a3871 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 90f8624 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger ad02254 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 044958a Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger e3471e6 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger b5d560a Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger a48634d Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger b33ddd3 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 3510129 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 2ff8e15 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger d87e40b Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 0fd4c4c Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger ac3737f Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 9f55acb Basic evaluation - first level 75a5092 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 10eb834 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 9e3e302 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 17b10a7 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger c3cbf9e Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger dc49175 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger f3a2be8 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger f187243 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 0f7ab11 Merge branch 'master' of git://github.com/icsharpcode/ILSpy into Debugger 0a54ead Port debugger libraries to use new NRefactory. 89af871 Started porting the debugger code to use new NRefactory git-subtree-dir: NRefactory git-subtree-split: a73d7ba8db559273e648e095cd4e149462b6526a --- ICSharpCode.Editor/ICSharpCode.Editor.csproj | 72 - ICSharpCode.Editor/IDocumentLine.cs | 30 - ICSharpCode.Editor/ISegment.cs | 55 - ICSharpCode.Editor/ITextEditor.cs | 100 - ICSharpCode.Editor/LinkedElement.cs | 68 - ICSharpCode.NRefactory.CSharp/.gitignore | 3 + .../Analysis/ControlFlow.cs | 26 +- .../Analysis/DefiniteAssignmentAnalysis.cs | 24 +- .../Ast/AstNode.cs | 102 +- .../Ast/AstNodeCollection.cs | 40 +- .../Ast/AstType.cs | 22 +- .../Ast/CSharpModifierToken.cs | 49 +- .../Ast/CSharpTokenNode.cs | 20 +- .../Ast/CSharpUtil.cs | 0 .../Ast/CompilationUnit.cs | 2 +- .../Ast/ComposedType.cs | 10 +- .../Ast/DepthFirstAstVisitor.cs | 13 +- .../Ast/ErrorNode.cs | 10 +- .../Expressions/AnonymousMethodExpression.cs | 13 +- .../AnonymousTypeCreateExpression.cs | 12 +- .../Ast/Expressions/ArrayCreateExpression.cs | 20 +- .../Expressions/ArrayInitializerExpression.cs | 18 +- .../Ast/Expressions/AsExpression.cs | 2 +- .../Ast/Expressions/AssignmentExpression.cs | 2 +- .../Expressions/BaseReferenceExpression.cs | 10 +- .../Expressions/BinaryOperatorExpression.cs | 15 +- .../Ast/Expressions/CastExpression.cs | 2 +- .../Ast/Expressions/CheckedExpression.cs | 2 +- .../Ast/Expressions/ConditionalExpression.cs | 2 +- .../Ast/Expressions/DefaultValueExpression.cs | 2 +- .../Ast/Expressions/DirectionExpression.cs | 2 +- .../Ast/Expressions/EmptyExpression.cs | 14 +- .../Ast/Expressions/Expression.cs | 31 +- .../Ast/Expressions/IdentifierExpression.cs | 6 +- .../Ast/Expressions/IndexerExpression.cs | 2 +- .../Ast/Expressions/InvocationExpression.cs | 2 +- .../Ast/Expressions/IsExpression.cs | 2 +- .../Ast/Expressions/LambdaExpression.cs | 13 +- .../Expressions/MemberReferenceExpression.cs | 6 +- .../Expressions/NamedArgumentExpression.cs | 77 + .../Ast/Expressions/NamedExpression.cs | 86 + .../Expressions/NullReferenceExpression.cs | 12 +- .../Ast/Expressions/ObjectCreateExpression.cs | 2 +- .../Expressions/ParenthesizedExpression.cs | 2 +- .../Expressions/PointerReferenceExpression.cs | 6 +- .../Ast/Expressions/PrimitiveExpression.cs | 14 +- .../Ast/Expressions/QueryExpression.cs | 71 +- .../Ast/Expressions/SizeOfExpression.cs | 2 +- .../Ast/Expressions/StackAllocExpression.cs | 2 +- .../Expressions/ThisReferenceExpression.cs | 10 +- .../Ast/Expressions/TypeOfExpression.cs | 2 +- .../Expressions/TypeReferenceExpression.cs | 54 + .../Expressions/UnaryOperatorExpression.cs | 19 +- .../Ast/Expressions/UncheckedExpression.cs | 2 +- .../Ast/Expressions/UndocumentedExpression.cs | 2 +- .../Ast/GeneralScope/Attribute.cs | 4 +- .../Ast/GeneralScope/AttributeSection.cs | 21 +- .../Ast/GeneralScope/Comment.cs | 20 +- .../Ast/GeneralScope/Constraint.cs | 6 +- .../Ast/GeneralScope/DelegateDeclaration.cs | 6 +- .../GeneralScope/ExternAliasDeclaration.cs | 6 +- .../Ast/GeneralScope/NamespaceDeclaration.cs | 6 +- .../Ast/GeneralScope/TypeDeclaration.cs | 14 +- .../GeneralScope/TypeParameterDeclaration.cs | 23 +- .../Ast/GeneralScope/UsingAliasDeclaration.cs | 10 +- .../Ast/GeneralScope/UsingDeclaration.cs | 2 +- .../Ast/IAstVisitor.cs | 22 +- .../Ast/IRelocatable.cs | 4 +- .../Ast/Identifier.cs | 36 +- .../Ast/IdentifierExpressionBackreference.cs | 54 + .../Ast/MemberType.cs | 8 +- .../Ast/Modifiers.cs | 15 +- .../Ast/NodeType.cs | 4 + .../Ast/ObservableAstVisitor.cs | 18 +- .../Ast/PrimitiveType.cs | 14 +- .../Ast/SimpleType.cs | 10 +- .../Ast/Statements/BlockStatement.cs | 6 +- .../Ast/Statements/BreakStatement.cs | 2 +- .../Ast/Statements/CheckedStatement.cs | 2 +- .../Ast/Statements/ContinueStatement.cs | 2 +- .../Ast/Statements/DoWhileStatement.cs | 2 +- .../Ast/Statements/EmptyStatement.cs | 14 +- .../Ast/Statements/ExpressionStatement.cs | 2 +- .../Ast/Statements/FixedStatement.cs | 2 +- .../Ast/Statements/ForStatement.cs | 2 +- .../Ast/Statements/ForeachStatement.cs | 6 +- .../Ast/Statements/GotoStatement.cs | 10 +- .../Ast/Statements/IfElseStatement.cs | 2 +- .../Ast/Statements/LabelStatement.cs | 6 +- .../Ast/Statements/LockStatement.cs | 2 +- .../Ast/Statements/ReturnStatement.cs | 2 +- .../Ast/Statements/Statement.cs | 15 +- .../Ast/Statements/SwitchStatement.cs | 11 +- .../Ast/Statements/ThrowStatement.cs | 2 +- .../Ast/Statements/TryCatchStatement.cs | 10 +- .../Ast/Statements/UncheckedStatement.cs | 2 +- .../Ast/Statements/UnsafeStatement.cs | 2 +- .../Ast/Statements/UsingStatement.cs | 2 +- .../VariableDeclarationStatement.cs | 2 +- .../Ast/Statements/WhileStatement.cs | 2 +- .../Ast/Statements/YieldBreakStatement.cs | 2 +- .../Ast/Statements/YieldReturnStatement.cs | 8 +- .../Ast/TypeMembers/Accessor.cs | 4 +- .../Ast/TypeMembers/AttributedNode.cs | 21 +- .../Ast/TypeMembers/ConstructorDeclaration.cs | 6 +- .../Ast/TypeMembers/DestructorDeclaration.cs | 2 +- .../Ast/TypeMembers/EnumMemberDeclaration.cs | 6 +- .../Ast/TypeMembers/EventDeclaration.cs | 4 +- .../Ast/TypeMembers/FieldDeclaration.cs | 2 +- .../Ast/TypeMembers/FixedFieldDeclaration.cs | 2 +- .../TypeMembers/FixedVariableInitializer.cs | 6 +- .../Ast/TypeMembers/IndexerDeclaration.cs | 2 +- .../Ast/TypeMembers/MemberDeclaration.cs | 4 +- .../Ast/TypeMembers/MethodDeclaration.cs | 2 +- .../Ast/TypeMembers/OperatorDeclaration.cs | 4 +- .../Ast/TypeMembers/ParameterDeclaration.cs | 6 +- .../Ast/TypeMembers/PropertyDeclaration.cs | 2 +- .../Ast/TypeMembers/VariableInitializer.cs | 16 +- .../Completion/CSharpCompletionEngine.cs | 51 + .../Formatter/AstFormattingVisitor.cs | 256 +- .../Formatter/CSharpFormattingOptions.cs | 0 .../Formatter/Indent.cs | 0 .../ICSharpCode.NRefactory.CSharp.csproj | 313 + .../OutputVisitor/CSharpOutputVisitor.cs | 441 +- .../OutputVisitor/CodeDomConvertVisitor.cs | 1304 +++ .../OutputVisitor/IOutputFormatter.cs | 59 + .../OutputVisitor/InsertParenthesesVisitor.cs | 19 +- .../TextWriterOutputFormatter.cs | 19 +- .../Parser/CSharpParser.cs | 773 +- .../Parser/ParsedFile.cs | 53 +- .../Parser/TypeSystemConvertVisitor.cs | 271 +- .../Parser/mcs/AssemblyInfo.cs | 0 .../Parser/mcs/ChangeLog | 0 .../Parser/mcs/CryptoConvert.cs | 0 .../Parser/mcs/Makefile | 0 .../Parser/mcs/MonoSymbolFile.cs | 0 .../Parser/mcs/MonoSymbolTable.cs | 0 .../Parser/mcs/MonoSymbolWriter.cs | 0 .../Parser/mcs/NOTES | 0 .../Parser/mcs/OPTIMIZE | 0 .../Parser/mcs/OTODO | 0 .../Parser/mcs/PLAN | 0 .../Parser/mcs/README | 0 .../Parser/mcs/TODO | 0 .../Parser/mcs/anonymous.cs | 109 +- .../Parser/mcs/argument.cs | 125 +- .../Parser/mcs/assembly.cs | 0 .../Parser/mcs/assign.cs | 51 +- .../Parser/mcs/async.cs | 304 +- .../Parser/mcs/attribute.cs | 39 +- .../Parser/mcs/cfold.cs | 0 .../Parser/mcs/class.cs | 28 +- .../Parser/mcs/codegen.cs | 486 +- .../Parser/mcs/compiler.doc | 0 .../Parser/mcs/complete.cs | 15 +- .../Parser/mcs/const.cs | 0 .../Parser/mcs/constant.cs | 32 +- .../Parser/mcs/context.cs | 72 +- .../Parser/mcs/convert.cs | 3 +- .../Parser/mcs/cs-parser.cs | 8840 +++++++++-------- .../Parser/mcs/cs-parser.jay | 383 +- .../Parser/mcs/cs-tokenizer.cs | 129 +- .../Parser/mcs/decl.cs | 33 +- .../Parser/mcs/delegate.cs | 16 +- .../Parser/mcs/dmcs.csproj | 0 .../Parser/mcs/dmcs.exe.config | 0 .../Parser/mcs/dmcs.exe.sources | 0 .../Parser/mcs/dmcs.sln | 0 .../Parser/mcs/doc-bootstrap.cs | 0 .../Parser/mcs/doc.cs | 0 .../Parser/mcs/driver.cs | 0 .../Parser/mcs/dynamic.cs | 19 +- .../Parser/mcs/ecore.cs | 510 +- .../Parser/mcs/enum.cs | 5 + .../Parser/mcs/eval.cs | 7 + .../Parser/mcs/expression.cs | 1119 ++- .../Parser/mcs/field.cs | 0 .../Parser/mcs/flowanalysis.cs | 115 +- .../Parser/mcs/generic.cs | 34 +- .../Parser/mcs/gmcs.csproj | 0 .../Parser/mcs/gmcs.exe.config | 28 +- .../Parser/mcs/gmcs.exe.sources | 0 .../Parser/mcs/gmcs.sln | 0 .../Parser/mcs/gmcs.userprefs | 0 .../Parser/mcs/gmcs2.csproj | 0 .../Parser/mcs/hosting.cs | 0 .../Parser/mcs/import.cs | 27 +- .../Parser/mcs/iterators.cs | 253 +- .../Parser/mcs/lambda.cs | 6 +- .../Parser/mcs/lambda.todo | 0 .../Parser/mcs/linq.cs | 0 .../Parser/mcs/literal.cs | 0 .../Parser/mcs/location.cs | 19 +- .../Parser/mcs/membercache.cs | 0 .../Parser/mcs/method.cs | 101 +- .../Parser/mcs/modifiers.cs | 0 .../Parser/mcs/namespace.cs | 50 +- .../Parser/mcs/nullable.cs | 194 +- .../Parser/mcs/outline.cs | 0 .../Parser/mcs/parameter.cs | 32 +- .../Parser/mcs/pending.cs | 90 +- .../Parser/mcs/property.cs | 6 +- .../Parser/mcs/reflection.cs | 0 .../Parser/mcs/repl.txt | 0 .../Parser/mcs/report.cs | 8 +- .../Parser/mcs/rootcontext.cs | 0 .../Parser/mcs/roottypes.cs | 2 +- .../Parser/mcs/smcs.exe.sources | 0 .../Parser/mcs/smcs.exe.sources-xml | 0 .../Parser/mcs/statement.cs | 297 +- .../Parser/mcs/support.cs | 2 +- .../Parser/mcs/symbolwriter.cs | 0 .../Parser/mcs/typemanager.cs | 10 + .../Parser/mcs/typespec.cs | 16 +- .../Parser/mcs/visit.cs | 5 + .../Parser/mcs/y.output | 0 .../Properties/AssemblyInfo.cs | 4 +- .../Refactoring/Action.cs | 0 .../ContextAction/AddAnotherAccessor.cs | 4 +- .../ContextAction/CheckIfParameterIsNull.cs | 4 +- .../ContextAction/ConvertDecToHex.cs | 0 .../ContextAction/ConvertForeachToFor.cs | 0 .../ContextAction/ConvertHexToDec.cs | 0 .../ContextAction/CreateBackingStore.cs | 0 .../ContextAction/CreateEventInvocator.cs | 0 .../Refactoring/ContextAction/CreateField.cs | 0 .../ContextAction/CreateLocalVariable.cs | 0 .../ContextAction/CreateProperty.cs | 0 .../ContextAction/FlipOperatorArguments.cs | 0 .../ContextAction/GenerateGetter.cs | 0 .../ContextAction/GenerateSwitchLabels.cs | 4 +- .../InsertAnonymousMethodSignature.cs | 4 +- .../ContextAction/IntroduceFormatItem.cs | 6 +- .../Refactoring/ContextAction/InvertIf.cs | 0 .../ContextAction/RemoveBackingStore.cs | 7 +- .../Refactoring/ContextAction/RemoveBraces.cs | 2 +- .../ContextAction/ReplaceEmptyString.cs | 0 .../SplitDeclarationAndAssignment.cs | 0 .../Refactoring/ContextAction/SplitString.cs | 10 +- .../ContextAction/UseExplicitType.cs | 0 .../ContextAction/UseVarKeyword.cs | 0 .../Refactoring/CreateLinkAction.cs | 0 .../Refactoring/FormatTextAction.cs | 0 .../Refactoring/IActionFactory.cs | 0 .../Refactoring/IContextAction.cs | 0 .../Refactoring/NodeOutputAction.cs | 27 +- .../Refactoring/NodeSelectionAction.cs | 0 .../Refactoring/RefactoringContext.cs | 19 +- .../Refactoring/Script.cs | 4 +- .../Refactoring/TextReplaceAction.cs | 0 .../Refactoring/TypeSystemAstBuilder.cs | 733 ++ .../Resolver/AliasNamespaceReference.cs | 72 + .../Resolver/CSharpAttribute.cs | 96 +- .../Resolver/CSharpInvocationResolveResult.cs | 89 + .../Resolver/CSharpResolver.cs | 1220 ++- .../CompositeResolveVisitorNavigator.cs | 63 + .../Resolver/ConstantValues.cs | 179 +- .../Resolver/ConversionResolveResult.cs | 49 + .../Resolver/Conversions.cs | 1140 +++ .../Resolver/DetectSkippableNodesNavigator.cs | 88 + .../Resolver/ErrorResolveResult.cs | 43 + .../Resolver/FindReferenceSearchScope.cs | 51 + .../Resolver/FindReferencedEntities.cs | 68 + .../Resolver/FindReferences.cs | 787 ++ .../Resolver/IResolveVisitorNavigator.cs | 104 + .../Resolver/ITypeOrNamespaceReference.cs | 40 + .../Resolver/LambdaResolveResult.cs | 77 + ICSharpCode.NRefactory.CSharp/Resolver/Log.cs | 80 + .../Resolver/MapTypeIntoNewContext.cs | 19 +- .../Resolver/MemberLookup.cs | 569 ++ .../MemberTypeOrNamespaceReference.cs | 151 + .../Resolver/MethodGroupResolveResult.cs | 222 + .../NodeListResolveVisitorNavigator.cs | 76 + .../Resolver/OperatorResolveResult.cs | 109 + .../Resolver/OverloadResolution.cs | 304 +- .../Resolver/OverloadResolutionErrors.cs | 19 +- .../Resolver/ResolveAtLocation.cs | 87 + .../Resolver/ResolveVisitor.cs | 3383 +++++++ .../Resolver/SimpleNameLookupMode.cs | 47 + .../SimpleTypeOrNamespaceReference.cs | 142 + .../Resolver/TypeInference.cs | 306 +- .../Resolver/UsingScope.cs | 20 +- .../CSDemo.Designer.cs | 44 +- ICSharpCode.NRefactory.Demo/CSDemo.cs | 96 +- .../ICSharpCode.NRefactory.Demo.csproj | 8 +- .../MainForm.Designer.cs | 20 +- ICSharpCode.NRefactory.Demo/MainForm.cs | 19 +- ICSharpCode.NRefactory.Demo/Program.cs | 19 +- .../VBAstView.Designer.cs | 19 +- ICSharpCode.NRefactory.Demo/VBAstView.cs | 19 +- .../VBDemo.Designer.cs | 19 +- ICSharpCode.NRefactory.Demo/VBDemo.cs | 21 +- .../VBEditDialog.Designer.cs | 19 +- ICSharpCode.NRefactory.Demo/VBEditDialog.cs | 19 +- .../Analysis/DefiniteAssignmentTests.cs | 19 +- .../CSharp/AstStructureTests.cs | 19 +- .../CSharp/CSharpOutputVisitorTests.cs | 53 + .../CSharp/CodeDomConvertVisitorTests.cs | 177 + .../CSharp/InsertParenthesesVisitorTests.cs | 23 +- .../AliasReferenceExpressionTests.cs | 53 - .../AnonymousMethodExpressionTests.cs | 82 + .../Parser/Expression/AnonymousMethodTests.cs | 56 - .../AnonymousTypeCreateExpressionTests.cs | 40 + .../Expression/ArrayCreateExpressionTests.cs | 149 + .../ArrayObjectCreateExpressionTests.cs | 56 - .../Expression/AssignmentExpressionTests.cs | 29 +- .../BaseReferenceExpressionTests.cs | 19 +- .../BinaryOperatorExpressionTests.cs | 19 +- .../Parser/Expression/CastExpressionTests.cs | 19 +- .../Expression/CheckedExpressionTests.cs | 19 +- .../Expression/ConditionalExpressionTests.cs | 19 +- .../Expression/DefaultValueExpressionTests.cs | 19 +- .../Expression/IdentifierExpressionTests.cs | 19 +- .../Expression/IndexerExpressionTests.cs | 19 +- .../Expression/InvocationExpressionTests.cs | 31 +- .../Parser/Expression/IsExpressionTests.cs | 19 +- .../Expression/LambdaExpressionTests.cs | 43 +- .../MemberReferenceExpressionTests.cs | 36 +- .../Expression/ObjectCreateExpressionTests.cs | 252 + .../ParenthesizedExpressionTests.cs | 19 +- .../PointerReferenceExpressionTests.cs | 19 +- .../Expression/PrimitiveExpressionTests.cs | 27 +- .../Parser/Expression/QueryExpressionTests.cs | 86 +- .../Expression/SizeOfExpressionTests.cs | 19 +- .../Expression/StackAllocExpressionTests.cs | 19 +- .../ThisReferenceExpressionTests.cs | 19 +- .../Expression/TypeOfExpressionTests.cs | 19 +- .../TypeReferenceExpressionTests.cs | 19 +- .../UnaryOperatorExpressionTests.cs | 49 +- .../GeneralScope/AttributeSectionTests.cs | 98 +- .../GeneralScope/DelegateDeclarationTests.cs | 19 +- .../GeneralScope/NamespaceDeclarationTests.cs | 19 +- .../GeneralScope/TypeDeclarationTests.cs | 21 +- .../GeneralScope/UsingDeclarationTests.cs | 19 +- .../CSharp/Parser/ParseSelfTests.cs | 149 + .../CSharp/Parser/ParseUtil.cs | 21 +- .../Parser/Statements/BlockStatementTests.cs | 19 +- .../Statements/CheckedStatementTests.cs | 19 +- .../Parser/Statements/EmptyStatementTests.cs | 19 +- .../Statements/ExpressionStatementTests.cs | 19 +- .../Parser/Statements/FixedStatementTests.cs | 19 +- .../Parser/Statements/ForStatementTests.cs | 19 +- .../Parser/Statements/GotoStatementTests.cs | 20 +- .../Parser/Statements/IfElseStatementTests.cs | 19 +- .../Parser/Statements/LabelStatementTests.cs | 19 +- .../Parser/Statements/LockStatementTests.cs | 19 +- .../Parser/Statements/ReturnStatementTests.cs | 19 +- .../Parser/Statements/SwitchStatementTests.cs | 19 +- .../Parser/Statements/ThrowStatementTests.cs | 19 +- .../Statements/TryCatchStatementTests.cs | 19 +- .../Parser/Statements/UnsafeStatementTests.cs | 19 +- .../Parser/Statements/UsingStatementTests.cs | 19 +- .../VariableDeclarationStatementTests.cs | 57 +- .../Parser/Statements/WhileStatementTests.cs | 19 +- .../Parser/Statements/YieldStatementTests.cs | 22 +- .../ConstructorDeclarationTests.cs | 19 +- .../TypeMembers/DestructorDeclarationTests.cs | 19 +- .../TypeMembers/EventDeclarationTests.cs | 19 +- .../TypeMembers/FieldDeclarationTests.cs | 19 +- .../TypeMembers/IndexerDeclarationTests.cs | 19 +- .../TypeMembers/MethodDeclarationTests.cs | 51 +- .../TypeMembers/OperatorDeclarationTests.cs | 19 +- .../TypeMembers/PropertyDeclarationTests.cs | 31 +- .../Parser/TypeSystemConvertVisitorTests.cs | 53 +- .../Refactoring/TypeSystemAstBuilderTests.cs | 212 + .../CSharp/Resolver/ArrayCreateTests.cs | 116 + .../CSharp/Resolver/AttributeTests.cs | 49 +- .../CSharp/Resolver/BinaryOperatorTests.cs | 254 +- .../CSharp/Resolver/CastTests.cs | 50 +- .../Resolver/ConditionalOperatorTests.cs | 97 +- .../CSharp/Resolver/ConversionsTest.cs | 338 +- .../CSharp/Resolver/ExtensionMethodTests.cs | 52 +- .../CSharp/Resolver/InvocationTests.cs | 255 +- .../CSharp/Resolver/LambdaTests.cs | 173 +- .../CSharp/Resolver/LinqTests.cs | 223 +- .../Resolver/LocalTypeInferenceTests.cs | 20 +- .../CSharp/Resolver/NameLookupTests.cs | 115 +- .../CSharp/Resolver/ObjectCreationTests.cs | 114 +- .../Resolver/OverloadResolutionTests.cs | 123 +- .../CSharp/Resolver/ResolveAtLocationTests.cs | 121 + .../CSharp/Resolver/ResolverTestBase.cs | 128 +- .../CSharp/Resolver/TypeInferenceTests.cs | 179 +- .../CSharp/Resolver/UnaryOperatorTests.cs | 113 +- .../CSharp/Resolver/UnsafeCodeTests.cs | 20 +- .../Documentation/IDStringTests.cs | 335 + .../TestBlankLineFormatting.cs | 1 - .../FormattingTests/TestBraceStlye.cs | 3 - .../FormattingTests/TestFormattingBugs.cs | 9 +- .../FormattingTests/TestSpacingVisitor.cs | 160 +- .../TestStatementIndentation.cs | 3 - .../TestTypeLevelIndentation.cs | 20 +- .../FormattingTests/TextEditorTestAdapter.cs | 262 +- .../ICSharpCode.NRefactory.Tests.csproj | 51 +- .../TypeSystem/CecilLoaderTests.cs | 40 +- .../TypeSystem/GetAllBaseTypesTest.cs | 56 +- .../TypeSystem/GetMembersTests.cs | 62 +- .../TypeSystem/ReflectionHelperTests.cs | 19 +- .../TypeSystem/SerializedCecilLoaderTests.cs | 42 + .../TypeSystem/StructureTests.cs | 21 +- .../TypeSystem/TestInterningProvider.cs | 19 +- .../TypeSystem/TypeSystemTests.TestCase.cs | 38 +- .../TypeSystem/TypeSystemTests.cs | 156 +- ICSharpCode.NRefactory.Tests/Untested.cs | 41 - .../Utils/CSharpPrimitiveCastTests.cs | 19 +- .../Utils/TreeTraversalTests.cs | 19 +- .../ICSharpCode.NRefactory.VB.Tests.csproj | 21 +- .../Lexer/LexerPositionTests.cs | 28 +- ICSharpCode.NRefactory.VB/Ast/AstLocation.cs | 137 - ICSharpCode.NRefactory.VB/Ast/AstNode.cs | 47 +- .../Ast/AstNodeCollection.cs | 21 +- ICSharpCode.NRefactory.VB/Ast/Comment.cs | 67 + ICSharpCode.NRefactory.VB/Ast/Enums.cs | 219 +- .../AnonymousObjectCreationExpression.cs | 41 + .../Ast/Expressions/ArrayCreateExpression.cs | 64 + .../Expressions/ArrayInitializerExpression.cs | 53 + .../Ast/Expressions/AssignmentExpression.cs | 44 + .../Expressions/BinaryOperatorExpression.cs | 110 + .../Ast/Expressions/CastExpression.cs | 95 + .../CollectionRangeVariableDeclaration.cs | 42 + .../Ast/Expressions/ConditionalExpression.cs | 44 + .../Ast/Expressions/EmptyExpression.cs | 59 + .../Ast/Expressions/Expression.cs | 76 +- .../Expressions/FieldInitializerExpression.cs | 49 + .../Ast/Expressions/GetTypeExpression.cs | 31 + .../Expressions/GetXmlNamespaceExpression.cs | 32 + .../Ast/Expressions/IdentifierExpression.cs | 39 + .../Ast/Expressions/InstanceExpression.cs | 61 + .../Ast/Expressions/InvocationExpression.cs | 52 + .../Ast/Expressions/LambdaExpression.cs | 124 + .../Ast/Expressions/MemberAccessExpression.cs | 42 + .../Expressions/NamedArgumentExpression.cs | 28 +- .../Expressions/ObjectCreationExpression.cs | 59 + .../Expressions/ParenthesizedExpression.cs | 34 + .../Ast/Expressions/PrimitiveExpression.cs | 16 +- .../Ast/Expressions/QueryExpression.cs | 348 + .../Ast/Expressions/SimpleNameExpression.cs | 11 +- .../Ast/Expressions/TypeOfIsExpression.cs | 37 + .../Expressions/TypeReferenceExpression.cs | 8 +- .../Expressions/UnaryOperatorExpression.cs | 80 + .../Ast/Expressions/VariableInitializer.cs | 46 + .../Ast/Expressions/XmlIdentifier.cs | 12 +- .../Ast/Expressions/XmlLiteralString.cs | 12 +- .../Ast/General/Attribute.cs | 9 +- .../Ast/General/AttributeBlock.cs | 2 +- .../Ast/General/AttributedNode.cs | 6 +- .../Ast/General/CompilationUnit.cs | 10 +- .../Ast/General/EventMemberSpecifier.cs | 39 + .../Ast/General/InterfaceMemberSpecifier.cs | 47 + .../Ast/General/ParameterDeclaration.cs | 6 +- .../Ast/General/TypeParameterDeclaration.cs | 6 +- ICSharpCode.NRefactory.VB/Ast/Generated.cs | 2 +- .../Ast/GlobalScope/DelegateDeclaration.cs | 2 +- .../Ast/GlobalScope/EnumDeclaration.cs | 6 +- .../Ast/GlobalScope/EnumMemberDeclaration.cs | 2 +- .../Ast/GlobalScope/ImportsClause.cs | 4 +- .../Ast/GlobalScope/ImportsStatement.cs | 2 +- .../Ast/GlobalScope/NamespaceDeclaration.cs | 4 +- .../Ast/GlobalScope/OptionStatement.cs | 2 +- .../Ast/GlobalScope/TypeDeclaration.cs | 21 +- ICSharpCode.NRefactory.VB/Ast/INullable.cs | 2 +- ICSharpCode.NRefactory.VB/Ast/Identifier.cs | 21 +- .../Ast/Statements/BlockStatement.cs | 32 +- .../Ast/Statements/ContinueStatement.cs | 50 + .../Ast/Statements/DoLoopStatement.cs | 33 + .../Ast/Statements/ExitStatement.cs | 55 + .../Ast/Statements/ExpressionStatement.cs | 40 + .../Ast/Statements/ForEachStatement.cs | 38 + .../Ast/Statements/ForStatement.cs | 45 + .../Ast/Statements/GoToStatement.cs | 27 + .../Ast/Statements/IfElseStatement.cs | 39 + .../Statements/LabelDeclarationStatement.cs | 35 + .../Statements/LocalDeclarationStatement.cs | 37 + .../Ast/Statements/ReturnStatement.cs | 43 + .../Ast/Statements/SelectStatement.cs | 147 + .../Ast/Statements/Statement.cs | 26 +- .../Ast/Statements/SyncLockStatement.cs | 36 + .../Ast/Statements/ThrowStatement.cs | 43 + .../Ast/Statements/TryStatement.cs | 67 + .../Ast/Statements/UsingStatement.cs | 33 + .../Ast/Statements/WhileStatement.cs | 31 + .../Ast/Statements/WithStatement.cs | 36 + .../Ast/Statements/YieldStatement.cs | 44 + .../Ast/TypeMembers/Accessor.cs | 49 + .../Ast/TypeMembers/ConstructorDeclaration.cs | 45 + .../Ast/TypeMembers/EventDeclaration.cs | 59 + .../TypeMembers/ExternalMethodDeclaration.cs | 71 + .../Ast/TypeMembers/FieldDeclaration.cs | 81 + .../Ast/TypeMembers/MethodDeclaration.cs | 72 + .../Ast/TypeMembers/OperatorDeclaration.cs | 83 + .../Ast/TypeMembers/PropertyDeclaration.cs | 57 + .../Ast/TypeMembers/VariableDeclarator.cs | 63 + .../Ast/TypeName/AstType.cs | 84 +- .../Ast/TypeName/ComposedType.cs | 6 +- .../Ast/TypeName/PrimitiveType.cs | 12 +- .../Ast/TypeName/QualifiedType.cs | 4 +- .../Ast/TypeName/SimpleType.cs | 4 +- .../Ast/VBModifierToken.cs | 36 +- ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs | 16 +- .../AstBuilder/ExpressionBuilder.cs | 2 +- .../AstBuilder/StatementBuilder.cs | 2 +- ICSharpCode.NRefactory.VB/IAstVisitor.cs | 91 +- .../ICSharpCode.NRefactory.VB.csproj | 74 +- ICSharpCode.NRefactory.VB/Lexer/Block.cs | 6 +- .../Lexer/ExpressionFinder.cs | 4 +- .../Lexer/ExpressionFinderState.cs | 2 +- ICSharpCode.NRefactory.VB/Lexer/Extensions.cs | 2 +- .../Lexer/LATextReader.cs | 2 +- .../Lexer/LookupTable.cs | 2 +- .../Lexer/SavepointEventArgs.cs | 6 +- .../Lexer/Special/BlankLine.cs | 2 +- .../Lexer/Special/Comment.cs | 2 +- .../Lexer/Special/CommentType.cs | 2 +- .../Lexer/Special/ISpecial.cs | 2 +- .../Lexer/Special/PreProcessingDirective.cs | 2 +- .../Lexer/Special/SpecialTracker.cs | 2 +- .../Lexer/Special/TagComment.cs | 2 +- ICSharpCode.NRefactory.VB/Lexer/Token.cs | 18 +- ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs | 46 +- .../Lexer/VBLexerMemento.cs | 2 +- .../Lexer/XmlModeInfo.cs | 2 +- .../OutputVisitor/IOutputFormatter.cs | 7 +- .../OutputVisitor/OutputVisitor.cs | 2505 ++++- .../TextWriterOutputFormatter.cs | 18 + .../OutputVisitor/VBFormattingOptions.cs | 2 +- ICSharpCode.NRefactory.VB/Parser/Errors.cs | 2 +- ICSharpCode.NRefactory.VB/Parser/VBParser.cs | 2 +- .../PrettyPrinter/AbstractOutputFormatter.cs | 2 +- .../AbstractPrettyPrintOptions.cs | 2 +- .../PrettyPrinter/IOutputAstVisitor.cs | 2 +- .../PrettyPrinter/SpecialNodesInserter.cs | 2 +- .../VBNet/VBNetOutputFormatter.cs | 2 +- .../PrettyPrinter/VBNet/VBNetOutputVisitor.cs | 2 +- .../VBNet/VBNetPrettyPrintOptions.cs | 2 +- ICSharpCode.NRefactory.VB/VBParser.cs | 2 +- .../Visitors/CSharpToVBConverterVisitor.cs | 2211 +++++ ICSharpCode.NRefactory.snk | Bin 0 -> 596 bytes .../CSharp/Ast/AstLocation.cs | 137 - .../CSharp/Formatter/ITextEditorAdapter.cs | 83 - .../CSharp/OutputVisitor/IOutputFormatter.cs | 44 - .../StringBuilderOutputFormatter.cs | 158 - .../Refactoring/TypeSystemAstBuilder.cs | 218 - .../Resolver/AliasNamespaceReference.cs | 51 - .../CSharp/Resolver/AmbiguousResolveResult.cs | 33 - .../Resolver/ByReferenceResolveResult.cs | 32 - .../CSharp/Resolver/ConstantResolveResult.cs | 34 - .../CSharp/Resolver/Conversions.cs | 466 - .../CSharp/Resolver/ErrorResolveResult.cs | 22 - .../Resolver/IResolveVisitorNavigator.cs | 52 - .../Resolver/ITypeOrNamespaceReference.cs | 24 - .../CSharp/Resolver/LocalResolveResult.cs | 47 - .../CSharp/Resolver/MemberLookup.cs | 274 - .../CSharp/Resolver/MemberResolveResult.cs | 62 - .../MemberTypeOrNamespaceReference.cs | 79 - .../Resolver/MethodGroupResolveResult.cs | 61 - .../CSharp/Resolver/NamespaceResolveResult.cs | 30 - .../NodeListResolveVisitorNavigator.cs | 43 - .../CSharp/Resolver/ResolveResult.cs | 45 - .../CSharp/Resolver/ResolveVisitor.cs | 1265 --- .../SimpleTypeOrNamespaceReference.cs | 74 - .../CSharp/Resolver/TypeResolveResult.cs | 19 - .../Completion/DisplayFlags.cs | 38 + .../Completion/ICompletionData.cs | 47 + .../Completion/ICompletionDataFactory.cs | 49 + .../Completion/IEntityCompletionData.cs | 37 + .../Documentation/IDStringProvider.cs | 284 + .../Documentation/XmlDocumentationProvider.cs | 81 +- .../Editor}/IDocument.cs | 72 +- .../Editor/IDocumentLine.cs | 55 + ICSharpCode.NRefactory/Editor/ISegment.cs | 70 + .../Editor}/ITextAnchor.cs | 43 +- .../Editor}/ITextSource.cs | 45 +- .../Editor}/ReadOnlyDocument.cs | 70 +- .../Editor}/StringTextSource.cs | 33 +- .../Editor}/TextChangeEventArgs.cs | 23 +- .../ICSharpCode.NRefactory.csproj | 313 +- .../PatternMatching/AnyNode.cs | 24 +- .../PatternMatching/Backreference.cs | 59 +- .../PatternMatching/BacktrackingInfo.cs | 19 +- .../PatternMatching/Choice.cs | 24 +- .../PatternMatching/INode.cs | 19 +- .../PatternMatching/IPatternAstVisitor.cs | 21 - .../PatternMatching/Match.cs | 19 +- .../PatternMatching/NamedNode.cs | 24 +- .../PatternMatching/OptionalNode.cs | 24 +- .../PatternMatching/Pattern.cs | 31 +- .../PatternMatching/Repeat.cs | 24 +- .../Properties/AssemblyInfo.cs | 4 +- .../{CSharp/Ast => }/Role.cs | 19 +- .../Semantics/AmbiguousResolveResult.cs | 48 + .../Semantics/ArrayAccessResolveResult.cs | 50 + .../Semantics/ArrayCreateResolveResult.cs | 58 + .../Semantics/ByReferenceResolveResult.cs | 65 + .../Semantics/ConstantResolveResult.cs | 49 + .../Semantics/InvocationResolveResult.cs | 55 + .../Semantics/LocalResolveResult.cs | 77 + .../Semantics/MemberResolveResult.cs | 101 + .../Semantics/NamespaceResolveResult.cs | 45 + .../Semantics/ResolveResult.cs | 72 + .../Semantics/TypeOfResolveResult.cs | 44 + .../Semantics/TypeResolveResult.cs | 43 + .../UnknownMemberResolveResult.cs | 21 +- .../TextLocation.cs | 21 +- .../TypeSystem/Accessibility.cs | 19 +- .../TypeSystem/ArrayType.cs | 55 +- .../TypeSystem/ByReferenceType.cs | 63 +- .../TypeSystem/CecilLoader.cs | 336 +- .../TypeSystem/ClassType.cs | 17 - .../TypeSystem/DomRegion.cs | 38 +- .../TypeSystem/EntityType.cs | 19 +- ICSharpCode.NRefactory/TypeSystem/Error.cs | 36 +- .../TypeSystem/ExtensionMethods.cs | 108 +- .../TypeSystem/IAccessor.cs | 19 +- .../TypeSystem/IAnnotatable.cs | 21 +- .../TypeSystem/IAttribute.cs | 25 +- .../TypeSystem/IConstantValue.cs | 51 +- .../TypeSystem/IConversions.cs | 16 - .../TypeSystem/IDocumentationProvider.cs | 19 +- ICSharpCode.NRefactory/TypeSystem/IEntity.cs | 25 +- ICSharpCode.NRefactory/TypeSystem/IEvent.cs | 19 +- .../IExplicitInterfaceImplementation.cs | 19 +- ICSharpCode.NRefactory/TypeSystem/IField.cs | 24 +- .../TypeSystem/IFreezable.cs | 19 +- .../TypeSystem/IInterningProvider.cs | 19 +- ICSharpCode.NRefactory/TypeSystem/IMember.cs | 19 +- ICSharpCode.NRefactory/TypeSystem/IMethod.cs | 19 +- .../TypeSystem/INamedElement.cs | 19 +- .../TypeSystem/IParameter.cs | 24 +- .../TypeSystem/IParameterizedMember.cs | 19 +- .../TypeSystem/IParsedFile.cs | 35 +- .../TypeSystem/IProjectContent.cs | 39 +- .../TypeSystem/IProperty.cs | 19 +- .../TypeSystem/ISupportsInterning.cs | 19 +- .../ISynchronizedTypeResolveContext.cs | 19 +- ICSharpCode.NRefactory/TypeSystem/IType.cs | 257 +- .../TypeSystem/ITypeDefinition.cs | 30 +- .../TypeSystem/ITypeParameter.cs | 31 +- .../TypeSystem/ITypeReference.cs | 24 +- .../TypeSystem/ITypeResolveContext.cs | 29 +- .../TypeSystem/IVariable.cs | 21 +- .../Implementation/AbstractFreezable.cs | 27 +- .../Implementation/AbstractMember.cs | 24 +- .../TypeSystem/Implementation/AbstractType.cs | 55 +- .../Implementation/BaseTypeCollector.cs | 81 + .../CompositeTypeResolveContext.cs | 51 +- .../Implementation/CompoundTypeDefinition.cs | 151 + .../Implementation/DefaultAccessor.cs | 20 +- .../Implementation/DefaultAttribute.cs | 41 +- .../TypeSystem/Implementation/DefaultEvent.cs | 20 +- .../DefaultExplicitInterfaceImplementation.cs | 20 +- .../TypeSystem/Implementation/DefaultField.cs | 26 +- .../Implementation/DefaultMethod.cs | 25 +- .../Implementation/DefaultParameter.cs | 40 +- .../Implementation/DefaultProperty.cs | 20 +- .../Implementation/DefaultTypeDefinition.cs | 427 +- .../Implementation/DefaultTypeParameter.cs | 211 +- .../Implementation/GetClassTypeReference.cs | 72 +- .../Implementation/GetMembersHelper.cs | 281 + .../MethodTypeParameterSubstitution.cs | 34 - .../Implementation}/MinimalResolveContext.cs | 81 +- .../Implementation/NestedTypeReference.cs | 32 +- .../Implementation/ProxyTypeResolveContext.cs | 28 +- .../Implementation/SimpleConstantValue.cs | 37 +- .../Implementation/SimpleInterningProvider.cs | 48 +- .../Implementation/SimpleProjectContent.cs | 157 +- .../Implementation/SpecializedEvent.cs | 76 +- .../Implementation/SpecializedField.cs | 72 +- .../Implementation/SpecializedMember.cs | 286 + .../Implementation/SpecializedMethod.cs | 140 +- .../Implementation/SpecializedProperty.cs | 83 +- .../SubstitutionTypeReference.cs | 34 +- .../TypeParameterSubstitution.cs | 95 + .../TypeSystem/Implementation/TypeStorage.cs | 64 +- .../Implementation/TypeWithElementType.cs | 22 +- .../Implementation/VoidTypeDefinition.cs | 42 +- .../TypeSystem/IntersectionType.cs | 60 +- .../TypeSystem/KnownTypeReference.cs | 102 +- .../TypeSystem/NullableType.cs | 30 +- .../TypeSystem/ParameterListComparer.cs | 37 +- .../TypeSystem/ParameterizedType.cs | 280 +- .../TypeSystem/PointerType.cs | 64 +- .../TypeSystem/ReflectionHelper.cs | 91 +- .../ReflectionNameParseException.cs | 19 +- .../TypeSystem/SharedTypes.cs | 99 +- ICSharpCode.NRefactory/TypeSystem/TypeKind.cs | 81 + .../TypeSystem/TypeVisitor.cs | 19 +- .../Utils/7BitEncodedInts.cs | 117 + ICSharpCode.NRefactory/Utils/BitVector16.cs | 20 +- ICSharpCode.NRefactory/Utils/BusyManager.cs | 19 +- .../Utils/CSharpPrimitiveCast.cs | 19 +- ICSharpCode.NRefactory/Utils/CacheManager.cs | 147 +- .../Utils/DotNet35Compat.cs | 58 - ICSharpCode.NRefactory/Utils/EmptyList.cs | 110 +- .../Utils/ExtensionMethods.cs | 28 +- .../Utils/FastSerializer.cs | 1334 +++ ICSharpCode.NRefactory/Utils/GraphVizGraph.cs | 19 +- ICSharpCode.NRefactory/Utils/Platform.cs | 21 +- .../Utils/ReferenceComparer.cs | 39 + ICSharpCode.NRefactory/Utils/TreeTraversal.cs | 19 +- NRefactory.sln | 85 +- doc/TODO | 19 +- 700 files changed, 43509 insertions(+), 15250 deletions(-) delete mode 100644 ICSharpCode.Editor/ICSharpCode.Editor.csproj delete mode 100644 ICSharpCode.Editor/IDocumentLine.cs delete mode 100644 ICSharpCode.Editor/ISegment.cs delete mode 100644 ICSharpCode.Editor/ITextEditor.cs delete mode 100644 ICSharpCode.Editor/LinkedElement.cs create mode 100644 ICSharpCode.NRefactory.CSharp/.gitignore rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Analysis/ControlFlow.cs (94%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Analysis/DefiniteAssignmentAnalysis.cs (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/AstNode.cs (88%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/AstNodeCollection.cs (73%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/AstType.cs (81%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/CSharpModifierToken.cs (60%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/CSharpTokenNode.cs (85%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/CSharpUtil.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/CompilationUnit.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/ComposedType.cs (95%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/DepthFirstAstVisitor.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/ErrorNode.cs (91%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/AnonymousMethodExpression.cs (85%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/AnonymousTypeCreateExpression.cs (91%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/ArrayCreateExpression.cs (60%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/ArrayInitializerExpression.cs (88%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/AsExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/AssignmentExpression.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/BaseReferenceExpression.cs (88%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/BinaryOperatorExpression.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/CastExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/CheckedExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/ConditionalExpression.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/DefaultValueExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/DirectionExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/EmptyExpression.cs (88%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/Expression.cs (82%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/IdentifierExpression.cs (95%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/IndexerExpression.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/InvocationExpression.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/IsExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/LambdaExpression.cs (83%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/MemberReferenceExpression.cs (98%) create mode 100644 ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedArgumentExpression.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedExpression.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/NullReferenceExpression.cs (86%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/ObjectCreateExpression.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/ParenthesizedExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/PointerReferenceExpression.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/PrimitiveExpression.cs (86%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/QueryExpression.cs (86%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/SizeOfExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/StackAllocExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/ThisReferenceExpression.cs (88%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/TypeOfExpression.cs (98%) create mode 100644 ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeReferenceExpression.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/UnaryOperatorExpression.cs (90%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/UncheckedExpression.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Expressions/UndocumentedExpression.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/Attribute.cs (95%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/AttributeSection.cs (91%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/Comment.cs (81%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/Constraint.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/DelegateDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/ExternAliasDeclaration.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/NamespaceDeclaration.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/TypeDeclaration.cs (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/TypeParameterDeclaration.cs (57%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/UsingAliasDeclaration.cs (91%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/GeneralScope/UsingDeclaration.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/IAstVisitor.cs (86%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/IRelocatable.cs (95%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Identifier.cs (76%) create mode 100644 ICSharpCode.NRefactory.CSharp/Ast/IdentifierExpressionBackreference.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/MemberType.cs (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Modifiers.cs (83%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/NodeType.cs (93%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/ObservableAstVisitor.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/PrimitiveType.cs (84%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/SimpleType.cs (94%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/BlockStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/BreakStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/CheckedStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/ContinueStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/DoWhileStatement.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/EmptyStatement.cs (86%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/ExpressionStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/FixedStatement.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/ForStatement.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/ForeachStatement.cs (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/GotoStatement.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/IfElseStatement.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/LabelStatement.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/LockStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/ReturnStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/Statement.cs (87%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/SwitchStatement.cs (95%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/ThrowStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/TryCatchStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/UncheckedStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/UnsafeStatement.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/UsingStatement.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/VariableDeclarationStatement.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/WhileStatement.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/Statements/YieldBreakStatement.cs (98%) rename ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldStatement.cs => ICSharpCode.NRefactory.CSharp/Ast/Statements/YieldReturnStatement.cs (92%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/Accessor.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/AttributedNode.cs (62%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/ConstructorDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/DestructorDeclaration.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/EnumMemberDeclaration.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/EventDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/FieldDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/FixedFieldDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/FixedVariableInitializer.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/IndexerDeclaration.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/MemberDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/MethodDeclaration.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/OperatorDeclaration.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/ParameterDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/PropertyDeclaration.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Ast/TypeMembers/VariableInitializer.cs (92%) create mode 100644 ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Formatter/AstFormattingVisitor.cs (88%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Formatter/CSharpFormattingOptions.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Formatter/Indent.cs (100%) create mode 100644 ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj rename ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs => ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs (88%) create mode 100644 ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs create mode 100644 ICSharpCode.NRefactory.CSharp/OutputVisitor/IOutputFormatter.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/OutputVisitor/InsertParenthesesVisitor.cs (92%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/OutputVisitor/TextWriterOutputFormatter.cs (75%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/CSharpParser.cs (81%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/ParsedFile.cs (56%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/TypeSystemConvertVisitor.cs (80%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/AssemblyInfo.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/ChangeLog (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/CryptoConvert.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/Makefile (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/MonoSymbolFile.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/MonoSymbolTable.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/MonoSymbolWriter.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/NOTES (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/OPTIMIZE (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/OTODO (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/PLAN (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/README (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/TODO (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/anonymous.cs (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/argument.cs (86%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/assembly.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/assign.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/async.cs (64%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/attribute.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/cfold.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/class.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/codegen.cs (60%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/compiler.doc (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/complete.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/const.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/constant.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/context.cs (91%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/convert.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/cs-parser.cs (65%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/cs-parser.jay (94%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/cs-tokenizer.cs (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/decl.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/delegate.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/dmcs.csproj (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/dmcs.exe.config (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/dmcs.exe.sources (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/dmcs.sln (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/doc-bootstrap.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/doc.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/driver.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/dynamic.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/ecore.cs (94%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/enum.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/eval.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/expression.cs (94%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/field.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/flowanalysis.cs (94%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/generic.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/gmcs.csproj (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/gmcs.exe.config (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/gmcs.exe.sources (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/gmcs.sln (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/gmcs.userprefs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/gmcs2.csproj (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/hosting.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/import.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/iterators.cs (92%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/lambda.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/lambda.todo (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/linq.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/literal.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/location.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/membercache.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/method.cs (96%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/modifiers.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/namespace.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/nullable.cs (91%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/outline.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/parameter.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/pending.cs (92%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/property.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/reflection.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/repl.txt (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/report.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/rootcontext.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/roottypes.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/smcs.exe.sources (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/smcs.exe.sources-xml (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/statement.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/support.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/symbolwriter.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/typemanager.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/typespec.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/visit.cs (99%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Parser/mcs/y.output (100%) rename {ICSharpCode.Editor => ICSharpCode.NRefactory.CSharp}/Properties/AssemblyInfo.cs (88%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/Action.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/AddAnotherAccessor.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/CheckIfParameterIsNull.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/ConvertDecToHex.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/ConvertForeachToFor.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/ConvertHexToDec.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/CreateBackingStore.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/CreateEventInvocator.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/CreateField.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/CreateLocalVariable.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/CreateProperty.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/FlipOperatorArguments.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/GenerateGetter.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/GenerateSwitchLabels.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/IntroduceFormatItem.cs (94%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/InvertIf.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/RemoveBackingStore.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/RemoveBraces.cs (97%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/ReplaceEmptyString.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/SplitString.cs (82%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/UseExplicitType.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/ContextAction/UseVarKeyword.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/CreateLinkAction.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/FormatTextAction.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/IActionFactory.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/IContextAction.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/NodeOutputAction.cs (84%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/NodeSelectionAction.cs (100%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/RefactoringContext.cs (90%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/Script.cs (98%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Refactoring/TextReplaceAction.cs (100%) create mode 100644 ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/AliasNamespaceReference.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/CSharpAttribute.cs (52%) create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/CSharpResolver.cs (62%) create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/CompositeResolveVisitorNavigator.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/ConstantValues.cs (77%) create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/ConversionResolveResult.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/DetectSkippableNodesNavigator.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/FindReferenceSearchScope.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/FindReferencedEntities.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/IResolveVisitorNavigator.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/ITypeOrNamespaceReference.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/Log.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/MapTypeIntoNewContext.cs (56%) create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/NodeListResolveVisitorNavigator.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/OperatorResolveResult.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/OverloadResolution.cs (60%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/OverloadResolutionErrors.cs (58%) create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/SimpleNameLookupMode.cs create mode 100644 ICSharpCode.NRefactory.CSharp/Resolver/SimpleTypeOrNamespaceReference.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/TypeInference.cs (72%) rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.CSharp}/Resolver/UsingScope.cs (77%) create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs delete mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodExpressionTests.cs delete mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs delete mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs create mode 100644 ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs delete mode 100644 ICSharpCode.NRefactory.Tests/Untested.cs delete mode 100644 ICSharpCode.NRefactory.VB/Ast/AstLocation.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Comment.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/AnonymousObjectCreationExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayInitializerExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/AssignmentExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/BinaryOperatorExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/CollectionRangeVariableDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/ConditionalExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/EmptyExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/FieldInitializerExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/IdentifierExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/InstanceExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/InvocationExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/LambdaExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.VB}/Ast/Expressions/NamedArgumentExpression.cs (54%) create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/ObjectCreationExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/ParenthesizedExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/QueryExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs rename {ICSharpCode.NRefactory/CSharp => ICSharpCode.NRefactory.VB}/Ast/Expressions/TypeReferenceExpression.cs (76%) create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/UnaryOperatorExpression.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Expressions/VariableInitializer.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/ContinueStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/DoLoopStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/ExitStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/ExpressionStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/ForEachStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/ForStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/GoToStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/IfElseStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/LabelDeclarationStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/LocalDeclarationStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/ReturnStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/SyncLockStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/ThrowStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/TryStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/UsingStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/WhileStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/WithStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/Statements/YieldStatement.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/Accessor.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/EventDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/ExternalMethodDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/OperatorDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/PropertyDeclaration.cs create mode 100644 ICSharpCode.NRefactory.VB/Ast/TypeMembers/VariableDeclarator.cs create mode 100644 ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs create mode 100644 ICSharpCode.NRefactory.snk delete mode 100644 ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/ByReferenceResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/ConstantResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/ErrorResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/ITypeOrNamespaceReference.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/NamespaceResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs delete mode 100644 ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Completion/DisplayFlags.cs create mode 100644 ICSharpCode.NRefactory/Completion/ICompletionData.cs create mode 100644 ICSharpCode.NRefactory/Completion/ICompletionDataFactory.cs create mode 100644 ICSharpCode.NRefactory/Completion/IEntityCompletionData.cs create mode 100644 ICSharpCode.NRefactory/Documentation/IDStringProvider.cs rename {ICSharpCode.Editor => ICSharpCode.NRefactory/Editor}/IDocument.cs (74%) create mode 100644 ICSharpCode.NRefactory/Editor/IDocumentLine.cs create mode 100644 ICSharpCode.NRefactory/Editor/ISegment.cs rename {ICSharpCode.Editor => ICSharpCode.NRefactory/Editor}/ITextAnchor.cs (58%) rename {ICSharpCode.Editor => ICSharpCode.NRefactory/Editor}/ITextSource.cs (69%) rename {ICSharpCode.Editor => ICSharpCode.NRefactory/Editor}/ReadOnlyDocument.cs (73%) rename {ICSharpCode.Editor => ICSharpCode.NRefactory/Editor}/StringTextSource.cs (52%) rename {ICSharpCode.Editor => ICSharpCode.NRefactory/Editor}/TextChangeEventArgs.cs (50%) delete mode 100644 ICSharpCode.NRefactory/PatternMatching/IPatternAstVisitor.cs rename ICSharpCode.NRefactory/{CSharp/Ast => }/Role.cs (58%) create mode 100644 ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/ArrayAccessResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/ArrayCreateResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/ByReferenceResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/ConstantResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/ResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/TypeOfResolveResult.cs create mode 100644 ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs rename ICSharpCode.NRefactory/{CSharp/Resolver => Semantics}/UnknownMemberResolveResult.cs (66%) rename {ICSharpCode.Editor => ICSharpCode.NRefactory}/TextLocation.cs (76%) delete mode 100644 ICSharpCode.NRefactory/TypeSystem/ClassType.cs delete mode 100644 ICSharpCode.NRefactory/TypeSystem/IConversions.cs create mode 100644 ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs create mode 100644 ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs create mode 100644 ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs delete mode 100644 ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs rename ICSharpCode.NRefactory/{CSharp/Analysis => TypeSystem/Implementation}/MinimalResolveContext.cs (51%) create mode 100644 ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs create mode 100644 ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs create mode 100644 ICSharpCode.NRefactory/TypeSystem/TypeKind.cs create mode 100644 ICSharpCode.NRefactory/Utils/7BitEncodedInts.cs delete mode 100644 ICSharpCode.NRefactory/Utils/DotNet35Compat.cs create mode 100644 ICSharpCode.NRefactory/Utils/FastSerializer.cs create mode 100644 ICSharpCode.NRefactory/Utils/ReferenceComparer.cs diff --git a/ICSharpCode.Editor/ICSharpCode.Editor.csproj b/ICSharpCode.Editor/ICSharpCode.Editor.csproj deleted file mode 100644 index f3baf10f7..000000000 --- a/ICSharpCode.Editor/ICSharpCode.Editor.csproj +++ /dev/null @@ -1,72 +0,0 @@ - - - - {F054A788-B591-4561-A8BA-AE745BBEB817} - Debug - x86 - Library - ICSharpCode.Editor - ICSharpCode.Editor - v4.0 - Client - Properties - False - False - OnBuildSuccess - bin\Debug\ICSharpCode.Editor.xml - False - False - 4 - false - False - - - x86 - False - Auto - 4194304 - 4096 - - - bin\Debug\ - true - Full - False - True - DEBUG;TRACE - Project - - - bin\Release\ - False - None - True - False - TRACE - - - - - 3.5 - - - - 3.5 - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/ICSharpCode.Editor/IDocumentLine.cs b/ICSharpCode.Editor/IDocumentLine.cs deleted file mode 100644 index 982a8cd2b..000000000 --- a/ICSharpCode.Editor/IDocumentLine.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.Editor -{ - /// - /// A line inside a . - /// - public interface IDocumentLine : ISegment - { - /// - /// Gets the length of this line, including the line delimiter. - /// - int TotalLength { get; } - - /// - /// Gets the length of the line terminator. - /// Returns 1 or 2; or 0 at the end of the document. - /// - int DelimiterLength { get; } - - /// - /// Gets the number of this line. - /// The first line has the number 1. - /// - int LineNumber { get; } - } -} diff --git a/ICSharpCode.Editor/ISegment.cs b/ICSharpCode.Editor/ISegment.cs deleted file mode 100644 index bf8ac3c08..000000000 --- a/ICSharpCode.Editor/ISegment.cs +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.Editor -{ - /// - /// An (Offset,Length)-pair. - /// - public interface ISegment - { - /// - /// Gets the start offset of the segment. - /// - int Offset { get; } - - /// - /// Gets the length of the segment. - /// - /// Must not be negative. - int Length { get; } - - /// - /// Gets the end offset of the segment. - /// - /// EndOffset = Offset + Length; - int EndOffset { get; } - } - - /// - /// Extension methods for . - /// - public static class ISegmentExtensions - { - /// - /// Gets whether the segment contains the offset. - /// - /// - /// True, if offset is between segment.Start and segment.End (inclusive); otherwise, false. - /// - public static bool Contains (this ISegment segment, int offset) - { - return segment.Offset <= offset && offset <= segment.EndOffset; - } - - /// - /// True, if the segment contains the specified segment, false otherwise. - /// - public static bool Contains (this ISegment thisSegment, ISegment segment) - { - return segment != null && thisSegment.Offset <= segment.Offset && segment.EndOffset <= thisSegment.EndOffset; - } - } -} diff --git a/ICSharpCode.Editor/ITextEditor.cs b/ICSharpCode.Editor/ITextEditor.cs deleted file mode 100644 index 6d15eb769..000000000 --- a/ICSharpCode.Editor/ITextEditor.cs +++ /dev/null @@ -1,100 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace ICSharpCode.Editor -{ - /// - /// Interface for text editors. - /// - public interface ITextEditor : IServiceProvider - { - /// - /// Gets the document that is being edited. - /// - IDocument Document { get; } - - /// - /// Gets an object that represents the caret inside this text editor. - /// - ITextEditorCaret Caret { get; } - - /// - /// Sets the caret to the specified line/column and brings the caret into view. - /// - void JumpTo(int line, int column); - - /// - /// Gets the start offset of the selection. - /// - int SelectionStart { get; } - - /// - /// Gets the length of the selection. - /// - int SelectionLength { get; } - - /// - /// Gets/Sets the selected text. - /// - string SelectedText { get; set; } - - /// - /// Sets the selection. - /// - /// Start offset of the selection - /// Length of the selection - void Select(int selectionStart, int selectionLength); - - /// - /// Shows the specified linked elements, and allows the user to edit them. - /// - /// - /// Returns true when the user has finished editing the elements and pressed Return; - /// or false when editing is aborted for any reason. - /// - /// - /// The user can also edit other parts of the document (or other documents) while in link mode. - /// In case of success (true return value), this method will update the offsets of the linked elements - /// to reflect the changes done by the user. - /// If the text editor does not support link mode, it will immediately return false. - /// -// Task ShowLinkedElements(IEnumerable linkedElements); - } - - /// - /// Represents the caret in a text editor. - /// - public interface ITextEditorCaret - { - /// - /// Gets/Sets the caret offset; - /// - int Offset { get; set; } - - /// - /// Gets/Sets the caret line number. - /// Line numbers are counted starting from 1. - /// - int Line { get; set; } - - /// - /// Gets/Sets the caret column number. - /// Column numbers are counted starting from 1. - /// - int Column { get; set; } - - /// - /// Gets/sets the caret location. - /// - TextLocation Location { get; set; } - - /// - /// Is raised whenever the location of the caret has changed. - /// - event EventHandler LocationChanged; - } -} diff --git a/ICSharpCode.Editor/LinkedElement.cs b/ICSharpCode.Editor/LinkedElement.cs deleted file mode 100644 index 104e53e8a..000000000 --- a/ICSharpCode.Editor/LinkedElement.cs +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.Editor -{ -// I'm not sure if we need this. -// How about a method in the context - this method could wrap the internal representation. -// public void StartTextLinkMode (int linkLength, IEnumerable offsets) -// and maybe then variations taking more than one link element ? - -// /// -// /// Represents an element in the text editor that is either editable, or bound to another editable element. -// /// Used with -// /// -// public class LinkedElement -// { -// LinkedElement boundTo; -// -// /// -// /// Gets/Sets the start offset of this linked element. -// /// -// public int StartOffset { get; set; } -// -// /// -// /// Gets/Sets the end offset of this linked element. -// /// -// public int EndOffset { get; set; } -// -// /// -// /// Gets the linked element to which this element is bound. -// /// -// public LinkedElement BoundTo { -// get { return boundTo; } -// } -// -// /// -// /// Gets whether this element is editable. Returns true if this element is not bound. -// /// -// public bool IsEditable { -// get { return boundTo == null; } -// } -// -// /// -// /// Creates a new editable element. -// /// -// public LinkedElement(int startOffset, int endOffset) -// { -// this.StartOffset = startOffset; -// this.EndOffset = endOffset; -// } -// -// /// -// /// Creates a new element that is bound to . -// /// -// public LinkedElement(int startOffset, int endOffset, LinkedElement boundTo) -// { -// if (boundTo == null) -// throw new ArgumentNullException("boundTo"); -// this.StartOffset = startOffset; -// this.EndOffset = endOffset; -// while (boundTo.boundTo != null) -// boundTo = boundTo.boundTo; -// this.boundTo = boundTo; -// } -// } -} diff --git a/ICSharpCode.NRefactory.CSharp/.gitignore b/ICSharpCode.NRefactory.CSharp/.gitignore new file mode 100644 index 000000000..9ce745d95 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/.gitignore @@ -0,0 +1,3 @@ + +bin/ +obj/ \ No newline at end of file diff --git a/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs b/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs similarity index 94% rename from ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs rename to ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs index bfaaf11f5..36e63d818 100644 --- a/ICSharpCode.NRefactory/CSharp/Analysis/ControlFlow.cs +++ b/ICSharpCode.NRefactory.CSharp/Analysis/ControlFlow.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -8,6 +23,7 @@ using System.Linq; using System.Threading; using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -96,7 +112,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis /// Gets the try-finally statements that this control flow edge is leaving. /// public IEnumerable TryFinallyStatements { - get { return jumpOutOfTryFinally ?? Enumerable.Empty(); } + get { return jumpOutOfTryFinally ?? EmptyList.Instance; } } } @@ -152,7 +168,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis { return BuildControlFlowGraph(statement, new ResolveVisitor( new CSharpResolver(context, cancellationToken), - null, ConstantModeResolveVisitorNavigator.Skip)); + null)); } public IList BuildControlFlowGraph(Statement statement, ResolveVisitor resolveVisitor) @@ -657,7 +673,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis return CreateConnectedEndNode(usingStatement, bodyEnd); } - public override ControlFlowNode VisitYieldStatement(YieldStatement yieldStatement, ControlFlowNode data) + public override ControlFlowNode VisitYieldReturnStatement(YieldReturnStatement yieldStatement, ControlFlowNode data) { return CreateConnectedEndNode(yieldStatement, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs b/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs rename to ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs index edef14f63..a4c18e496 100644 --- a/ICSharpCode.NRefactory/CSharp/Analysis/DefiniteAssignmentAnalysis.cs +++ b/ICSharpCode.NRefactory.CSharp/Analysis/DefiniteAssignmentAnalysis.cs @@ -1,13 +1,31 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; + using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.CSharp.Analysis @@ -96,7 +114,7 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis public DefiniteAssignmentAnalysis(Statement rootStatement, ITypeResolveContext context, CancellationToken cancellationToken) : this(rootStatement, new ResolveVisitor(new CSharpResolver(context ?? MinimalResolveContext.Instance, cancellationToken), - null, ConstantModeResolveVisitorNavigator.Skip)) + null)) { } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs b/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs similarity index 88% rename from ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs rename to ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs index a535257ef..a09dc9f1c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstNode.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/AstNode.cs @@ -27,6 +27,7 @@ using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; +using System.IO; using System.Linq; using System.Threading; @@ -51,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -82,7 +83,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder (this, child, data); } @@ -116,20 +117,20 @@ namespace ICSharpCode.NRefactory.CSharp } } - public virtual AstLocation StartLocation { + public virtual TextLocation StartLocation { get { var child = firstChild; if (child == null) - return AstLocation.Empty; + return TextLocation.Empty; return child.StartLocation; } } - public virtual AstLocation EndLocation { + public virtual TextLocation EndLocation { get { var child = lastChild; if (child == null) - return AstLocation.Empty; + return TextLocation.Empty; return child.EndLocation; } } @@ -440,7 +441,7 @@ namespace ICSharpCode.NRefactory.CSharp return copy; } - public abstract S AcceptVisitor (IAstVisitor visitor, T data); + public abstract S AcceptVisitor (IAstVisitor visitor, T data = default(T)); #region Pattern Matching protected static bool MatchString (string name1, string name2) @@ -503,12 +504,12 @@ namespace ICSharpCode.NRefactory.CSharp return null; } - public AstNode GetNodeAt (int line, int column) + public AstNode GetNodeAt (int line, int column, Predicate pred = null) { - return GetNodeAt (new AstLocation (line, column)); + return GetNodeAt (new TextLocation (line, column), pred); } - public AstNode GetNodeAt (AstLocation location, Predicate pred = null) + public AstNode GetNodeAt (TextLocation location, Predicate pred = null) { AstNode result = null; AstNode node = this; @@ -532,14 +533,14 @@ namespace ICSharpCode.NRefactory.CSharp public T GetNodeAt (int line, int column) where T : AstNode { - return GetNodeAt (new AstLocation (line, column)); + return GetNodeAt (new TextLocation (line, column)); } /// /// Gets the node specified by T at location. This is useful for getting a specific node from the tree. For example searching /// the current method declaration. /// - public T GetNodeAt (AstLocation location) where T : AstNode + public T GetNodeAt (TextLocation location) where T : AstNode { T result = null; AstNode node = this; @@ -561,68 +562,12 @@ namespace ICSharpCode.NRefactory.CSharp return result; } - public AstNode GetResolveableNodeAt (int line, int column) - { - return GetResolveableNodeAt (new AstLocation (line, column)); - } - - /// - /// Gets a node that can be resolved at location. - /// - public AstNode GetResolveableNodeAt (AstLocation location) - { - return GetNodeAt (location, delegate (AstNode n) { - - if (n is TypeDeclaration) { - var decl = (TypeDeclaration)n; - return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; - } - - if (n is DelegateDeclaration) { - var decl = (DelegateDeclaration)n; - return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; - } - - if (n is MemberDeclaration) { - var decl = (MemberDeclaration)n; - return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; - } - - if (n is ConstructorDeclaration) { - var decl = (ConstructorDeclaration)n; - return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation; - } - - if (n is DestructorDeclaration) { - var decl = (DestructorDeclaration)n; - return decl.IdentifierToken.StartLocation <= location && location <= decl.IdentifierToken.EndLocation; - } - - if (n is VariableInitializer) { - var decl = (VariableInitializer)n; - return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; - } - - if (n is ParameterDeclaration) { - var decl = (ParameterDeclaration)n; - return decl.NameToken.StartLocation <= location && location <= decl.NameToken.EndLocation; - } - - if (n is MemberReferenceExpression) { - var decl = (MemberReferenceExpression)n; - return decl.MemberNameToken.StartLocation <= location && location <= decl.MemberNameToken.EndLocation; - } - - return n is IdentifierExpression || n is AstType; - }); - } - public IEnumerable GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn) { - return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn)); + return GetNodesBetween (new TextLocation (startLine, startColumn), new TextLocation (endLine, endColumn)); } - public IEnumerable GetNodesBetween (AstLocation start, AstLocation end) + public IEnumerable GetNodesBetween (TextLocation start, TextLocation end) { AstNode node = this; while (node != null) { @@ -648,10 +593,10 @@ namespace ICSharpCode.NRefactory.CSharp public bool Contains (int line, int column) { - return Contains (new AstLocation (line, column)); + return Contains (new TextLocation (line, column)); } - public bool Contains (AstLocation location) + public bool Contains (TextLocation location) { return this.StartLocation <= location && location < this.EndLocation; } @@ -663,6 +608,19 @@ namespace ICSharpCode.NRefactory.CSharp base.AddAnnotation (annotation); } + internal string DebugToString() + { + if (IsNull) + return "Null"; + StringWriter w = new StringWriter(); + AcceptVisitor(new CSharpOutputVisitor(w, new CSharpFormattingOptions()), null); + string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); + if (text.Length > 100) + return text.Substring(0, 97) + "..."; + else + return text; + } + // the Root role must be available when creating the null nodes, so we can't put it in the Roles class static readonly Role RootRole = new Role ("Root"); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs b/ICSharpCode.NRefactory.CSharp/Ast/AstNodeCollection.cs similarity index 73% rename from ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs rename to ICSharpCode.NRefactory.CSharp/Ast/AstNodeCollection.cs index adc6e5e41..1f1236e9c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstNodeCollection.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/AstNodeCollection.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; @@ -132,28 +147,17 @@ namespace ICSharpCode.NRefactory.CSharp } #region Equals and GetHashCode implementation - public override bool Equals(object obj) - { - if (obj is AstNodeCollection) { - return ((AstNodeCollection)obj) == this; - } else { - return false; - } - } - public override int GetHashCode() { return node.GetHashCode() ^ role.GetHashCode(); } - public static bool operator ==(AstNodeCollection left, AstNodeCollection right) - { - return left.role == right.role && left.node == right.node; - } - - public static bool operator !=(AstNodeCollection left, AstNodeCollection right) + public override bool Equals(object obj) { - return !(left.role == right.role && left.node == right.node); + AstNodeCollection other = obj as AstNodeCollection; + if (other == null) + return false; + return this.node == other.node && this.role == other.role; } #endregion diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs similarity index 81% rename from ICSharpCode.NRefactory/CSharp/Ast/AstType.cs rename to ICSharpCode.NRefactory.CSharp/Ast/AstType.cs index 4c6c0f0b0..fbc3eccf2 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/AstType.cs @@ -1,3 +1,21 @@ +// 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.Collections.Generic; @@ -19,7 +37,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -50,7 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs b/ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs similarity index 60% rename from ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs rename to ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs index 3fc7fa291..59d021aeb 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/CSharpModifierToken.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/CSharpModifierToken.cs @@ -1,6 +1,6 @@ // // CSharpModifierToken.cs -// +// // Author: // Mike Krüger // @@ -37,14 +37,8 @@ namespace ICSharpCode.NRefactory.CSharp public Modifiers Modifier { get { return modifier; } set { - for (int i = 0; i < lengthTable.Count; i++) { - if (lengthTable[i].Key == value) { - this.modifier = value; - this.tokenLength = lengthTable[i].Value; - return; - } - } - throw new ArgumentException ("Modifier " + value + " is invalid."); + this.tokenLength = GetModifierName(value).Length; + this.modifier = value; } } @@ -56,33 +50,21 @@ namespace ICSharpCode.NRefactory.CSharp // Not worth using a dictionary for such few elements. // This table is sorted in the order that modifiers should be output when generating code. - static readonly List> lengthTable = new List> () { - new KeyValuePair(Modifiers.Public, "public".Length), - new KeyValuePair(Modifiers.Protected, "protected".Length), - new KeyValuePair(Modifiers.Private, "private".Length), - new KeyValuePair(Modifiers.Internal, "internal".Length), - new KeyValuePair(Modifiers.New, "new".Length), - new KeyValuePair(Modifiers.Unsafe, "unsafe".Length), - new KeyValuePair(Modifiers.Abstract, "abstract".Length), - new KeyValuePair(Modifiers.Virtual, "virtual".Length), - new KeyValuePair(Modifiers.Sealed, "sealed".Length), - new KeyValuePair(Modifiers.Static, "static".Length), - new KeyValuePair(Modifiers.Override, "override".Length), - new KeyValuePair(Modifiers.Readonly, "readonly".Length), - new KeyValuePair(Modifiers.Volatile, "volatile".Length), - new KeyValuePair(Modifiers.Extern, "extern".Length), - new KeyValuePair(Modifiers.Partial, "partial".Length), - new KeyValuePair(Modifiers.Const, "const".Length), - - // even though it's used for patterns only, it needs to be in this table to be usable in the AST - new KeyValuePair(Modifiers.Any, "any".Length) + static readonly Modifiers[] allModifiers = { + Modifiers.Public, Modifiers.Protected, Modifiers.Private, Modifiers.Internal, + Modifiers.New, + Modifiers.Unsafe, + Modifiers.Abstract, Modifiers.Virtual, Modifiers.Sealed, Modifiers.Static, Modifiers.Override, + Modifiers.Readonly, Modifiers.Volatile, + Modifiers.Extern, Modifiers.Partial, Modifiers.Const, + Modifiers.Any }; public static IEnumerable AllModifiers { - get { return lengthTable.Select(p => p.Key); } + get { return allModifiers; } } - public CSharpModifierToken (AstLocation location, Modifiers modifier) : base (location, 0) + public CSharpModifierToken (TextLocation location, Modifiers modifier) : base (location, 0) { this.Modifier = modifier; } @@ -122,8 +104,9 @@ namespace ICSharpCode.NRefactory.CSharp return "volatile"; case Modifiers.Unsafe: return "unsafe"; - case Modifiers.Fixed: - return "fixed"; + case Modifiers.Any: + // even though it's used for patterns only, it needs to be in this list to be usable in the AST + return "any"; default: throw new NotSupportedException("Invalid value for Modifiers"); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs b/ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs similarity index 85% rename from ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs rename to ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs index b125413d0..00bf53dfd 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/CSharpTokenNode.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/CSharpTokenNode.cs @@ -1,4 +1,4 @@ -// +// // TokenNode.cs // // Author: @@ -38,11 +38,11 @@ namespace ICSharpCode.NRefactory.CSharp } } - public NullCSharpTokenNode () : base (AstLocation.Empty, 0) + public NullCSharpTokenNode () : base (TextLocation.Empty, 0) { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -60,34 +60,34 @@ namespace ICSharpCode.NRefactory.CSharp } } - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } } protected int tokenLength; - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (StartLocation.Line, StartLocation.Column + tokenLength); + return new TextLocation (StartLocation.Line, StartLocation.Column + tokenLength); } } - public CSharpTokenNode (AstLocation location, int tokenLength) + public CSharpTokenNode (TextLocation location, int tokenLength) { this.startLocation = location; this.tokenLength = tokenLength; } #region IRelocationable implementation - void IRelocatable.SetStartLocation (AstLocation startLocation) + void IRelocatable.SetStartLocation (TextLocation startLocation) { this.startLocation = startLocation; } #endregion - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCSharpTokenNode (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs b/ICSharpCode.NRefactory.CSharp/Ast/CSharpUtil.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Ast/CSharpUtil.cs rename to ICSharpCode.NRefactory.CSharp/Ast/CSharpUtil.cs diff --git a/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs b/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs rename to ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs index 889e8d048..f90f7cf01 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/CompilationUnit.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/CompilationUnit.cs @@ -83,7 +83,7 @@ namespace ICSharpCode.NRefactory.CSharp return o != null && GetChildrenByRole(MemberRole).DoMatch(o.GetChildrenByRole(MemberRole), match); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCompilationUnit (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs b/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs similarity index 95% rename from ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs rename to ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs index 813f47213..d70a47820 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/ComposedType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/ComposedType.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.CSharp return !GetChildByRole(NullableRole).IsNull; } set { - SetChildByRole(NullableRole, value ? new CSharpTokenNode(AstLocation.Empty, 1) : null); + SetChildByRole(NullableRole, value ? new CSharpTokenNode(TextLocation.Empty, 1) : null); } } @@ -63,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp d--; } while (d < value) { - InsertChildBefore(GetChildByRole(PointerRole), new CSharpTokenNode(AstLocation.Empty, 1), PointerRole); + InsertChildBefore(GetChildByRole(PointerRole), new CSharpTokenNode(TextLocation.Empty, 1), PointerRole); d++; } } @@ -73,7 +73,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (ArraySpecifierRole); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitComposedType (this, data); } @@ -149,7 +149,7 @@ namespace ICSharpCode.NRefactory.CSharp d--; } while (d < value) { - InsertChildBefore(GetChildByRole(Roles.Comma), new CSharpTokenNode(AstLocation.Empty, 1), Roles.Comma); + InsertChildBefore(GetChildByRole(Roles.Comma), new CSharpTokenNode(TextLocation.Empty, 1), Roles.Comma); d++; } } @@ -159,7 +159,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBracket); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitArraySpecifier(this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs b/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs rename to ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs index ecc5210a1..d001b7490 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/DepthFirstAstVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/DepthFirstAstVisitor.cs @@ -360,9 +360,9 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (yieldBreakStatement, data); } - public virtual S VisitYieldStatement (YieldStatement yieldStatement, T data) + public virtual S VisitYieldReturnStatement (YieldReturnStatement yieldReturnStatement, T data) { - return VisitChildren (yieldStatement, data); + return VisitChildren (yieldReturnStatement, data); } public virtual S VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, T data) @@ -445,9 +445,9 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (anonymousTypeCreateExpression, data); } - public virtual S VisitArrayCreateExpression (ArrayCreateExpression arrayObjectCreateExpression, T data) + public virtual S VisitArrayCreateExpression (ArrayCreateExpression arrayCreateExpression, T data) { - return VisitChildren (arrayObjectCreateExpression, data); + return VisitChildren (arrayCreateExpression, data); } public virtual S VisitParenthesizedExpression (ParenthesizedExpression parenthesizedExpression, T data) @@ -585,6 +585,11 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (namedArgumentExpression, data); } + public virtual S VisitNamedExpression (NamedExpression namedExpression, T data) + { + return VisitChildren (namedExpression, data); + } + public virtual S VisitEmptyExpression (EmptyExpression emptyExpression, T data) { return VisitChildren (emptyExpression, data); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs b/ICSharpCode.NRefactory.CSharp/Ast/ErrorNode.cs similarity index 91% rename from ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs rename to ICSharpCode.NRefactory.CSharp/Ast/ErrorNode.cs index af2fed750..53dfd7126 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/ErrorNode.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/ErrorNode.cs @@ -1,4 +1,4 @@ -// +// // ErrorNode.cs // // Author: @@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp /// public class ErrorNode : AstNode { - static AstLocation maxLoc = new AstLocation (int.MaxValue, int.MaxValue); + static TextLocation maxLoc = new TextLocation (int.MaxValue, int.MaxValue); public override NodeType NodeType { get { @@ -42,13 +42,13 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override AstLocation StartLocation { + public override TextLocation StartLocation { get { return maxLoc; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { return maxLoc; } @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { // nothing return default (S); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousMethodExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs similarity index 85% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousMethodExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs index f8c8cefac..91fc0c417 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousMethodExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousMethodExpression.cs @@ -30,11 +30,15 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp { /// - /// delegate(Parameters) {Body} + /// [async] delegate(Parameters) {Body} /// public class AnonymousMethodExpression : Expression { - // used to make a difference between delegate {} and delegate () {} + public readonly static Role AsyncModifierRole = LambdaExpression.AsyncModifierRole; + + public bool IsAsync { get; set; } + + // used to tell the difference between delegate {} and delegate () {} public bool HasParameterList { get; set; } @@ -78,7 +82,7 @@ namespace ICSharpCode.NRefactory.CSharp { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitAnonymousMethodExpression (this, data); } @@ -86,7 +90,8 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { AnonymousMethodExpression o = other as AnonymousMethodExpression; - return o != null && this.HasParameterList == o.HasParameterList && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); + return o != null && this.IsAsync == o.IsAsync && this.HasParameterList == o.HasParameterList + && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs similarity index 91% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs index 940249d8d..496a2cfdb 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AnonymousTypeCreateExpression.cs @@ -1,4 +1,4 @@ -// +// // AnonymousTypeCreateExpression.cs // // Author: @@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.LPar); } } - public AstNodeCollection Initializer { + public AstNodeCollection Initializers { get { return GetChildrenByRole (Roles.Expression); } } @@ -53,9 +53,9 @@ namespace ICSharpCode.NRefactory.CSharp { } - public AnonymousTypeCreateExpression (IEnumerable initializer) + public AnonymousTypeCreateExpression (IEnumerable initializers) { - foreach (var ini in initializer) { + foreach (var ini in initializers) { AddChild (ini, Roles.Expression); } } @@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitAnonymousTypeCreateExpression (this, data); } @@ -72,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { var o = other as AnonymousTypeCreateExpression; - return o != null && this.Initializer.DoMatch(o.Initializer, match); + return o != null && this.Initializers.DoMatch(o.Initializers, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayCreateExpression.cs similarity index 60% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayCreateExpression.cs index dffc3dd3d..f9bee2a68 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayCreateExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayCreateExpression.cs @@ -1,3 +1,21 @@ +// 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.Collections.Generic; @@ -33,7 +51,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (InitializerRole, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitArrayCreateExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs similarity index 88% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/ArrayInitializerExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/ArrayInitializerExpression.cs index 3c33d4d7b..d4858d8b2 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 (); @@ -44,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -68,7 +82,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBrace); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitArrayInitializerExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AsExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AsExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/AsExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/AsExpression.cs index b1a1b8065..59f4652da 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AsExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AsExpression.cs @@ -55,7 +55,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (type, Roles.Type); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitAsExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs index 998ab78fb..c0e9ef3f7 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/AssignmentExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/AssignmentExpression.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole(RightRole, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitAssignmentExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BaseReferenceExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BaseReferenceExpression.cs similarity index 88% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/BaseReferenceExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/BaseReferenceExpression.cs index b75fb9534..2214e3eaa 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BaseReferenceExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BaseReferenceExpression.cs @@ -31,23 +31,23 @@ namespace ICSharpCode.NRefactory.CSharp /// public class BaseReferenceExpression : Expression { - public AstLocation Location { + public TextLocation Location { get; set; } - public override AstLocation StartLocation { + public override TextLocation StartLocation { get { return Location; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (Location.Line, Location.Column + "base".Length); + return new TextLocation (Location.Line, Location.Column + "base".Length); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitBaseReferenceExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs index 171e3e31c..68259dedf 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/BinaryOperatorExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/BinaryOperatorExpression.cs @@ -67,7 +67,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole(RightRole, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitBinaryOperatorExpression (this, data); } @@ -128,11 +128,15 @@ namespace ICSharpCode.NRefactory.CSharp public enum BinaryOperatorType { + /// + /// Any binary operator (used in pattern matching) + /// + Any, + // We avoid 'logical or' on purpose, because it's not clear if that refers to the bitwise // or to the short-circuiting (conditional) operator: // MCS and old NRefactory used bitwise='|', logical='||' // but the C# spec uses logical='|', conditional='||' - /// left & right BitwiseAnd, /// left | right @@ -174,11 +178,6 @@ namespace ICSharpCode.NRefactory.CSharp ShiftRight, /// left ?? right - NullCoalescing, - - /// - /// Any binary operator (used in pattern matching) - /// - Any + NullCoalescing } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CastExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/CastExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/CastExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/CastExpression.cs index 88c7dcfe3..6a3f1ceb9 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CastExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/CastExpression.cs @@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (expression, Roles.Expression); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCastExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CheckedExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/CheckedExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/CheckedExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/CheckedExpression.cs index 349976c68..f9fd9ab9d 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/CheckedExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/CheckedExpression.cs @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (expression, Roles.Expression); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCheckedExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ConditionalExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ConditionalExpression.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/ConditionalExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/ConditionalExpression.cs index 5e8099432..3a98ed7ed 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ConditionalExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ConditionalExpression.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (falseExpression, FalseRole); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitConditionalExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DefaultValueExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/DefaultValueExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/DefaultValueExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/DefaultValueExpression.cs index 1a91d6d08..28fb4adc4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DefaultValueExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/DefaultValueExpression.cs @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (type, Roles.Type); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitDefaultValueExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DirectionExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/DirectionExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/DirectionExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/DirectionExpression.cs index 0c19b2ca7..d99182d33 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/DirectionExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/DirectionExpression.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (expression, Roles.Expression); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitDirectionExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/EmptyExpression.cs similarity index 88% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/EmptyExpression.cs index 3c23f54f8..e333090eb 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/EmptyExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/EmptyExpression.cs @@ -1,4 +1,4 @@ -// +// // EmptyExpression.cs // // Author: @@ -32,15 +32,15 @@ namespace ICSharpCode.NRefactory.CSharp /// public class EmptyExpression : Expression, IRelocatable { - AstLocation location; + TextLocation location; - public override AstLocation StartLocation { + public override TextLocation StartLocation { get { return location; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { return location; } @@ -50,19 +50,19 @@ namespace ICSharpCode.NRefactory.CSharp { } - public EmptyExpression (AstLocation location) + public EmptyExpression (TextLocation location) { this.location = location; } #region IRelocationable implementation - void IRelocatable.SetStartLocation (AstLocation startLocation) + void IRelocatable.SetStartLocation (TextLocation startLocation) { this.location = startLocation; } #endregion - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitEmptyExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/Expression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/Expression.cs similarity index 82% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/Expression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/Expression.cs index db0cee257..f61e67f0b 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/Expression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/Expression.cs @@ -1,10 +1,23 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; -using System.IO; -using System.Linq; namespace ICSharpCode.NRefactory.CSharp { @@ -28,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -59,7 +72,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } @@ -90,11 +103,7 @@ namespace ICSharpCode.NRefactory.CSharp // Make debugging easier by giving Expressions a ToString() implementation public override string ToString() { - if (IsNull) - return "Null"; - StringWriter w = new StringWriter(); - AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); - return w.ToString(); + return DebugToString(); } public Expression ReplaceWith(Func replaceFunction) diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IdentifierExpression.cs similarity index 95% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/IdentifierExpression.cs index e982f1320..892807fd3 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IdentifierExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IdentifierExpression.cs @@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp this.Identifier = identifier; } - public IdentifierExpression(string identifier, AstLocation location) + public IdentifierExpression(string identifier, TextLocation location) { SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (identifier, location)); } @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, TextLocation.Empty)); } } @@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.TypeArgument); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitIdentifierExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IndexerExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IndexerExpression.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/IndexerExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/IndexerExpression.cs index 045d8d038..1d7d9a464 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IndexerExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IndexerExpression.cs @@ -68,7 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitIndexerExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/InvocationExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/InvocationExpression.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/InvocationExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/InvocationExpression.cs index 84d0830fe..b609ae886 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/InvocationExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/InvocationExpression.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RPar); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitInvocationExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IsExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IsExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/IsExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/IsExpression.cs index a8c7b0e00..d01fe48b1 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/IsExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/IsExpression.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole(Roles.Type, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitIsExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/LambdaExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs similarity index 83% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/LambdaExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs index 774bd6c4a..2b6a39d6b 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/LambdaExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/LambdaExpression.cs @@ -1,6 +1,6 @@ // // LambdaExpression.cs -// +// // Author: // Mike Krüger // @@ -29,14 +29,17 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp { /// - /// Parameters => Body + /// [async] Parameters => Body /// public class LambdaExpression : Expression { + public readonly static Role AsyncModifierRole = new Role("AsyncModifier", CSharpTokenNode.Null); public readonly static Role ArrowRole = new Role("Arrow", CSharpTokenNode.Null); public static readonly Role BodyRole = new Role("Body", AstNode.Null); - public AstNodeCollection Parameters { + public bool IsAsync { get; set; } + + public AstNodeCollection Parameters { get { return GetChildrenByRole (Roles.Parameter); } } @@ -49,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (BodyRole, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitLambdaExpression (this, data); } @@ -57,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { LambdaExpression o = other as LambdaExpression; - return o != null && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); + return o != null && this.IsAsync == o.IsAsync && this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/MemberReferenceExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/MemberReferenceExpression.cs index 4a7decbe0..cf0c1808f 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/MemberReferenceExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/MemberReferenceExpression.cs @@ -1,4 +1,4 @@ -// +// // MemberReferenceExpression.cs // // Author: @@ -43,7 +43,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -87,7 +87,7 @@ namespace ICSharpCode.NRefactory.CSharp { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitMemberReferenceExpression (this, data); } diff --git a/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedArgumentExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedArgumentExpression.cs new file mode 100644 index 000000000..6b6303863 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedArgumentExpression.cs @@ -0,0 +1,77 @@ +// 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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents a named argument passed to a method or attribute. + /// name: expression + /// + public class NamedArgumentExpression : Expression + { + public NamedArgumentExpression() + { + } + + public NamedArgumentExpression(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, TextLocation.Empty)); + } + } + + public Identifier IdentifierToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole(Roles.Identifier, value); + } + } + + public CSharpTokenNode ColonToken { + get { return GetChildByRole (Roles.Colon); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) + { + return visitor.VisitNamedArgumentExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + NamedArgumentExpression o = other as NamedArgumentExpression; + return o != null && MatchString(this.Identifier, o.Identifier) && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NamedExpression.cs new file mode 100644 index 000000000..fb5ce405a --- /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, TextLocation.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 = default(T)) + { + 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/NullReferenceExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NullReferenceExpression.cs similarity index 86% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/NullReferenceExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/NullReferenceExpression.cs index df95202b8..3a92c97f3 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NullReferenceExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/NullReferenceExpression.cs @@ -31,16 +31,16 @@ namespace ICSharpCode.NRefactory.CSharp /// public class NullReferenceExpression : Expression { - AstLocation location; - public override AstLocation StartLocation { + TextLocation location; + public override TextLocation StartLocation { get { return location; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (location.Line, location.Column + "null".Length); + return new TextLocation (location.Line, location.Column + "null".Length); } } @@ -48,12 +48,12 @@ namespace ICSharpCode.NRefactory.CSharp { } - public NullReferenceExpression (AstLocation location) + public NullReferenceExpression (TextLocation location) { this.location = location; } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitNullReferenceExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ObjectCreateExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ObjectCreateExpression.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/ObjectCreateExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/ObjectCreateExpression.cs index 7bb5dc821..0e72c04b1 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ObjectCreateExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ObjectCreateExpression.cs @@ -79,7 +79,7 @@ namespace ICSharpCode.NRefactory.CSharp { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitObjectCreateExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ParenthesizedExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ParenthesizedExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/ParenthesizedExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/ParenthesizedExpression.cs index 8cdb5cfd1..8c32a42dd 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ParenthesizedExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ParenthesizedExpression.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp Expression = expr; } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitParenthesizedExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/PointerReferenceExpression.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/PointerReferenceExpression.cs index 21e805b67..a1b7f051f 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PointerReferenceExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/PointerReferenceExpression.cs @@ -1,4 +1,4 @@ -// +// // PointerReferenceExpression.cs // // Author: @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.TypeArgument); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitPointerReferenceExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs similarity index 86% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs index 22e16e29b..6e39fc277 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/PrimitiveExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/PrimitiveExpression.cs @@ -33,17 +33,17 @@ namespace ICSharpCode.NRefactory.CSharp { public static readonly object AnyValue = new object(); - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } } string literalValue; - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (StartLocation.Line, StartLocation.Column + literalValue.Length); + return new TextLocation (StartLocation.Line, StartLocation.Column + literalValue.Length); } } @@ -69,7 +69,7 @@ namespace ICSharpCode.NRefactory.CSharp this.literalValue = literalValue ?? ""; } - public PrimitiveExpression (object value, AstLocation startLocation, string literalValue) + public PrimitiveExpression (object value, TextLocation startLocation, string literalValue) { this.Value = value; this.startLocation = startLocation; @@ -77,13 +77,13 @@ namespace ICSharpCode.NRefactory.CSharp } #region IRelocationable implementation - void IRelocatable.SetStartLocation (AstLocation startLocation) + void IRelocatable.SetStartLocation (TextLocation startLocation) { this.startLocation = startLocation; } #endregion - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitPrimitiveExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/QueryExpression.cs similarity index 86% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/QueryExpression.cs index 5cf887703..5e7ffaa67 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/QueryExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/QueryExpression.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -21,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -37,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole(ClauseRole); } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryExpression (this, data); } @@ -89,11 +104,15 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, TextLocation.Empty)); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public Identifier IdentifierToken { + get { return GetChildByRole (Roles.Identifier); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryContinuationClause (this, data); } @@ -120,16 +139,20 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, TextLocation.Empty)); } } + public Identifier IdentifierToken { + get { return GetChildByRole(Roles.Identifier); } + } + public Expression Expression { get { return GetChildByRole (Roles.Expression); } set { SetChildByRole (Roles.Expression, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryFromClause (this, data); } @@ -153,10 +176,14 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole(Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, TextLocation.Empty)); } } + public Identifier IdentifierToken { + get { return GetChildByRole(Roles.Identifier); } + } + public CSharpTokenNode AssignToken { get { return GetChildByRole(Roles.Assign); } } @@ -166,7 +193,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole(Roles.Expression, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryLetClause (this, data); } @@ -190,7 +217,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Condition, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryWhereClause (this, data); } @@ -237,10 +264,14 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole(JoinIdentifierRole).Name; } set { - SetChildByRole(JoinIdentifierRole, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(JoinIdentifierRole, Identifier.Create (value, TextLocation.Empty)); } } + public Identifier JoinIdentifierToken { + get { return GetChildByRole(JoinIdentifierRole); } + } + public CSharpTokenNode InKeyword { get { return GetChildByRole (InKeywordRole); } } @@ -277,11 +308,15 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (IntoIdentifierRole).Name; } set { - SetChildByRole(IntoIdentifierRole, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(IntoIdentifierRole, Identifier.Create (value, TextLocation.Empty)); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public Identifier IntoIdentifierToken { + get { return GetChildByRole(IntoIdentifierRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryJoinClause (this, data); } @@ -309,7 +344,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (OrderingRole); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryOrderClause (this, data); } @@ -341,7 +376,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Keyword); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryOrdering (this, data); } @@ -371,7 +406,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Expression, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQuerySelectClause (this, data); } @@ -408,7 +443,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (KeyRole, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitQueryGroupClause (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/SizeOfExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/SizeOfExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/SizeOfExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/SizeOfExpression.cs index 6e7a740d6..eba12d3e0 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/SizeOfExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/SizeOfExpression.cs @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (type, Roles.Type); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitSizeOfExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/StackAllocExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/StackAllocExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/StackAllocExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/StackAllocExpression.cs index ad7fc1a7e..f69d92286 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/StackAllocExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/StackAllocExpression.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBracket); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitStackAllocExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ThisReferenceExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ThisReferenceExpression.cs similarity index 88% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/ThisReferenceExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/ThisReferenceExpression.cs index 5428cf04b..7d2bd33eb 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/ThisReferenceExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/ThisReferenceExpression.cs @@ -31,23 +31,23 @@ namespace ICSharpCode.NRefactory.CSharp /// public class ThisReferenceExpression : Expression { - public AstLocation Location { + public TextLocation Location { get; set; } - public override AstLocation StartLocation { + public override TextLocation StartLocation { get { return Location; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (Location.Line, Location.Column + "this".Length); + return new TextLocation (Location.Line, Location.Column + "this".Length); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitThisReferenceExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeOfExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeOfExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeOfExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeOfExpression.cs index 09e8931ff..31e0b7bf3 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeOfExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeOfExpression.cs @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (type, Roles.Type); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitTypeOfExpression (this, data); } diff --git a/ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeReferenceExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeReferenceExpression.cs new file mode 100644 index 000000000..c568f824a --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/TypeReferenceExpression.cs @@ -0,0 +1,54 @@ +// 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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Represents an AstType as an expression. + /// This is used when calling a method on a primitive type: "int.Parse()" + /// + public class TypeReferenceExpression : Expression + { + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) + { + return visitor.VisitTypeReferenceExpression(this, data); + } + + public TypeReferenceExpression () + { + } + + public TypeReferenceExpression (AstType type) + { + AddChild (type, Roles.Type); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + TypeReferenceExpression o = other as TypeReferenceExpression; + return o != null && this.Type.DoMatch(o.Type, match); + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs similarity index 90% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs index fe0b2d264..262bd51dd 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UnaryOperatorExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UnaryOperatorExpression.cs @@ -1,6 +1,6 @@ // // UnaryOperatorExpression.cs -// +// // Author: // Mike Krüger // @@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Expression, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUnaryOperatorExpression (this, data); } @@ -67,7 +67,8 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { UnaryOperatorExpression o = other as UnaryOperatorExpression; - return o != null && this.Operator == o.Operator && this.Expression.DoMatch(o.Expression, match); + return o != null && (this.Operator == UnaryOperatorType.Any || this.Operator == o.Operator) + && this.Expression.DoMatch(o.Expression, match); } public static string GetOperatorSymbol(UnaryOperatorType op) @@ -91,6 +92,8 @@ namespace ICSharpCode.NRefactory.CSharp return "*"; case UnaryOperatorType.AddressOf: return "&"; + case UnaryOperatorType.Await: + return "await"; default: throw new NotSupportedException("Invalid value for UnaryOperatorType"); } @@ -99,6 +102,11 @@ namespace ICSharpCode.NRefactory.CSharp public enum UnaryOperatorType { + /// + /// Any unary operator (used in pattern matching) + /// + Any, + /// Logical not (!a) Not, /// Bitwise not (~a) @@ -118,7 +126,8 @@ namespace ICSharpCode.NRefactory.CSharp /// Dereferencing (*a) Dereference, /// Get address (&a) - AddressOf + AddressOf, + /// C# 5.0 await + Await } - } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UncheckedExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UncheckedExpression.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/UncheckedExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/UncheckedExpression.cs index 6e9e61923..6bd835775 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UncheckedExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UncheckedExpression.cs @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (expression, Roles.Expression); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUncheckedExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UndocumentedExpression.cs b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UndocumentedExpression.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/UndocumentedExpression.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Expressions/UndocumentedExpression.cs index 8bbd81a5f..3a6d62855 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/UndocumentedExpression.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Expressions/UndocumentedExpression.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RPar); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUndocumentedExpression (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Attribute.cs similarity index 95% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Attribute.cs index 95235527f..433510338 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Attribute.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Attribute.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp set; } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitAttribute (this, data); } @@ -70,7 +70,7 @@ namespace ICSharpCode.NRefactory.CSharp if (IsNull) return "Null"; var w = new System.IO.StringWriter (); - AcceptVisitor (new OutputVisitor (w, new CSharpFormattingOptions ()), null); + AcceptVisitor (new CSharpOutputVisitor (w, new CSharpFormattingOptions ()), null); return w.ToString (); } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/AttributeSection.cs similarity index 91% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/AttributeSection.cs index bce347c92..cf142593c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/AttributeSection.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/AttributeSection.cs @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } @@ -85,8 +85,21 @@ namespace ICSharpCode.NRefactory.CSharp } public string AttributeTarget { - get; - set; + get { + return GetChildByRole (Roles.Identifier).Name; + } + set { + SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (value, TextLocation.Empty)); + } + } + + public Identifier AttributeTargetToken { + get { + return GetChildByRole (Roles.Identifier); + } + set { + SetChildByRole (Roles.Identifier, value); + } } public AstNodeCollection Attributes { @@ -97,7 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBracket); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitAttributeSection (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs similarity index 81% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs index 61b424f49..f6cd0d2af 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Comment.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Comment.cs @@ -1,4 +1,4 @@ -// +// // Comment.cs // // Author: @@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp { public override NodeType NodeType { get { - return NodeType.Unknown; + return NodeType.Whitespace; } } @@ -55,15 +55,15 @@ namespace ICSharpCode.NRefactory.CSharp set; } - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } } - AstLocation endLocation; - public override AstLocation EndLocation { + TextLocation endLocation; + public override TextLocation EndLocation { get { return endLocation; } @@ -75,7 +75,7 @@ namespace ICSharpCode.NRefactory.CSharp this.Content = content; } - public Comment (CommentType commentType, AstLocation startLocation, AstLocation endLocation) + public Comment (CommentType commentType, TextLocation startLocation, TextLocation endLocation) { this.CommentType = commentType; this.startLocation = startLocation; @@ -83,15 +83,15 @@ namespace ICSharpCode.NRefactory.CSharp } #region IRelocationable implementation - void IRelocatable.SetStartLocation (AstLocation startLocation) + void IRelocatable.SetStartLocation (TextLocation startLocation) { int lineDelta = startLocation.Line - this.startLocation.Line; - endLocation = new AstLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column); + endLocation = new TextLocation (endLocation.Line + lineDelta, lineDelta != 0 ? endLocation.Column : endLocation.Column + startLocation.Column - this.startLocation.Column); this.startLocation = startLocation; } #endregion - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitComment (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Constraint.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Constraint.cs index 48c4e0ecb..6d6dc45d0 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/Constraint.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/Constraint.cs @@ -1,4 +1,4 @@ -// +// // Constraint.cs // // Author: @@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (BaseTypeRole); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitConstraint (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/DelegateDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/DelegateDeclaration.cs index c33c0bf24..c226d8ffd 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/DelegateDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/DelegateDeclaration.cs @@ -1,4 +1,4 @@ -// +// // DelegateDeclaration.cs // // Author: @@ -50,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -83,7 +83,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.Constraint); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitDelegateDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs index 7d9a33df4..f238f1aa2 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/ExternAliasDeclaration.cs @@ -1,4 +1,4 @@ -// +// // ExternAliasDeclaration.cs // // Author: @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -69,7 +69,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitExternAliasDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NamespaceDeclaration.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NamespaceDeclaration.cs index c580f3790..d8736adc4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/NamespaceDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/NamespaceDeclaration.cs @@ -1,4 +1,4 @@ -// +// // NamespaceDeclaration.cs // // Author: @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp return builder.ToString (); } set { - GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => Identifier.Create (ident, AstLocation.Empty))); + GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => Identifier.Create (ident, TextLocation.Empty))); } } @@ -109,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (child, MemberRole); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitNamespaceDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeDeclaration.cs similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeDeclaration.cs index 945c936cd..018e0491e 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeDeclaration.cs @@ -1,4 +1,4 @@ -// +// // TypeDeclaration.cs // // Author: @@ -30,6 +30,14 @@ using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.CSharp { + public enum ClassType + { + Class, + Struct, + Interface, + Enum + } + /// /// class Name<TypeParameters> : BaseTypes where Constraints; /// @@ -55,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -92,7 +100,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBrace); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitTypeDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs similarity index 57% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs index ee2d58eb3..afa3122a5 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/TypeParameterDeclaration.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.TypeSystem; @@ -35,7 +50,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -48,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitTypeParameterDeclaration(this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs similarity index 91% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs index 7fd3dfa09..8a69357c6 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingAliasDeclaration.cs @@ -1,4 +1,4 @@ -// +// // UsingAliasDeclaration.cs // // Author: @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (AliasRole).Name; } set { - SetChildByRole(AliasRole, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(AliasRole, Identifier.Create (value, TextLocation.Empty)); } } @@ -72,17 +72,17 @@ namespace ICSharpCode.NRefactory.CSharp public UsingAliasDeclaration (string alias, string nameSpace) { - AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole); + AddChild (Identifier.Create (alias, TextLocation.Empty), AliasRole); AddChild (new SimpleType (nameSpace), ImportRole); } public UsingAliasDeclaration (string alias, AstType import) { - AddChild (Identifier.Create (alias, AstLocation.Empty), AliasRole); + AddChild (Identifier.Create (alias, TextLocation.Empty), AliasRole); AddChild (import, ImportRole); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUsingAliasDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingDeclaration.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingDeclaration.cs index 77c2697f8..31ae7ddfc 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/GeneralScope/UsingDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/GeneralScope/UsingDeclaration.cs @@ -74,7 +74,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (import, ImportRole); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUsingDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs b/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs similarity index 86% rename from ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs rename to ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs index 4092d5671..6079ca046 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/IAstVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/IAstVisitor.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -30,6 +45,7 @@ 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 VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, T data); S VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, T data); S VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, T data); @@ -94,7 +110,7 @@ namespace ICSharpCode.NRefactory.CSharp S VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, T data); S VisitWhileStatement(WhileStatement whileStatement, T data); S VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, T data); - S VisitYieldStatement(YieldStatement yieldStatement, T data); + S VisitYieldReturnStatement(YieldReturnStatement yieldReturnStatement, T data); S VisitAccessor(Accessor accessor, T data); S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, T data); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs b/ICSharpCode.NRefactory.CSharp/Ast/IRelocatable.cs similarity index 95% rename from ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs rename to ICSharpCode.NRefactory.CSharp/Ast/IRelocatable.cs index 48205191f..cbb282a19 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/IRelocatable.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/IRelocatable.cs @@ -1,4 +1,4 @@ -// +// // IRelocationable.cs // // Author: @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp { public interface IRelocatable { - void SetStartLocation (AstLocation startLocation); + void SetStartLocation (TextLocation startLocation); } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs b/ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs similarity index 76% rename from ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs index 12bd64475..0938d9f0c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Identifier.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Identifier.cs @@ -1,4 +1,4 @@ -// +// // Identifier.cs // // Author: @@ -30,8 +30,8 @@ namespace ICSharpCode.NRefactory.CSharp { public class Identifier : AstNode, IRelocatable { - public static readonly Identifier Null = new NullIdentifier (); - class NullIdentifier : Identifier + public new static readonly Identifier Null = new NullIdentifier (); + sealed class NullIdentifier : Identifier { public override bool IsNull { get { @@ -39,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp public override NodeType NodeType { get { - return NodeType.Unknown; + return NodeType.Token; } } @@ -66,8 +66,8 @@ namespace ICSharpCode.NRefactory.CSharp } } - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } @@ -81,15 +81,15 @@ namespace ICSharpCode.NRefactory.CSharp } #region IRelocationable implementation - void IRelocatable.SetStartLocation (AstLocation startLocation) + void IRelocatable.SetStartLocation (TextLocation startLocation) { this.startLocation = startLocation; } #endregion - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length); + return new TextLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length); } } @@ -98,7 +98,7 @@ namespace ICSharpCode.NRefactory.CSharp this.name = string.Empty; } - protected Identifier (string name, AstLocation location) + protected Identifier (string name, TextLocation location) { if (name == null) throw new ArgumentNullException("name"); @@ -108,10 +108,10 @@ namespace ICSharpCode.NRefactory.CSharp public static Identifier Create (string name) { - return Create (name, AstLocation.Empty); + return Create (name, TextLocation.Empty); } - public static Identifier Create (string name, AstLocation location) + public static Identifier Create (string name, TextLocation location) { if (name == null) throw new ArgumentNullException("name"); @@ -120,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp return new Identifier (name, location); } - public static Identifier Create (string name, AstLocation location, bool isVerbatim) + public static Identifier Create (string name, TextLocation location, bool isVerbatim) { if (name == null) throw new ArgumentNullException("name"); @@ -130,7 +130,7 @@ namespace ICSharpCode.NRefactory.CSharp return new Identifier (name, location); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitIdentifier (this, data); } @@ -143,9 +143,9 @@ namespace ICSharpCode.NRefactory.CSharp class VerbatimIdentifier : Identifier { - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + 1); // @"..." + return new TextLocation (StartLocation.Line, StartLocation.Column + (Name ?? "").Length + 1); // @"..." } } @@ -155,7 +155,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public VerbatimIdentifier(string name, AstLocation location) : base (name, location) + public VerbatimIdentifier(string name, TextLocation location) : base (name, location) { } } diff --git a/ICSharpCode.NRefactory.CSharp/Ast/IdentifierExpressionBackreference.cs b/ICSharpCode.NRefactory.CSharp/Ast/IdentifierExpressionBackreference.cs new file mode 100644 index 000000000..89da7231c --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Ast/IdentifierExpressionBackreference.cs @@ -0,0 +1,54 @@ +// 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.Linq; +using ICSharpCode.NRefactory.PatternMatching; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Matches identifier expressions that have the same identifier as the referenced variable/type definition/method definition. + /// + public class IdentifierExpressionBackreference : Pattern + { + readonly string referencedGroupName; + + public string ReferencedGroupName { + get { return referencedGroupName; } + } + + public IdentifierExpressionBackreference(string referencedGroupName) + { + if (referencedGroupName == null) + throw new ArgumentNullException("referencedGroupName"); + this.referencedGroupName = referencedGroupName; + } + + public override bool DoMatch(INode other, Match match) + { + CSharp.IdentifierExpression ident = other as CSharp.IdentifierExpression; + if (ident == null || ident.TypeArguments.Any()) + return false; + CSharp.AstNode referenced = (CSharp.AstNode)match.Get(referencedGroupName).Last(); + if (referenced == null) + return false; + return ident.Identifier == referenced.GetChildByRole(CSharp.AstNode.Roles.Identifier).Name; + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs b/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs rename to ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs index 771623eac..b551e77ee 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/MemberType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/MemberType.cs @@ -1,4 +1,4 @@ -// +// // FullTypeName.cs // // Author: @@ -47,7 +47,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -87,7 +87,7 @@ namespace ICSharpCode.NRefactory.CSharp { } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitMemberType (this, data); } @@ -109,7 +109,7 @@ namespace ICSharpCode.NRefactory.CSharp b.Append(this.MemberName); if (this.TypeArguments.Any()) { b.Append('<'); - b.Append(DotNet35Compat.StringJoin(", ", this.TypeArguments)); + b.Append(string.Join(", ", this.TypeArguments)); b.Append('>'); } return b.ToString(); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs b/ICSharpCode.NRefactory.CSharp/Ast/Modifiers.cs similarity index 83% rename from ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Modifiers.cs index 700a3c04d..eb320495c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Modifiers.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Modifiers.cs @@ -30,7 +30,6 @@ using System; namespace ICSharpCode.NRefactory.CSharp { - // For compatibility with old nrefactory - same flags. [Flags] public enum Modifiers { @@ -54,21 +53,13 @@ namespace ICSharpCode.NRefactory.CSharp Extern = 0x2000, Volatile = 0x4000, Unsafe = 0x8000, + Async = 0x10000, - //Overloads = 0x10000, - //WithEvents = 0x20000, - //Default = 0x40000, - Fixed = 0x80000, - - //ProtectedOrInternal = Internal | Protected, - //ProtectedAndInternal = 0x100000, (not supported in C#) - //SpecialName = 0x200000, - //Final = 0x400000, - //Literal = 0x800000, VisibilityMask = Private | Internal | Protected | Public, /// /// Special value used to match any modifiers during pattern matching. /// Any = unchecked((int)0x80000000) - }} + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs b/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs similarity index 93% rename from ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs rename to ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs index 5fd175c77..2240130b8 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/NodeType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/NodeType.cs @@ -45,6 +45,10 @@ namespace ICSharpCode.NRefactory.CSharp Token, QueryClause, /// + /// Comment or whitespace or pre-processor directive + /// + Whitespace, + /// /// Placeholder for a pattern /// Pattern diff --git a/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs b/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs rename to ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs index 253f6ef3c..9088ca0e3 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/ObservableAstVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/ObservableAstVisitor.cs @@ -1,4 +1,4 @@ -// +// // ObservableAstVisitor.cs // // Author: @@ -671,11 +671,11 @@ namespace ICSharpCode.NRefactory.CSharp return VisitChildren (yieldBreakStatement, data); } - public event Action YieldStatementVisited; + public event Action YieldReturnStatementVisited; - S IAstVisitor.VisitYieldStatement (YieldStatement yieldStatement, T data) + S IAstVisitor.VisitYieldReturnStatement (YieldReturnStatement yieldStatement, T data) { - var handler = YieldStatementVisited; + var handler = YieldReturnStatementVisited; if (handler != null) handler (yieldStatement, data); return VisitChildren (yieldStatement, data); @@ -1121,6 +1121,16 @@ 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 EmptyExpressionVisited; S IAstVisitor.VisitEmptyExpression (EmptyExpression emptyExpression, T data) diff --git a/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs b/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs similarity index 84% rename from ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs rename to ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs index 26c93b21a..92705e96a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/PrimitiveType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/PrimitiveType.cs @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp public class PrimitiveType : AstType, IRelocatable { public string Keyword { get; set; } - public AstLocation Location { get; set; } + public TextLocation Location { get; set; } public PrimitiveType() { @@ -43,32 +43,32 @@ namespace ICSharpCode.NRefactory.CSharp this.Keyword = keyword; } - public PrimitiveType(string keyword, AstLocation location) + public PrimitiveType(string keyword, TextLocation location) { this.Keyword = keyword; this.Location = location; } - public override AstLocation StartLocation { + public override TextLocation StartLocation { get { return Location; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (Location.Line, Location.Column + (Keyword != null ? Keyword.Length : 0)); + return new TextLocation (Location.Line, Location.Column + (Keyword != null ? Keyword.Length : 0)); } } #region IRelocationable implementation - void IRelocatable.SetStartLocation (AstLocation startLocation) + void IRelocatable.SetStartLocation (TextLocation startLocation) { this.Location = startLocation; } #endregion - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitPrimitiveType (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs b/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs similarity index 94% rename from ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs rename to ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs index 2609473e7..280511da0 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/SimpleType.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/SimpleType.cs @@ -1,4 +1,4 @@ -// +// // FullTypeName.cs // // Author: @@ -42,7 +42,7 @@ namespace ICSharpCode.NRefactory.CSharp this.Identifier = identifier; } - public SimpleType(string identifier, AstLocation location) + public SimpleType(string identifier, TextLocation location) { SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (identifier, location)); } @@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, CSharp.Identifier.Create (value, TextLocation.Empty)); } } @@ -81,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.TypeArgument); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitSimpleType (this, data); } @@ -97,7 +97,7 @@ namespace ICSharpCode.NRefactory.CSharp StringBuilder b = new StringBuilder(this.Identifier); if (this.TypeArguments.Any()) { b.Append('<'); - b.Append(DotNet35Compat.StringJoin(", ", this.TypeArguments)); + b.Append(string.Join(", ", this.TypeArguments)); b.Append('>'); } return b.ToString(); diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs index 50cf3e6cd..e42f13b6c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/BlockStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/BlockStatement.cs @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -76,7 +76,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } @@ -105,7 +105,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBrace); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitBlockStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/BreakStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/BreakStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/BreakStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/BreakStatement.cs index 6599b5eaf..5c993f896 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/BreakStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/BreakStatement.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitBreakStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/CheckedStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/CheckedStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/CheckedStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/CheckedStatement.cs index 731649f4a..c81724b91 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/CheckedStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/CheckedStatement.cs @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (body, Roles.Body); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCheckedStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ContinueStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ContinueStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/ContinueStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/ContinueStatement.cs index 1de6b5d50..cb8cf30e6 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ContinueStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ContinueStatement.cs @@ -35,7 +35,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitContinueStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/DoWhileStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/DoWhileStatement.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/DoWhileStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/DoWhileStatement.cs index 378fd43ab..9e0cc4a43 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/DoWhileStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/DoWhileStatement.cs @@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitDoWhileStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/EmptyStatement.cs similarity index 86% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/EmptyStatement.cs index c75adbec6..e0c899983 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/EmptyStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/EmptyStatement.cs @@ -1,4 +1,4 @@ -// +// // EmptyStatement.cs // // Author: @@ -31,31 +31,31 @@ namespace ICSharpCode.NRefactory.CSharp /// public class EmptyStatement : Statement, IRelocatable { - public AstLocation Location { + public TextLocation Location { get; set; } - public override AstLocation StartLocation { + public override TextLocation StartLocation { get { return Location; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (Location.Line, Location.Column); + return new TextLocation (Location.Line, Location.Column + 1); } } #region IRelocationable implementation - void IRelocatable.SetStartLocation (AstLocation startLocation) + void IRelocatable.SetStartLocation (TextLocation startLocation) { this.Location = startLocation; } #endregion - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitEmptyStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ExpressionStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ExpressionStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/ExpressionStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/ExpressionStatement.cs index 4e76bd5bb..3954d5e42 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ExpressionStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ExpressionStatement.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitExpressionStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/FixedStatement.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/FixedStatement.cs index 9a8efbc9a..263cf8fbd 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/FixedStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/FixedStatement.cs @@ -59,7 +59,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.EmbeddedStatement, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitFixedStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ForStatement.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/ForStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/ForStatement.cs index ebbe44022..a6c91b322 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ForStatement.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.EmbeddedStatement, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitForStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ForeachStatement.cs similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/ForeachStatement.cs index 52be5da59..ccd3ecdeb 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ForeachStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ForeachStatement.cs @@ -1,4 +1,4 @@ -// +// // ForeachStatement.cs // // Author: @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -80,7 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.EmbeddedStatement, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitForeachStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/GotoStatement.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/GotoStatement.cs index 0bcc5e238..c02e223d6 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/GotoStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/GotoStatement.cs @@ -1,4 +1,4 @@ -// +// // GotoStatement.cs // // Author: @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.CSharp if (string.IsNullOrEmpty(value)) SetChildByRole(Roles.Identifier, null); else - SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -60,7 +60,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitGotoStatement (this, data); } @@ -99,7 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitGotoCaseStatement (this, data); } @@ -130,7 +130,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitGotoDefaultStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/IfElseStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/IfElseStatement.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/IfElseStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/IfElseStatement.cs index 8fa84392d..803d7bf8a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/IfElseStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/IfElseStatement.cs @@ -69,7 +69,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (FalseRole, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitIfElseStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/LabelStatement.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/LabelStatement.cs index b23c80a4c..6b3a08cf8 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/LabelStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/LabelStatement.cs @@ -1,4 +1,4 @@ -// +// // LabelStatement.cs // // Author: @@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole(Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole(Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -44,7 +44,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Colon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitLabelStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/LockStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/LockStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/LockStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/LockStatement.cs index 7298e4f1d..8a5f2f76f 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/LockStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/LockStatement.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.EmbeddedStatement, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitLockStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ReturnStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ReturnStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/ReturnStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/ReturnStatement.cs index 075a22589..8219490d7 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ReturnStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ReturnStatement.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (returnExpression, Roles.Expression); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitReturnStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/Statement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/Statement.cs similarity index 87% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/Statement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/Statement.cs index e2d607571..665a5dfd7 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/Statement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/Statement.cs @@ -2,7 +2,6 @@ // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; -using System.IO; namespace ICSharpCode.NRefactory.CSharp { @@ -26,7 +25,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -57,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } @@ -93,15 +92,7 @@ namespace ICSharpCode.NRefactory.CSharp // Make debugging easier by giving Statements a ToString() implementation public override string ToString() { - if (IsNull) - return "Null"; - StringWriter w = new StringWriter(); - AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); - string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); - if (text.Length > 100) - return text.Substring(0, 97) + "..."; - else - return text; + return DebugToString(); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/SwitchStatement.cs similarity index 95% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/SwitchStatement.cs index c3fd4dd3f..bf5ca7a83 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/SwitchStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/SwitchStatement.cs @@ -65,7 +65,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBrace); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitSwitchStatement (this, data); } @@ -98,7 +98,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } @@ -131,7 +131,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.EmbeddedStatement); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitSwitchSection (this, data); } @@ -151,6 +151,9 @@ namespace ICSharpCode.NRefactory.CSharp } } + /// + /// Gets or sets the expression. The expression can be null - if the expression is null, it's the default switch section. + /// public Expression Expression { get { return GetChildByRole (Roles.Expression); } set { SetChildByRole (Roles.Expression, value); } @@ -165,7 +168,7 @@ namespace ICSharpCode.NRefactory.CSharp this.Expression = expression; } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCaseLabel (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ThrowStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ThrowStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/ThrowStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/ThrowStatement.cs index 2eafdd977..5d42af3cc 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/ThrowStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/ThrowStatement.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (expression, Roles.Expression); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitThrowStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/TryCatchStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/TryCatchStatement.cs index 77ef45e6b..711a6f491 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/TryCatchStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/TryCatchStatement.cs @@ -1,4 +1,4 @@ -// +// // TryCatchStatement.cs // // Author: @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (FinallyBlockRole, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitTryCatchStatement (this, data); } @@ -98,7 +98,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } @@ -140,7 +140,7 @@ namespace ICSharpCode.NRefactory.CSharp if (string.IsNullOrEmpty(value)) SetChildByRole (Roles.Identifier, null); else - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -162,7 +162,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Body, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCatchClause (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/UncheckedStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/UncheckedStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/UncheckedStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/UncheckedStatement.cs index af40fa5a9..086cff854 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/UncheckedStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/UncheckedStatement.cs @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp AddChild (body, Roles.Body); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUncheckedStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/UnsafeStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/UnsafeStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/UnsafeStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/UnsafeStatement.cs index c5ccb63af..fba1ebe43 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/UnsafeStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/UnsafeStatement.cs @@ -40,7 +40,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Body, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUnsafeStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/UsingStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/UsingStatement.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/UsingStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/UsingStatement.cs index 27714d61b..030ce0368 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/UsingStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/UsingStatement.cs @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.EmbeddedStatement, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitUsingStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/VariableDeclarationStatement.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/VariableDeclarationStatement.cs index 54f473684..c9792125f 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/VariableDeclarationStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/VariableDeclarationStatement.cs @@ -66,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp return Variables.FirstOrDefault (vi => vi.Name == name); } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitVariableDeclarationStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/WhileStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/WhileStatement.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/WhileStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/WhileStatement.cs index 01470b3ab..db71887c4 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/WhileStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/WhileStatement.cs @@ -55,7 +55,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.EmbeddedStatement, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitWhileStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldBreakStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/YieldBreakStatement.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldBreakStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/YieldBreakStatement.cs index 4c572615a..253253fef 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldBreakStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/YieldBreakStatement.cs @@ -46,7 +46,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitYieldBreakStatement (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldStatement.cs b/ICSharpCode.NRefactory.CSharp/Ast/Statements/YieldReturnStatement.cs similarity index 92% rename from ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldStatement.cs rename to ICSharpCode.NRefactory.CSharp/Ast/Statements/YieldReturnStatement.cs index 001815f3a..a3b65ac2a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Statements/YieldStatement.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/Statements/YieldReturnStatement.cs @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// yield return Expression; /// - public class YieldStatement : Statement + public class YieldReturnStatement : Statement { public static readonly Role YieldKeywordRole = new Role("YieldKeyword", CSharpTokenNode.Null); public static readonly Role ReturnKeywordRole = new Role("ReturnKeyword", CSharpTokenNode.Null); @@ -51,14 +51,14 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.Semicolon); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { - return visitor.VisitYieldStatement (this, data); + return visitor.VisitYieldReturnStatement (this, data); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { - YieldStatement o = other as YieldStatement; + YieldReturnStatement o = other as YieldReturnStatement; return o != null && this.Expression.DoMatch(o.Expression, match); } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs index 748948f6a..0755e0436 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/Accessor.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/Accessor.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -57,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Body, value); } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitAccessor (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/AttributedNode.cs similarity index 62% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/AttributedNode.cs index 019c55444..f854c594a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/AttributedNode.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/AttributedNode.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -42,7 +57,7 @@ namespace ICSharpCode.NRefactory.CSharp if ((m & newValue) != 0) { if ((m & oldValue) == 0) { // Modifier was added - var newToken = new CSharpModifierToken(AstLocation.Empty, m); + var newToken = new CSharpModifierToken(TextLocation.Empty, m); node.InsertChildAfter(insertionPos, newToken, ModifierRole); insertionPos = newToken; } else { diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ConstructorDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ConstructorDeclaration.cs index afcc2d47d..f356e93ab 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ConstructorDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ConstructorDeclaration.cs @@ -71,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Member; } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitConstructorDeclaration (this, data); } @@ -106,7 +106,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return default (S); } @@ -140,7 +140,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RPar); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitConstructorInitializer (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/DestructorDeclaration.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/DestructorDeclaration.cs index 829682e73..0e129e433 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/DestructorDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/DestructorDeclaration.cs @@ -62,7 +62,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Member; } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitDestructorDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs index 8c3156298..f646a9385 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EnumMemberDeclaration.cs @@ -1,4 +1,4 @@ -// +// // EnumMemberDeclaration.cs // // Author: @@ -36,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -58,7 +58,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Member; } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitEnumMemberDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EventDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EventDeclaration.cs index 49d28ede3..752463a2e 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/EventDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/EventDeclaration.cs @@ -43,7 +43,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.Variable); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitEventDeclaration (this, data); } @@ -79,7 +79,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBrace); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitCustomEventDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FieldDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FieldDeclaration.cs index 1003aa9b7..2b30b2be3 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FieldDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FieldDeclaration.cs @@ -44,7 +44,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (Roles.Variable); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitFieldDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs index 2fde82260..ea20b3585 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedFieldDeclaration.cs @@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildrenByRole (VariableRole); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitFixedFieldDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedVariableInitializer.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedVariableInitializer.cs index 1d5d9da93..11bbc138a 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/FixedVariableInitializer.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/FixedVariableInitializer.cs @@ -1,4 +1,4 @@ -// +// // FixedFieldDeclaration.cs // // Author: @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -80,7 +80,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBracket); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitFixedVariableInitializer (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/IndexerDeclaration.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/IndexerDeclaration.cs index 4d19c97d7..221a6dde8 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/IndexerDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/IndexerDeclaration.cs @@ -64,7 +64,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBrace); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitIndexerDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MemberDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MemberDeclaration.cs index f2fd81683..e1463c077 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MemberDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MemberDeclaration.cs @@ -1,4 +1,4 @@ -// +// // AbstractMember.cs // // Author: @@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MethodDeclaration.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MethodDeclaration.cs index 556c0a3a4..129c87e26 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/MethodDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/MethodDeclaration.cs @@ -63,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitMethodDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/OperatorDeclaration.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/OperatorDeclaration.cs index 31d123232..35865d24c 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/OperatorDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/OperatorDeclaration.cs @@ -28,7 +28,7 @@ using System.Linq; namespace ICSharpCode.NRefactory.CSharp { - public enum OperatorType + public enum OperatorType { // Values must correspond to Mono.CSharp.Operator.OpType // due to the casts used in OperatorDeclaration. @@ -129,7 +129,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Member; } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitOperatorDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs index 287611ef6..332973004 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/ParameterDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/ParameterDeclaration.cs @@ -1,4 +1,4 @@ -// +// // ParameterDeclarationExpression.cs // // Author: @@ -68,7 +68,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -86,7 +86,7 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Expression, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitParameterDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/PropertyDeclaration.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/PropertyDeclaration.cs index 2d1376a0e..536266750 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/PropertyDeclaration.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/PropertyDeclaration.cs @@ -49,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return GetChildByRole (Roles.RBrace); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitPropertyDeclaration (this, data); } diff --git a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/VariableInitializer.cs similarity index 92% rename from ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs rename to ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/VariableInitializer.cs index 6e1d57272..314fca0c9 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/TypeMembers/VariableInitializer.cs +++ b/ICSharpCode.NRefactory.CSharp/Ast/TypeMembers/VariableInitializer.cs @@ -1,4 +1,4 @@ -// +// // VariableInitializer.cs // // Author: @@ -47,7 +47,7 @@ namespace ICSharpCode.NRefactory.CSharp get { return NodeType.Pattern; } } - public override S AcceptVisitor(IAstVisitor visitor, T data) + public override S AcceptVisitor(IAstVisitor visitor, T data = default(T)) { return visitor.VisitPatternPlaceholder(this, child, data); } @@ -85,7 +85,7 @@ namespace ICSharpCode.NRefactory.CSharp return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, Identifier.Create (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, Identifier.Create (value, TextLocation.Empty)); } } @@ -107,11 +107,19 @@ namespace ICSharpCode.NRefactory.CSharp set { SetChildByRole (Roles.Expression, value); } } - public override S AcceptVisitor (IAstVisitor visitor, T data) + public override S AcceptVisitor (IAstVisitor visitor, T data = default(T)) { return visitor.VisitVariableInitializer (this, data); } + public override string ToString() + { + if (this.Initializer.IsNull) + return "[VariableInitializer " + this.Name + "]"; + else + return "[VariableInitializer " + this.Name + " = " + this.Initializer.ToString() + "]"; + } + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { VariableInitializer o = other as VariableInitializer; diff --git a/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs new file mode 100644 index 000000000..45a2ec2dd --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Completion/CSharpCompletionEngine.cs @@ -0,0 +1,51 @@ +// +// CSharpCompletionEngine.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using System.Collections.Generic; +using ICSharpCode.NRefactory.Completion; +using ICSharpCode.NRefactory.Editor; + +namespace ICSharpCode.NRefactory.CSharp.Completion +{ + public class CSharpCompletionEngine + { + IDocument document; + ICompletionDataFactory factory; + + public CSharpCompletionEngine (IDocument document, ICompletionDataFactory factory) + { + this.document = document; + this.factory = factory; + } + + public IEnumerable GetCompletionData (int offset) + { + // BIG TODO !!!! + yield break; + } + } +} + diff --git a/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs b/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs similarity index 88% rename from ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs rename to ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs index 2b08ae116..7b1779a37 100644 --- a/ICSharpCode.NRefactory/CSharp/Formatter/AstFormattingVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Formatter/AstFormattingVisitor.cs @@ -1,4 +1,4 @@ -// +// // AstFormattingVisitor.cs // // Author: @@ -27,6 +27,7 @@ using System; using System.Text; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.Editor; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.CSharp.Refactoring; @@ -35,7 +36,7 @@ namespace ICSharpCode.NRefactory.CSharp public class AstFormattingVisitor : DepthFirstAstVisitor { CSharpFormattingOptions policy; - ITextEditorAdapter data; + IDocument document; IActionFactory factory; List changes = new List (); Indent curIndent = new Indent (); @@ -67,16 +68,20 @@ namespace ICSharpCode.NRefactory.CSharp get; set; } + + public string EolMarker { get; set; } - public AstFormattingVisitor (CSharpFormattingOptions policy, ITextEditorAdapter data, IActionFactory factory) + public AstFormattingVisitor (CSharpFormattingOptions policy, IDocument document, IActionFactory factory, + bool tabsToSpaces = false, int indentationSize = 4) { if (factory == null) throw new ArgumentNullException ("factory"); this.policy = policy; - this.data = data; - this.curIndent.TabsToSpaces = this.data.TabsToSpaces; - this.curIndent.TabSize = this.data.TabSize; + this.document = document; + this.curIndent.TabsToSpaces = tabsToSpaces; + this.curIndent.TabSize = indentationSize; this.factory = factory; + this.EolMarker = Environment.NewLine; CorrectBlankLines = true; } @@ -94,21 +99,23 @@ namespace ICSharpCode.NRefactory.CSharp int line = loc.Line; do { line++; - } while (line < data.LineCount && data.GetEditableLength (line) == data.GetIndentation (line).Length); - var start = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + } while (line < document.LineCount && IsSpacing(document.GetLineByNumber(line))); + var start = document.GetOffset (node.EndLocation); int foundBlankLines = line - loc.Line - 1; StringBuilder sb = new StringBuilder (); for (int i = 0; i < blankLines - foundBlankLines; i++) - sb.Append (data.EolMarker); + sb.Append (this.EolMarker); int ws = start; - while (ws < data.Length && IsSpacing (data.GetCharAt (ws))) + while (ws < document.TextLength && IsSpacing (document.GetCharAt (ws))) ws++; int removedChars = ws - start; - if (foundBlankLines > blankLines) - removedChars += data.GetLineEndOffset (loc.Line + foundBlankLines - blankLines) - data.GetLineEndOffset (loc.Line); + if (foundBlankLines > blankLines) { + removedChars += document.GetLineByNumber (loc.Line + foundBlankLines - blankLines).EndOffset + - document.GetLineByNumber (loc.Line).EndOffset; + } AddChange (start, removedChars, sb.ToString ()); } @@ -120,12 +127,12 @@ namespace ICSharpCode.NRefactory.CSharp int line = loc.Line; do { line--; - } while (line > 0 && data.GetEditableLength (line) == data.GetIndentation (line).Length); - int end = data.GetLineOffset (loc.Line); - int start = line >= 1 ? data.GetLineEndOffset (line) : 0; + } while (line > 0 && IsSpacing(document.GetLineByNumber(line))); + int end = document.GetOffset (loc.Line, 1); + int start = document.GetOffset (line + 1, 1); StringBuilder sb = new StringBuilder (); for (int i = 0; i < blankLines; i++) - sb.Append (data.EolMarker); + sb.Append (this.EolMarker); AddChange (start, end - start, sb.ToString ()); } @@ -166,7 +173,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitTypeDeclaration (TypeDeclaration typeDeclaration, object data) { - FixIndentationForceNewLine (typeDeclaration.StartLocation); + FormatAttributedNode (typeDeclaration); BraceStyle braceStyle; bool indentBody = false; switch (typeDeclaration.ClassType) { @@ -216,6 +223,16 @@ namespace ICSharpCode.NRefactory.CSharp { return ch == ' ' || ch == '\t'; } + + bool IsSpacing (ISegment segment) + { + int endOffset = segment.EndOffset; + for (int i = segment.Offset; i < endOffset; i++) { + if (!IsSpacing(document.GetCharAt(i))) + return false; + } + return true; + } int SearchLastNonWsChar (int startOffset, int endOffset) { @@ -226,18 +243,18 @@ namespace ICSharpCode.NRefactory.CSharp int result = -1; bool inComment = false; - for (int i = startOffset; i < endOffset && i < data.Length; i++) { - char ch = data.GetCharAt (i); + for (int i = startOffset; i < endOffset && i < document.TextLength; i++) { + char ch = document.GetCharAt (i); if (IsSpacing (ch)) continue; - if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') + if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '/') return result; - if (ch == '/' && i + 1 < data.Length && data.GetCharAt (i + 1) == '*') { + if (ch == '/' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '*') { inComment = true; i++; continue; } - if (inComment && ch == '*' && i + 1 < data.Length && data.GetCharAt (i + 1) == '/') { + if (inComment && ch == '*' && i + 1 < document.TextLength && document.GetCharAt (i + 1) == '/') { inComment = false; i++; continue; @@ -270,12 +287,12 @@ namespace ICSharpCode.NRefactory.CSharp { if (n == null) return; - AstLocation location = n.EndLocation; - int offset = data.LocationToOffset (location.Line, location.Column); - if (location.Column > data.GetEditableLength (location.Line)) + TextLocation location = n.EndLocation; + int offset = document.GetOffset (location); + if (location.Column > document.GetLineByNumber (location.Line).Length) return; int i = offset; - while (i < data.Length && IsSpacing (data.GetCharAt (i))) { + while (i < document.TextLength && IsSpacing (document.GetCharAt (i))) { i++; } ForceSpace (offset - 1, i, forceSpaces); @@ -301,14 +318,14 @@ namespace ICSharpCode.NRefactory.CSharp { if (n == null || n.IsNull) return 0; - AstLocation location = n.StartLocation; + TextLocation location = n.StartLocation; // respect manual line breaks. - if (location.Column <= 1 || data.GetIndentation (location.Line).Length == location.Column - 1) + if (location.Column <= 1 || GetIndentation (location.Line).Length == location.Column - 1) return 0; - int offset = data.LocationToOffset (location.Line, location.Column); + int offset = document.GetOffset (location); int i = offset - 1; - while (i >= 0 && IsSpacing (data.GetCharAt (i))) { + while (i >= 0 && IsSpacing (document.GetCharAt (i))) { i--; } ForceSpace (i, offset, forceSpaces); @@ -317,7 +334,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitPropertyDeclaration (PropertyDeclaration propertyDeclaration, object data) { - FixIndentationForceNewLine (propertyDeclaration.StartLocation); + FormatAttributedNode (propertyDeclaration); bool oneLine = false; switch (policy.PropertyFormatting) { case PropertyFormatting.AllowOneLine: @@ -337,14 +354,14 @@ namespace ICSharpCode.NRefactory.CSharp case PropertyFormatting.ForceOneLine: isSimple = IsSimpleAccessor (propertyDeclaration.Getter) && IsSimpleAccessor (propertyDeclaration.Setter); if (isSimple) { - int offset = this.data.LocationToOffset (propertyDeclaration.LBraceToken.StartLocation.Line, propertyDeclaration.LBraceToken.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.LBraceToken.StartLocation); int start = SearchWhitespaceStart (offset); int end = SearchWhitespaceEnd (offset); AddChange (start, offset - start, " "); AddChange (offset + 1, end - offset - 2, " "); - offset = this.data.LocationToOffset (propertyDeclaration.RBraceToken.StartLocation.Line, propertyDeclaration.RBraceToken.StartLocation.Column); + offset = this.document.GetOffset (propertyDeclaration.RBraceToken.StartLocation); start = SearchWhitespaceStart (offset); AddChange (start, offset - start, " "); oneLine = true; @@ -360,15 +377,15 @@ namespace ICSharpCode.NRefactory.CSharp if (!propertyDeclaration.Getter.IsNull) { if (!oneLine) { if (!IsLineIsEmptyUpToEol (propertyDeclaration.Getter.StartLocation)) { - int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Getter.StartLocation); int start = SearchWhitespaceStart (offset); string indentString = this.curIndent.IndentString; - AddChange (start, offset - start, this.data.EolMarker + indentString); + AddChange (start, offset - start, this.EolMarker + indentString); } else { FixIndentation (propertyDeclaration.Getter.StartLocation); } } else { - int offset = this.data.LocationToOffset (propertyDeclaration.Getter.StartLocation.Line, propertyDeclaration.Getter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Getter.StartLocation); int start = SearchWhitespaceStart (offset); AddChange (start, offset - start, " "); @@ -388,15 +405,15 @@ namespace ICSharpCode.NRefactory.CSharp if (!propertyDeclaration.Setter.IsNull) { if (!oneLine) { if (!IsLineIsEmptyUpToEol (propertyDeclaration.Setter.StartLocation)) { - int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Setter.StartLocation); int start = SearchWhitespaceStart (offset); string indentString = this.curIndent.IndentString; - AddChange (start, offset - start, this.data.EolMarker + indentString); + AddChange (start, offset - start, this.EolMarker + indentString); } else { FixIndentation (propertyDeclaration.Setter.StartLocation); } } else { - int offset = this.data.LocationToOffset (propertyDeclaration.Setter.StartLocation.Line, propertyDeclaration.Setter.StartLocation.Column); + int offset = this.document.GetOffset (propertyDeclaration.Setter.StartLocation); int start = SearchWhitespaceStart (offset); AddChange (start, offset - start, " "); @@ -429,7 +446,7 @@ namespace ICSharpCode.NRefactory.CSharp FormatCommas (indexerDeclaration, policy.SpaceBeforeIndexerDeclarationParameterComma, policy.SpaceAfterIndexerDeclarationParameterComma); - FixIndentationForceNewLine (indexerDeclaration.StartLocation); + FormatAttributedNode (indexerDeclaration); EnforceBraceStyle (policy.PropertyBraceStyle, indexerDeclaration.LBraceToken, indexerDeclaration.RBraceToken); if (policy.IndentPropertyBody) IndentLevel++; @@ -471,7 +488,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitCustomEventDeclaration (CustomEventDeclaration eventDeclaration, object data) { - FixIndentationForceNewLine (eventDeclaration.StartLocation); + FormatAttributedNode (eventDeclaration); EnforceBraceStyle (policy.EventBraceStyle, eventDeclaration.LBraceToken, eventDeclaration.RBraceToken); if (policy.IndentEventBody) IndentLevel++; @@ -514,7 +531,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitEventDeclaration (EventDeclaration eventDeclaration, object data) { - FixIndentationForceNewLine (eventDeclaration.StartLocation); + FormatAttributedNode (eventDeclaration); if (eventDeclaration.NextSibling is EventDeclaration && IsSimpleEvent (eventDeclaration) && IsSimpleEvent (eventDeclaration.NextSibling)) { EnsureBlankLinesAfter (eventDeclaration, policy.BlankLinesBetweenEventFields); } else if (IsMember (eventDeclaration.NextSibling)) { @@ -532,7 +549,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitFieldDeclaration (FieldDeclaration fieldDeclaration, object data) { - FixIndentationForceNewLine (fieldDeclaration.StartLocation); + FormatAttributedNode (fieldDeclaration); FormatCommas (fieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); if (fieldDeclaration.NextSibling is FieldDeclaration || fieldDeclaration.NextSibling is FixedFieldDeclaration) { EnsureBlankLinesAfter (fieldDeclaration, policy.BlankLinesBetweenFields); @@ -544,7 +561,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitFixedFieldDeclaration (FixedFieldDeclaration fixedFieldDeclaration, object data) { - FixIndentationForceNewLine (fixedFieldDeclaration.StartLocation); + FormatAttributedNode (fixedFieldDeclaration); FormatCommas (fixedFieldDeclaration, policy.SpaceBeforeFieldDeclarationComma, policy.SpaceAfterFieldDeclarationComma); if (fixedFieldDeclaration.NextSibling is FieldDeclaration || fixedFieldDeclaration.NextSibling is FixedFieldDeclaration) { EnsureBlankLinesAfter (fixedFieldDeclaration, policy.BlankLinesBetweenFields); @@ -556,13 +573,13 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitEnumMemberDeclaration (EnumMemberDeclaration enumMemberDeclaration, object data) { - FixIndentationForceNewLine (enumMemberDeclaration.StartLocation); + FormatAttributedNode (enumMemberDeclaration); return base.VisitEnumMemberDeclaration (enumMemberDeclaration, data); } public override object VisitDelegateDeclaration (DelegateDeclaration delegateDeclaration, object data) { - FixIndentation (delegateDeclaration.StartLocation); + FormatAttributedNode (delegateDeclaration); ForceSpacesBefore (delegateDeclaration.LParToken, policy.SpaceBeforeDelegateDeclarationParentheses); if (delegateDeclaration.Parameters.Any ()) { @@ -587,10 +604,23 @@ namespace ICSharpCode.NRefactory.CSharp { return nextSibling != null && nextSibling.NodeType == NodeType.Member; } - + + void FormatAttributedNode (AstNode node) + { + if (node == null) + return; + AstNode child = node.FirstChild; + while (child != null && child is AttributeSection) { + FixIndentationForceNewLine (child.StartLocation); + child = child.NextSibling; + } + if (child != null) + FixIndentationForceNewLine (child.StartLocation); + } + public override object VisitMethodDeclaration (MethodDeclaration methodDeclaration, object data) { - FixIndentationForceNewLine (methodDeclaration.StartLocation); + FormatAttributedNode (methodDeclaration); ForceSpacesBefore (methodDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); if (methodDeclaration.Parameters.Any ()) { @@ -618,7 +648,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitOperatorDeclaration (OperatorDeclaration operatorDeclaration, object data) { - FixIndentationForceNewLine (operatorDeclaration.StartLocation); + FormatAttributedNode (operatorDeclaration); ForceSpacesBefore (operatorDeclaration.LParToken, policy.SpaceBeforeMethodDeclarationParentheses); if (operatorDeclaration.Parameters.Any ()) { @@ -646,7 +676,7 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitConstructorDeclaration (ConstructorDeclaration constructorDeclaration, object data) { - FixIndentationForceNewLine (constructorDeclaration.StartLocation); + FormatAttributedNode (constructorDeclaration); ForceSpacesBefore (constructorDeclaration.LParToken, policy.SpaceBeforeConstructorDeclarationParentheses); if (constructorDeclaration.Parameters.Any ()) { @@ -674,10 +704,10 @@ namespace ICSharpCode.NRefactory.CSharp public override object VisitDestructorDeclaration (DestructorDeclaration destructorDeclaration, object data) { - FixIndentationForceNewLine (destructorDeclaration.StartLocation); + FormatAttributedNode (destructorDeclaration); CSharpTokenNode lParen = destructorDeclaration.LParToken; - int offset = this.data.LocationToOffset (lParen.StartLocation.Line, lParen.StartLocation.Column); + int offset = this.document.GetOffset (lParen.StartLocation); ForceSpaceBefore (offset, policy.SpaceBeforeConstructorDeclarationParentheses); object result = null; @@ -786,9 +816,9 @@ namespace ICSharpCode.NRefactory.CSharp case BraceForcement.AddBraces: if (!isBlock) { AstNode n = node.Parent.GetCSharpNodeBefore (node); - int start = data.LocationToOffset (n.EndLocation.Line, n.EndLocation.Column); + int start = document.GetOffset (n.EndLocation); var next = n.GetNextNode (); - int offset = data.LocationToOffset (next.StartLocation.Line, next.StartLocation.Column); + int offset = document.GetOffset (next.StartLocation); string startBrace = ""; switch (braceStyle) { case BraceStyle.EndOfLineWithoutSpace: @@ -798,15 +828,15 @@ namespace ICSharpCode.NRefactory.CSharp startBrace = " {"; break; case BraceStyle.NextLine: - startBrace = data.EolMarker + curIndent.IndentString + "{"; + startBrace = this.EolMarker + curIndent.IndentString + "{"; break; case BraceStyle.NextLineShifted2: case BraceStyle.NextLineShifted: - startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{"; + startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "{"; break; } - if (IsLineIsEmptyUpToEol (data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column))) - startBrace += data.EolMarker + data.GetIndentation (node.StartLocation.Line); + if (IsLineIsEmptyUpToEol (document.GetOffset (node.StartLocation))) + startBrace += this.EolMarker + GetIndentation (node.StartLocation.Line); AddChange (start, offset - start, startBrace); } break; @@ -814,10 +844,10 @@ namespace ICSharpCode.NRefactory.CSharp if (isBlock) { BlockStatement block = node as BlockStatement; if (block.Statements.Count () == 1) { - int offset1 = data.LocationToOffset (node.StartLocation.Line, node.StartLocation.Column); + int offset1 = document.GetOffset (node.StartLocation); int start = SearchWhitespaceStart (offset1); - int offset2 = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); + int offset2 = document.GetOffset (node.EndLocation); int end = SearchWhitespaceStart (offset2 - 1); AddChange (start, offset1 - start + 1, null); @@ -853,8 +883,8 @@ namespace ICSharpCode.NRefactory.CSharp break; case BraceForcement.AddBraces: if (!isBlock) { - int offset = data.LocationToOffset (node.EndLocation.Line, node.EndLocation.Column); - if (!char.IsWhiteSpace (data.GetCharAt (offset))) + int offset = document.GetOffset (node.EndLocation); + if (!char.IsWhiteSpace (document.GetCharAt (offset))) offset++; string startBrace = ""; switch (braceStyle) { @@ -862,17 +892,17 @@ namespace ICSharpCode.NRefactory.CSharp startBrace = null; break; case BraceStyle.EndOfLineWithoutSpace: - startBrace = data.EolMarker + curIndent.IndentString + "}"; + startBrace = this.EolMarker + curIndent.IndentString + "}"; break; case BraceStyle.EndOfLine: - startBrace = data.EolMarker + curIndent.IndentString + "}"; + startBrace = this.EolMarker + curIndent.IndentString + "}"; break; case BraceStyle.NextLine: - startBrace = data.EolMarker + curIndent.IndentString + "}"; + startBrace = this.EolMarker + curIndent.IndentString + "}"; break; case BraceStyle.NextLineShifted2: case BraceStyle.NextLineShifted: - startBrace = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}"; + startBrace = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent + "}"; break; } if (startBrace != null) @@ -889,10 +919,10 @@ namespace ICSharpCode.NRefactory.CSharp return; // LineSegment lbraceLineSegment = data.Document.GetLine (lbrace.StartLocation.Line); - int lbraceOffset = data.LocationToOffset (lbrace.StartLocation.Line, lbrace.StartLocation.Column); + int lbraceOffset = document.GetOffset (lbrace.StartLocation); // LineSegment rbraceLineSegment = data.Document.GetLine (rbrace.StartLocation.Line); - int rbraceOffset = data.LocationToOffset (rbrace.StartLocation.Line, rbrace.StartLocation.Column); + int rbraceOffset = document.GetOffset (rbrace.StartLocation); int whitespaceStart = SearchWhitespaceStart (lbraceOffset); int whitespaceEnd = SearchWhitespaceLineStart (rbraceOffset); string startIndent = ""; @@ -903,7 +933,7 @@ namespace ICSharpCode.NRefactory.CSharp break; case BraceStyle.EndOfLineWithoutSpace: startIndent = ""; - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; break; case BraceStyle.EndOfLine: var prevNode = lbrace.GetPrevNode (); @@ -914,22 +944,22 @@ namespace ICSharpCode.NRefactory.CSharp while (prevNode is Comment) { prevNode = prevNode.GetPrevNode (); } - whitespaceStart = data.LocationToOffset (prevNode.EndLocation.Line, prevNode.EndLocation.Column); + whitespaceStart = document.GetOffset (prevNode.EndLocation); lbraceOffset = whitespaceStart; startIndent = " {"; } else { startIndent = " "; } - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; break; case BraceStyle.NextLine: - startIndent = data.EolMarker + curIndent.IndentString; - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : data.EolMarker + curIndent.IndentString; + startIndent = this.EolMarker + curIndent.IndentString; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString : this.EolMarker + curIndent.IndentString; break; case BraceStyle.NextLineShifted2: case BraceStyle.NextLineShifted: - startIndent = data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; - endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : data.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + startIndent = this.EolMarker + curIndent.IndentString + curIndent.SingleIndent; + endIndent = IsLineIsEmptyUpToEol (rbraceOffset) ? curIndent.IndentString + curIndent.SingleIndent : this.EolMarker + curIndent.IndentString + curIndent.SingleIndent; break; } @@ -944,7 +974,7 @@ namespace ICSharpCode.NRefactory.CSharp if (changes.Any (c => c.Offset == offset && c.RemovedChars == removedChars && c.InsertedText == insertedText)) return; - string currentText = data.GetTextAt (offset, removedChars); + string currentText = document.GetText (offset, removedChars); if (currentText == insertedText) return; if (currentText.Any (c => !(char.IsWhiteSpace (c) || c == '\r' || c == '\t' || c == '{' || c == '}'))) @@ -971,15 +1001,15 @@ namespace ICSharpCode.NRefactory.CSharp changes.Add (factory.CreateTextReplaceAction (offset, removedChars, insertedText)); } - public bool IsLineIsEmptyUpToEol (AstLocation startLocation) + public bool IsLineIsEmptyUpToEol (TextLocation startLocation) { - return IsLineIsEmptyUpToEol (data.LocationToOffset (startLocation.Line, startLocation.Column) - 1); + return IsLineIsEmptyUpToEol (document.GetOffset (startLocation) - 1); } bool IsLineIsEmptyUpToEol (int startOffset) { for (int offset = startOffset - 1; offset >= 0; offset--) { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); if (ch != ' ' && ch != '\t') return ch == '\n' || ch == '\r'; } @@ -991,7 +1021,7 @@ namespace ICSharpCode.NRefactory.CSharp if (startOffset < 0) throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); for (int offset = startOffset - 1; offset >= 0; offset--) { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); if (!Char.IsWhiteSpace (ch)) { return offset + 1; } @@ -1001,15 +1031,15 @@ namespace ICSharpCode.NRefactory.CSharp int SearchWhitespaceEnd (int startOffset) { - if (startOffset > data.Length) + if (startOffset > document.TextLength) throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); - for (int offset = startOffset + 1; offset < data.Length; offset++) { - char ch = data.GetCharAt (offset); + for (int offset = startOffset + 1; offset < document.TextLength; offset++) { + char ch = document.GetCharAt (offset); if (!Char.IsWhiteSpace (ch)) { return offset + 1; } } - return data.Length - 1; + return document.TextLength - 1; } int SearchWhitespaceLineStart (int startOffset) @@ -1017,7 +1047,7 @@ namespace ICSharpCode.NRefactory.CSharp if (startOffset < 0) throw new ArgumentOutOfRangeException ("startoffset", "value : " + startOffset); for (int offset = startOffset - 1; offset >= 0; offset--) { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); if (ch != ' ' && ch != '\t') { return offset + 1; } @@ -1248,7 +1278,7 @@ namespace ICSharpCode.NRefactory.CSharp return null; } - public override object VisitYieldStatement (YieldStatement yieldStatement, object data) + public override object VisitYieldReturnStatement (YieldReturnStatement yieldStatement, object data) { FixStatementIndentation (yieldStatement.StartLocation); return null; @@ -1466,7 +1496,7 @@ namespace ICSharpCode.NRefactory.CSharp { bool insertedSpace = false; do { - char ch = data.GetCharAt (offset); + char ch = document.GetCharAt (offset); //Console.WriteLine (ch); if (!IsSpacing (ch) && (insertedSpace || !forceSpace)) break; @@ -1524,9 +1554,9 @@ namespace ICSharpCode.NRefactory.CSharp { if (semicolon.IsNull) return; - int endOffset = data.LocationToOffset (semicolon.StartLocation.Line, semicolon.StartLocation.Column); + int endOffset = document.GetOffset (semicolon.StartLocation); int offset = endOffset; - while (offset - 1 > 0 && char.IsWhiteSpace (data.GetCharAt (offset - 1))) { + while (offset - 1 > 0 && char.IsWhiteSpace (document.GetCharAt (offset - 1))) { offset--; } if (offset < endOffset) { @@ -1538,18 +1568,18 @@ namespace ICSharpCode.NRefactory.CSharp { if (keywordNode == null) return; - int offset = data.LocationToOffset (keywordNode.StartLocation.Line, keywordNode.StartLocation.Column); + int offset = document.GetOffset (keywordNode.StartLocation); int whitespaceStart = SearchWhitespaceStart (offset); - string indentString = newLine ? data.EolMarker + this.curIndent.IndentString : " "; + string indentString = newLine ? this.EolMarker + this.curIndent.IndentString : " "; AddChange (whitespaceStart, offset - whitespaceStart, indentString); } string nextStatementIndent = null; - void FixStatementIndentation (AstLocation location) + void FixStatementIndentation (TextLocation location) { - int offset = data.LocationToOffset (location.Line, location.Column); + int offset = document.GetOffset (location); if (offset <= 0) { Console.WriteLine ("possible wrong offset"); Console.WriteLine (Environment.StackTrace); @@ -1557,52 +1587,66 @@ namespace ICSharpCode.NRefactory.CSharp } bool isEmpty = IsLineIsEmptyUpToEol (offset); int lineStart = SearchWhitespaceLineStart (offset); - string indentString = nextStatementIndent == null ? (isEmpty ? "" : data.EolMarker) + this.curIndent.IndentString : nextStatementIndent; + string indentString = nextStatementIndent == null ? (isEmpty ? "" : this.EolMarker) + this.curIndent.IndentString : nextStatementIndent; nextStatementIndent = null; AddChange (lineStart, offset - lineStart, indentString); } - void FixIndentation (AstLocation location) + void FixIndentation (TextLocation location) { FixIndentation (location, 0); } - void FixIndentation (AstLocation location, int relOffset) + void FixIndentation (TextLocation location, int relOffset) { - if (location.Line < 1 || location.Line > data.LineCount) { + if (location.Line < 1 || location.Line > document.LineCount) { Console.WriteLine ("Invalid location " + location); Console.WriteLine (Environment.StackTrace); return; } - string lineIndent = data.GetIndentation (location.Line); + string lineIndent = GetIndentation (location.Line); string indentString = this.curIndent.IndentString; if (indentString != lineIndent && location.Column - 1 + relOffset == lineIndent.Length) { - AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + AddChange (document.GetOffset (location.Line, 1), lineIndent.Length, indentString); } } - void FixIndentationForceNewLine (AstLocation location) + void FixIndentationForceNewLine (TextLocation location) { - string lineIndent = data.GetIndentation (location.Line); + string lineIndent = GetIndentation (location.Line); string indentString = this.curIndent.IndentString; if (location.Column - 1 == lineIndent.Length) { - AddChange (data.GetLineOffset (location.Line), lineIndent.Length, indentString); + AddChange (document.GetOffset (location.Line, 1), lineIndent.Length, indentString); } else { - int offset = data.LocationToOffset (location.Line, location.Column); + int offset = document.GetOffset (location); int start = SearchWhitespaceLineStart (offset); if (start > 0) { - char ch = data.GetCharAt (start - 1); + char ch = document.GetCharAt (start - 1); if (ch == '\n') { start--; - if (start > 1 && data.GetCharAt (start - 1) == '\r') + if (start > 1 && document.GetCharAt (start - 1) == '\r') start--; } else if (ch == '\r') { start--; } - AddChange (start, offset - start, data.EolMarker + indentString); + AddChange (start, offset - start, this.EolMarker + indentString); } } } + + string GetIndentation(int lineNumber) + { + IDocumentLine line = document.GetLineByNumber(lineNumber); + StringBuilder b = new StringBuilder(); + int endOffset = line.EndOffset; + for (int i = line.Offset; i < endOffset; i++) { + char c = document.GetCharAt(i); + if (!IsSpacing(c)) + break; + b.Append(c); + } + return b.ToString(); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Formatter/CSharpFormattingOptions.cs b/ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Formatter/CSharpFormattingOptions.cs rename to ICSharpCode.NRefactory.CSharp/Formatter/CSharpFormattingOptions.cs diff --git a/ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs b/ICSharpCode.NRefactory.CSharp/Formatter/Indent.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Formatter/Indent.cs rename to ICSharpCode.NRefactory.CSharp/Formatter/Indent.cs diff --git a/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj new file mode 100644 index 000000000..633504288 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/ICSharpCode.NRefactory.CSharp.csproj @@ -0,0 +1,313 @@ + + + + {53DCA265-3C3C-42F9-B647-F72BA678122B} + Debug + AnyCPU + Library + ICSharpCode.NRefactory.CSharp + ICSharpCode.NRefactory.CSharp + Properties + False + False + 4 + false + 10.0.0 + 2.0 + True + ..\ICSharpCode.NRefactory.snk + False + File + + + AnyCPU + False + Auto + 4194304 + 4096 + + + ..\ICSharpCode.NRefactory\bin\Debug\ + true + Full + False + False + DEBUG;TRACE;FULL_AST + + + ..\ICSharpCode.NRefactory\bin\Release\ + false + None + True + False + TRACE;FULL_AST + + + + + 3.5 + + + + 3.5 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} + ICSharpCode.NRefactory + + + + \ No newline at end of file diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs similarity index 88% rename from ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs rename to ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs index 34589023d..07c1610df 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpOutputVisitor.cs @@ -1,5 +1,21 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Diagnostics; @@ -7,7 +23,7 @@ using System.Globalization; using System.IO; using System.Linq; using System.Text; - +using System.Threading.Tasks; using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.TypeSystem; @@ -16,7 +32,7 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Outputs the AST. /// - public class OutputVisitor : IAstVisitor, IPatternAstVisitor + public class CSharpOutputVisitor : IAstVisitor { readonly IOutputFormatter formatter; readonly CSharpFormattingOptions policy; @@ -40,7 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp Division } - public OutputVisitor (TextWriter textWriter, CSharpFormattingOptions formattingPolicy) + public CSharpOutputVisitor (TextWriter textWriter, CSharpFormattingOptions formattingPolicy) { if (textWriter == null) throw new ArgumentNullException ("textWriter"); @@ -50,7 +66,7 @@ namespace ICSharpCode.NRefactory.CSharp this.policy = formattingPolicy; } - public OutputVisitor (IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy) + public CSharpOutputVisitor (IOutputFormatter formatter, CSharpFormattingOptions formattingPolicy) { if (formatter == null) throw new ArgumentNullException ("formatter"); @@ -242,7 +258,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken ("[", AstNode.Roles.LBracket); if (list.Any ()) { Space (spaceWithin); - WriteCommaSeparatedList (list.SafeCast ()); + WriteCommaSeparatedList (list); Space (spaceWithin); } WriteToken ("]", AstNode.Roles.RBracket); @@ -253,7 +269,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken ("[", AstNode.Roles.LBracket); if (list.Any ()) { Space (policy.SpacesWithinBrackets); - WriteCommaSeparatedList (list.SafeCast ()); + WriteCommaSeparatedList (list); Space (policy.SpacesWithinBrackets); } WriteToken ("]", AstNode.Roles.RBracket); @@ -398,13 +414,21 @@ namespace ICSharpCode.NRefactory.CSharp { if (unconditionalKeywords.Contains (identifier)) return true; - if (context.Ancestors.Any (a => a is QueryExpression)) { - if (queryKeywords.Contains (identifier)) + foreach (AstNode ancestor in context.Ancestors) { + if (ancestor is QueryExpression && queryKeywords.Contains (identifier)) return true; + if (identifier == "await") { + // with lambdas/anonymous methods, + if (ancestor is LambdaExpression) + return ((LambdaExpression)ancestor).IsAsync; + if (ancestor is AnonymousMethodExpression) + return ((AnonymousMethodExpression)ancestor).IsAsync; + if (ancestor is AttributedNode) + return (((AttributedNode)ancestor).Modifiers & Modifiers.Async) == Modifiers.Async; + } } return false; } - #endregion #region Write constructs @@ -421,7 +445,7 @@ namespace ICSharpCode.NRefactory.CSharp { if (typeParameters.Any ()) { WriteToken ("<", AstNode.Roles.LChevron); - WriteCommaSeparatedList (typeParameters.SafeCast ()); + WriteCommaSeparatedList (typeParameters); WriteToken (">", AstNode.Roles.RChevron); } } @@ -496,6 +520,10 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitAnonymousMethodExpression (AnonymousMethodExpression anonymousMethodExpression, object data) { StartNode (anonymousMethodExpression); + if (anonymousMethodExpression.IsAsync) { + WriteKeyword ("async", AnonymousMethodExpression.AsyncModifierRole); + Space (); + } WriteKeyword ("delegate"); if (anonymousMethodExpression.HasParameterList) { Space (policy.SpaceBeforeMethodDeclarationParentheses); @@ -509,19 +537,19 @@ namespace ICSharpCode.NRefactory.CSharp { StartNode (undocumentedExpression); switch (undocumentedExpression.UndocumentedExpressionType) { - case UndocumentedExpressionType.ArgList: - case UndocumentedExpressionType.ArgListAccess: - WriteKeyword ("__arglist"); - break; - case UndocumentedExpressionType.MakeRef: - WriteKeyword ("__makeref"); - break; - case UndocumentedExpressionType.RefType: - WriteKeyword ("__reftype"); - break; - case UndocumentedExpressionType.RefValue: - WriteKeyword ("__refvalue"); - break; + case UndocumentedExpressionType.ArgList: + case UndocumentedExpressionType.ArgListAccess: + WriteKeyword ("__arglist"); + break; + case UndocumentedExpressionType.MakeRef: + WriteKeyword ("__makeref"); + break; + case UndocumentedExpressionType.RefType: + WriteKeyword ("__reftype"); + break; + case UndocumentedExpressionType.RefValue: + WriteKeyword ("__refvalue"); + break; } if (undocumentedExpression.Arguments.Count > 0) { Space (policy.SpaceBeforeMethodCallParentheses); @@ -535,7 +563,8 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (arrayCreateExpression); WriteKeyword ("new"); arrayCreateExpression.Type.AcceptVisitor (this, data); - WriteCommaSeparatedListInBrackets (arrayCreateExpression.Arguments); + if (arrayCreateExpression.Arguments.Count > 0) + WriteCommaSeparatedListInBrackets (arrayCreateExpression.Arguments); foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) specifier.AcceptVisitor (this, data); arrayCreateExpression.Initializer.AcceptVisitor (this, data); @@ -545,25 +574,30 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitArrayInitializerExpression (ArrayInitializerExpression arrayInitializerExpression, object data) { StartNode (arrayInitializerExpression); + PrintInitializerElements(arrayInitializerExpression.Elements); + return EndNode (arrayInitializerExpression); + } + + void PrintInitializerElements(AstNodeCollection elements) + { BraceStyle style; if (policy.PlaceArrayInitializersOnNewLine == ArrayInitializerPlacement.AlwaysNewLine) style = BraceStyle.NextLine; else style = BraceStyle.EndOfLine; - OpenBrace (style); + OpenBrace(style); bool isFirst = true; - foreach (AstNode node in arrayInitializerExpression.Elements) { + foreach (AstNode node in elements) { if (isFirst) { isFirst = false; } else { - Comma (node); - NewLine (); + Comma(node, noSpaceAfterComma: true); + NewLine(); } - node.AcceptVisitor (this, null); + node.AcceptVisitor(this, null); } - NewLine (); - CloseBrace (style); - return EndNode (arrayInitializerExpression); + NewLine(); + CloseBrace(style); } public object VisitAsExpression (AsExpression asExpression, object data) @@ -601,43 +635,43 @@ namespace ICSharpCode.NRefactory.CSharp binaryOperatorExpression.Left.AcceptVisitor (this, data); bool spacePolicy; switch (binaryOperatorExpression.Operator) { - case BinaryOperatorType.BitwiseAnd: - case BinaryOperatorType.BitwiseOr: - case BinaryOperatorType.ExclusiveOr: - spacePolicy = policy.SpaceAroundBitwiseOperator; - break; - case BinaryOperatorType.ConditionalAnd: - case BinaryOperatorType.ConditionalOr: - spacePolicy = policy.SpaceAroundLogicalOperator; - break; - case BinaryOperatorType.GreaterThan: - case BinaryOperatorType.GreaterThanOrEqual: - case BinaryOperatorType.LessThanOrEqual: - case BinaryOperatorType.LessThan: - spacePolicy = policy.SpaceAroundRelationalOperator; - break; - case BinaryOperatorType.Equality: - case BinaryOperatorType.InEquality: - spacePolicy = policy.SpaceAroundEqualityOperator; - break; - case BinaryOperatorType.Add: - case BinaryOperatorType.Subtract: - spacePolicy = policy.SpaceAroundAdditiveOperator; - break; - case BinaryOperatorType.Multiply: - case BinaryOperatorType.Divide: - case BinaryOperatorType.Modulus: - spacePolicy = policy.SpaceAroundMultiplicativeOperator; - break; - case BinaryOperatorType.ShiftLeft: - case BinaryOperatorType.ShiftRight: - spacePolicy = policy.SpaceAroundShiftOperator; - break; - case BinaryOperatorType.NullCoalescing: - spacePolicy = true; - break; - default: - throw new NotSupportedException ("Invalid value for BinaryOperatorType"); + case BinaryOperatorType.BitwiseAnd: + case BinaryOperatorType.BitwiseOr: + case BinaryOperatorType.ExclusiveOr: + spacePolicy = policy.SpaceAroundBitwiseOperator; + break; + case BinaryOperatorType.ConditionalAnd: + case BinaryOperatorType.ConditionalOr: + spacePolicy = policy.SpaceAroundLogicalOperator; + break; + case BinaryOperatorType.GreaterThan: + case BinaryOperatorType.GreaterThanOrEqual: + case BinaryOperatorType.LessThanOrEqual: + case BinaryOperatorType.LessThan: + spacePolicy = policy.SpaceAroundRelationalOperator; + break; + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + spacePolicy = policy.SpaceAroundEqualityOperator; + break; + case BinaryOperatorType.Add: + case BinaryOperatorType.Subtract: + spacePolicy = policy.SpaceAroundAdditiveOperator; + break; + case BinaryOperatorType.Multiply: + case BinaryOperatorType.Divide: + case BinaryOperatorType.Modulus: + spacePolicy = policy.SpaceAroundMultiplicativeOperator; + break; + case BinaryOperatorType.ShiftLeft: + case BinaryOperatorType.ShiftRight: + spacePolicy = policy.SpaceAroundShiftOperator; + break; + case BinaryOperatorType.NullCoalescing: + spacePolicy = true; + break; + default: + throw new NotSupportedException ("Invalid value for BinaryOperatorType"); } Space (spacePolicy); WriteToken (BinaryOperatorExpression.GetOperatorSymbol (binaryOperatorExpression.Operator), BinaryOperatorExpression.OperatorRole); @@ -710,14 +744,14 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (directionExpression); switch (directionExpression.FieldDirection) { - case FieldDirection.Out: - WriteKeyword ("out"); - break; - case FieldDirection.Ref: - WriteKeyword ("ref"); - break; - default: - throw new NotSupportedException ("Invalid value for FieldDirection"); + case FieldDirection.Out: + WriteKeyword ("out"); + break; + case FieldDirection.Ref: + WriteKeyword ("ref"); + break; + default: + throw new NotSupportedException ("Invalid value for FieldDirection"); } Space (); directionExpression.Expression.AcceptVisitor (this, data); @@ -764,6 +798,10 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitLambdaExpression (LambdaExpression lambdaExpression, object data) { StartNode (lambdaExpression); + if (lambdaExpression.IsAsync) { + WriteKeyword ("async", LambdaExpression.AsyncModifierRole); + Space (); + } if (LambdaNeedsParenthesis (lambdaExpression)) { WriteCommaSeparatedListInParenthesis (lambdaExpression.Parameters, policy.SpaceWithinMethodDeclarationParentheses); } else { @@ -798,17 +836,23 @@ namespace ICSharpCode.NRefactory.CSharp { StartNode (namedArgumentExpression); WriteIdentifier (namedArgumentExpression.Identifier); - if (namedArgumentExpression.Parent is ArrayInitializerExpression) { - Space(); - WriteToken("=", NamedArgumentExpression.Roles.Assign); - } else { - WriteToken(":", NamedArgumentExpression.Roles.Colon); - } + WriteToken(":", NamedArgumentExpression.Roles.Colon); Space (); namedArgumentExpression.Expression.AcceptVisitor (this, data); 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 VisitNullReferenceExpression (NullReferenceExpression nullReferenceExpression, object data) { StartNode (nullReferenceExpression); @@ -822,8 +866,8 @@ namespace ICSharpCode.NRefactory.CSharp WriteKeyword ("new"); objectCreateExpression.Type.AcceptVisitor (this, data); bool useParenthesis = objectCreateExpression.Arguments.Any() || objectCreateExpression.Initializer.IsNull; - // also use parenthesis if there is an '(' token and this isn't an anonymous type - if (!objectCreateExpression.LParToken.IsNull && !objectCreateExpression.Type.IsNull) + // also use parenthesis if there is an '(' token + if (!objectCreateExpression.LParToken.IsNull) useParenthesis = true; if (useParenthesis) { Space (policy.SpaceBeforeMethodCallParentheses); @@ -838,17 +882,7 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (anonymousTypeCreateExpression); WriteKeyword ("new"); Space (); - LPar (); - RPar (); - Space (); - OpenBrace (policy.AnonymousMethodBraceStyle); - foreach (AstNode node in anonymousTypeCreateExpression.Initializer) { - node.AcceptVisitor (this, null); - if (node.NextSibling != null) - Comma (node); - NewLine (); - } - CloseBrace (policy.AnonymousMethodBraceStyle); + PrintInitializerElements(anonymousTypeCreateExpression.Initializers); return EndNode (anonymousTypeCreateExpression); } @@ -992,32 +1026,32 @@ namespace ICSharpCode.NRefactory.CSharp public static string ConvertChar(char ch) { switch (ch) { - case '\\': - return "\\\\"; - case '\0': - return "\\0"; - case '\a': - return "\\a"; - case '\b': - return "\\b"; - case '\f': - return "\\f"; - case '\n': - return "\\n"; - case '\r': - return "\\r"; - case '\t': - return "\\t"; - case '\v': - return "\\v"; - default: + case '\\': + return "\\\\"; + case '\0': + return "\\0"; + case '\a': + return "\\a"; + case '\b': + return "\\b"; + case '\f': + return "\\f"; + case '\n': + return "\\n"; + case '\r': + return "\\r"; + case '\t': + return "\\t"; + case '\v': + return "\\v"; + default: if (char.IsControl(ch) || char.IsSurrogate(ch) || // print all uncommon white spaces as numbers (char.IsWhiteSpace(ch) && ch != ' ')) { - return "\\u" + ((int)ch).ToString ("x4"); - } else { - return ch.ToString (); - } + return "\\u" + ((int)ch).ToString ("x4"); + } else { + return ch.ToString (); + } } } @@ -1094,8 +1128,11 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (unaryOperatorExpression); UnaryOperatorType opType = unaryOperatorExpression.Operator; string opSymbol = UnaryOperatorExpression.GetOperatorSymbol (opType); - if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) + if (opType == UnaryOperatorType.Await) { + WriteKeyword (opSymbol, UnaryOperatorExpression.OperatorRole); + } else if (!(opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement)) { WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); + } unaryOperatorExpression.Expression.AcceptVisitor (this, data); if (opType == UnaryOperatorType.PostIncrement || opType == UnaryOperatorType.PostDecrement) WriteToken (opSymbol, UnaryOperatorExpression.OperatorRole); @@ -1219,7 +1256,7 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (queryOrderClause); WriteKeyword ("orderby"); Space (); - WriteCommaSeparatedList (queryOrderClause.Orderings.SafeCast ()); + WriteCommaSeparatedList (queryOrderClause.Orderings); return EndNode (queryOrderClause); } @@ -1228,14 +1265,14 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (queryOrdering); queryOrdering.Expression.AcceptVisitor (this, data); switch (queryOrdering.Direction) { - case QueryOrderingDirection.Ascending: - Space (); - WriteKeyword ("ascending"); - break; - case QueryOrderingDirection.Descending: - Space (); - WriteKeyword ("descending"); - break; + case QueryOrderingDirection.Ascending: + Space (); + WriteKeyword ("ascending"); + break; + case QueryOrderingDirection.Descending: + Space (); + WriteKeyword ("descending"); + break; } return EndNode (queryOrdering); } @@ -1284,7 +1321,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken (":", AttributeSection.Roles.Colon); Space (); } - WriteCommaSeparatedList (attributeSection.Attributes.SafeCast ()); + WriteCommaSeparatedList (attributeSection.Attributes); WriteToken ("]", AstNode.Roles.RBracket); if (attributeSection.Parent is ParameterDeclaration || attributeSection.Parent is TypeParameterDeclaration) Space (); @@ -1332,22 +1369,22 @@ namespace ICSharpCode.NRefactory.CSharp WriteModifiers (typeDeclaration.ModifierTokens); BraceStyle braceStyle; switch (typeDeclaration.ClassType) { - case ClassType.Enum: - WriteKeyword ("enum"); - braceStyle = policy.EnumBraceStyle; - break; - case ClassType.Interface: - WriteKeyword ("interface"); - braceStyle = policy.InterfaceBraceStyle; - break; - case ClassType.Struct: - WriteKeyword ("struct"); - braceStyle = policy.StructBraceStyle; - break; - default: - WriteKeyword ("class"); - braceStyle = policy.ClassBraceStyle; - break; + case ClassType.Enum: + WriteKeyword ("enum"); + braceStyle = policy.EnumBraceStyle; + break; + case ClassType.Interface: + WriteKeyword ("interface"); + braceStyle = policy.InterfaceBraceStyle; + break; + case ClassType.Struct: + WriteKeyword ("struct"); + braceStyle = policy.StructBraceStyle; + break; + default: + WriteKeyword ("class"); + braceStyle = policy.ClassBraceStyle; + break; } WriteIdentifier (typeDeclaration.Name); WriteTypeParameters (typeDeclaration.TypeParameters); @@ -1553,7 +1590,7 @@ namespace ICSharpCode.NRefactory.CSharp LPar (); Space (policy.SpacesWithinForParentheses); - WriteCommaSeparatedList (forStatement.Initializers.SafeCast ()); + WriteCommaSeparatedList (forStatement.Initializers); Space (policy.SpaceBeforeForSemicolon); WriteToken (";", AstNode.Roles.Semicolon); Space (policy.SpaceAfterForSemicolon); @@ -1563,7 +1600,7 @@ namespace ICSharpCode.NRefactory.CSharp WriteToken (";", AstNode.Roles.Semicolon); Space (policy.SpaceAfterForSemicolon); - WriteCommaSeparatedList (forStatement.Iterators.SafeCast ()); + WriteCommaSeparatedList (forStatement.Iterators); Space (policy.SpacesWithinForParentheses); RPar (); @@ -1838,15 +1875,15 @@ namespace ICSharpCode.NRefactory.CSharp return EndNode (yieldBreakStatement); } - public object VisitYieldStatement (YieldStatement yieldStatement, object data) + public object VisitYieldReturnStatement (YieldReturnStatement yieldReturnStatement, object data) { - StartNode (yieldStatement); - WriteKeyword ("yield", YieldStatement.YieldKeywordRole); - WriteKeyword ("return", YieldStatement.ReturnKeywordRole); + StartNode (yieldReturnStatement); + WriteKeyword ("yield", YieldReturnStatement.YieldKeywordRole); + WriteKeyword ("return", YieldReturnStatement.ReturnKeywordRole); Space (); - yieldStatement.Expression.AcceptVisitor (this, data); + yieldReturnStatement.Expression.AcceptVisitor (this, data); Semicolon (); - return EndNode (yieldStatement); + return EndNode (yieldReturnStatement); } #endregion @@ -2079,18 +2116,18 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (parameterDeclaration); WriteAttributes (parameterDeclaration.Attributes); switch (parameterDeclaration.ParameterModifier) { - case ParameterModifier.Ref: - WriteKeyword ("ref", ParameterDeclaration.ModifierRole); - break; - case ParameterModifier.Out: - WriteKeyword ("out", ParameterDeclaration.ModifierRole); - break; - case ParameterModifier.Params: - WriteKeyword ("params", ParameterDeclaration.ModifierRole); - break; - case ParameterModifier.This: - WriteKeyword ("this", ParameterDeclaration.ModifierRole); - break; + case ParameterModifier.Ref: + WriteKeyword ("ref", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.Out: + WriteKeyword ("out", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.Params: + WriteKeyword ("params", ParameterDeclaration.ModifierRole); + break; + case ParameterModifier.This: + WriteKeyword ("this", ParameterDeclaration.ModifierRole); + break; } parameterDeclaration.Type.AcceptVisitor (this, data); if (!parameterDeclaration.Type.IsNull && !string.IsNullOrEmpty (parameterDeclaration.Name)) @@ -2229,16 +2266,16 @@ namespace ICSharpCode.NRefactory.CSharp StartNode (typeParameterDeclaration); WriteAttributes (typeParameterDeclaration.Attributes); switch (typeParameterDeclaration.Variance) { - case VarianceModifier.Invariant: - break; - case VarianceModifier.Covariant: - WriteKeyword ("out"); - break; - case VarianceModifier.Contravariant: - WriteKeyword ("in"); - break; - default: - throw new NotSupportedException ("Invalid value for VarianceModifier"); + case VarianceModifier.Invariant: + break; + case VarianceModifier.Covariant: + WriteKeyword ("out"); + break; + case VarianceModifier.Contravariant: + WriteKeyword ("in"); + break; + default: + throw new NotSupportedException ("Invalid value for VarianceModifier"); } WriteIdentifier (typeParameterDeclaration.Name); return EndNode (typeParameterDeclaration); @@ -2282,39 +2319,35 @@ namespace ICSharpCode.NRefactory.CSharp public object VisitPatternPlaceholder (AstNode placeholder, PatternMatching.Pattern pattern, object data) { StartNode (placeholder); - pattern.AcceptVisitor (this, data); + VisitNodeInPattern(pattern, data); return EndNode (placeholder); } - object IPatternAstVisitor.VisitAnyNode (AnyNode anyNode, object data) + void VisitAnyNode (AnyNode anyNode, object data) { if (!string.IsNullOrEmpty (anyNode.GroupName)) { WriteIdentifier (anyNode.GroupName); WriteToken (":", AstNode.Roles.Colon); } - WriteKeyword ("anyNode"); - return null; } - object IPatternAstVisitor.VisitBackreference (Backreference backreference, object data) + void VisitBackreference (Backreference backreference, object data) { WriteKeyword ("backreference"); LPar (); WriteIdentifier (backreference.ReferencedGroupName); RPar (); - return null; } - object IPatternAstVisitor.VisitIdentifierExpressionBackreference (IdentifierExpressionBackreference identifierExpressionBackreference, object data) + void VisitIdentifierExpressionBackreference (IdentifierExpressionBackreference identifierExpressionBackreference, object data) { WriteKeyword ("identifierBackreference"); LPar (); WriteIdentifier (identifierExpressionBackreference.ReferencedGroupName); RPar (); - return null; } - object IPatternAstVisitor.VisitChoice (Choice choice, object data) + void VisitChoice (Choice choice, object data) { WriteKeyword ("choice"); Space (); @@ -2329,20 +2362,18 @@ namespace ICSharpCode.NRefactory.CSharp } formatter.Unindent (); RPar (); - return null; } - object IPatternAstVisitor.VisitNamedNode (NamedNode namedNode, object data) + void VisitNamedNode (NamedNode namedNode, object data) { if (!string.IsNullOrEmpty (namedNode.GroupName)) { WriteIdentifier (namedNode.GroupName); WriteToken (":", AstNode.Roles.Colon); } VisitNodeInPattern (namedNode.ChildNode, data); - return null; } - object IPatternAstVisitor.VisitRepeat (Repeat repeat, object data) + void VisitRepeat (Repeat repeat, object data) { WriteKeyword ("repeat"); LPar (); @@ -2354,30 +2385,34 @@ namespace ICSharpCode.NRefactory.CSharp } VisitNodeInPattern (repeat.ChildNode, data); RPar (); - return null; } - object IPatternAstVisitor.VisitOptionalNode (OptionalNode optionalNode, object data) + void VisitOptionalNode (OptionalNode optionalNode, object data) { WriteKeyword ("optional"); LPar (); VisitNodeInPattern (optionalNode.ChildNode, data); RPar (); - return null; } void VisitNodeInPattern (INode childNode, object data) { - AstNode astNode = childNode as AstNode; - if (astNode != null) { - astNode.AcceptVisitor (this, data); + if (childNode is AstNode) { + ((AstNode)childNode).AcceptVisitor(this, data); + } else if (childNode is IdentifierExpressionBackreference) { + VisitIdentifierExpressionBackreference((IdentifierExpressionBackreference)childNode, data); + } else if (childNode is Choice) { + VisitChoice((Choice)childNode, data); + } else if (childNode is AnyNode) { + VisitAnyNode((AnyNode)childNode, data); + } else if (childNode is Backreference) { + VisitBackreference((Backreference)childNode, data); + } else if (childNode is NamedNode) { + VisitNamedNode((NamedNode)childNode, data); + } else if (childNode is OptionalNode) { + VisitOptionalNode((OptionalNode)childNode, data); } else { - Pattern pattern = childNode as Pattern; - if (pattern != null) { - pattern.AcceptVisitor (this, data); - } else { - throw new InvalidOperationException ("Unknown node type in pattern"); - } + throw new InvalidOperationException ("Unknown node type in pattern"); } } #endregion diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs new file mode 100644 index 000000000..eb82b1981 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/CodeDomConvertVisitor.cs @@ -0,0 +1,1304 @@ +// 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.CodeDom; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Converts from C# AST to CodeDom. + /// + /// + /// The conversion is intended for use in the SharpDevelop forms designer. + /// + public class CodeDomConvertVisitor : IAstVisitor + { + ITypeResolveContext context = MinimalResolveContext.Instance; + ResolveVisitor resolveVisitor; + bool useFullyQualifiedTypeNames; + + /// + /// Gets/Sets whether the visitor should use fully-qualified type references. + /// + public bool UseFullyQualifiedTypeNames { + get { return useFullyQualifiedTypeNames; } + set { useFullyQualifiedTypeNames = value; } + } + + /// + /// Converts a compilation unit to CodeDom. + /// + /// The input compilation unit. + /// Type resolve context, used for resolving type references. + /// CSharpParsedFile, used for resolving. + /// Converted CodeCompileUnit + /// + /// This conversion process requires a resolver because it needs to distinguish field/property/event references etc. + /// + public CodeCompileUnit Convert(CompilationUnit compilationUnit, ITypeResolveContext context, CSharpParsedFile parsedFile) + { + if (compilationUnit == null) + throw new ArgumentNullException("compilationUnit"); + if (context == null) + throw new ArgumentNullException("context"); + if (parsedFile == null) + throw new ArgumentNullException("parsedFile"); + using (var ctx = context.Synchronize()) { + ResolveVisitor resolveVisitor = new ResolveVisitor(new CSharpResolver(ctx), parsedFile); + resolveVisitor.Scan(compilationUnit); + return (CodeCompileUnit)Convert(compilationUnit, resolveVisitor); + } + } + + /// + /// Converts a C# AST node to CodeDom. + /// + /// The input node. + /// The resolve visitor. + /// The visitor must be already initialized for the file containing the given node (Scan must be called). + /// The node converted into CodeDom + /// + /// This conversion process requires a resolver because it needs to distinguish field/property/event references etc. + /// + public CodeObject Convert(AstNode node, ResolveVisitor resolveVisitor) + { + if (node == null) + throw new ArgumentNullException("node"); + if (resolveVisitor == null) + throw new ArgumentNullException("resolveVisitor"); + try { + this.resolveVisitor = resolveVisitor; + this.context = resolveVisitor.TypeResolveContext; + return node.AcceptVisitor(this); + } finally { + this.resolveVisitor = null; + this.context = MinimalResolveContext.Instance; + } + } + + ResolveResult Resolve(AstNode node) + { + if (resolveVisitor == null) + return ErrorResolveResult.UnknownError; + else + return resolveVisitor.GetResolveResult(node); + } + + CodeExpression Convert(Expression expr) + { + return (CodeExpression)expr.AcceptVisitor(this); + } + + CodeExpression[] Convert(IEnumerable expressions) + { + List result = new List(); + foreach (Expression expr in expressions) { + CodeExpression e = Convert(expr); + if (e != null) + result.Add(e); + } + return result.ToArray(); + } + + CodeTypeReference Convert(AstType type) + { + return (CodeTypeReference)type.AcceptVisitor(this); + } + + CodeTypeReference[] Convert(IEnumerable types) + { + List result = new List(); + foreach (AstType type in types) { + CodeTypeReference e = Convert(type); + if (e != null) + result.Add(e); + } + return result.ToArray(); + } + + CodeTypeReference Convert(IType type) + { + return new CodeTypeReference(type.ReflectionName); + } + + CodeStatement Convert(Statement stmt) + { + return (CodeStatement)stmt.AcceptVisitor(this); + } + + CodeStatement[] ConvertBlock(BlockStatement block) + { + List result = new List(); + foreach (Statement stmt in block.Statements) { + CodeStatement s = Convert(stmt); + if (s != null) + result.Add(s); + } + return result.ToArray(); + } + + CodeStatement[] ConvertEmbeddedStatement(Statement embeddedStatement) + { + BlockStatement block = embeddedStatement as BlockStatement; + if (block != null) { + return ConvertBlock(block); + } + CodeStatement s = Convert(embeddedStatement); + if (s != null) + return new CodeStatement[] { s }; + else + return new CodeStatement[0]; + } + + string MakeSnippet(AstNode node) + { + StringWriter w = new StringWriter(); + CSharpOutputVisitor v = new CSharpOutputVisitor(w, new CSharpFormattingOptions()); + node.AcceptVisitor(v); + return w.ToString(); + } + + /// + /// Converts an expression by storing it as C# snippet. + /// This is used for expressions that cannot be represented in CodeDom. + /// + CodeSnippetExpression MakeSnippetExpression(Expression expr) + { + return new CodeSnippetExpression(MakeSnippet(expr)); + } + + CodeSnippetStatement MakeSnippetStatement(Statement stmt) + { + return new CodeSnippetStatement(MakeSnippet(stmt)); + } + + CodeObject IAstVisitor.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) + { + return MakeSnippetExpression(anonymousMethodExpression); + } + + CodeObject IAstVisitor.VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, object data) + { + return MakeSnippetExpression(undocumentedExpression); + } + + CodeObject IAstVisitor.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) + { + CodeArrayCreateExpression ace = new CodeArrayCreateExpression(); + int dimensions = arrayCreateExpression.Arguments.Count; + int nestingDepth = arrayCreateExpression.AdditionalArraySpecifiers.Count; + if (dimensions > 0) + nestingDepth++; + if (nestingDepth > 1 || dimensions > 1) { + // CodeDom does not support jagged or multi-dimensional arrays + return MakeSnippetExpression(arrayCreateExpression); + } + if (arrayCreateExpression.Type.IsNull) { + ace.CreateType = Convert(Resolve(arrayCreateExpression).Type); + } else { + ace.CreateType = Convert(arrayCreateExpression.Type); + } + if (arrayCreateExpression.Arguments.Count == 1) { + ace.SizeExpression = Convert(arrayCreateExpression.Arguments.Single()); + } + ace.Initializers.AddRange(Convert(arrayCreateExpression.Initializer.Elements)); + return ace; + } + + CodeObject IAstVisitor.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data) + { + // Array initializers should be handled by the parent node + return MakeSnippetExpression(arrayInitializerExpression); + } + + CodeObject IAstVisitor.VisitAsExpression(AsExpression asExpression, object data) + { + return MakeSnippetExpression(asExpression); + } + + CodeObject IAstVisitor.VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) + { + // assignments are only supported as statements, not as expressions + return MakeSnippetExpression(assignmentExpression); + } + + CodeObject IAstVisitor.VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) + { + return new CodeBaseReferenceExpression(); + } + + CodeObject IAstVisitor.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + { + CodeBinaryOperatorType op; + switch (binaryOperatorExpression.Operator) { + case BinaryOperatorType.BitwiseAnd: + op = CodeBinaryOperatorType.BitwiseAnd; + break; + case BinaryOperatorType.BitwiseOr: + op = CodeBinaryOperatorType.BitwiseOr; + break; + case BinaryOperatorType.ConditionalAnd: + op = CodeBinaryOperatorType.BooleanAnd; + break; + case BinaryOperatorType.ConditionalOr: + op = CodeBinaryOperatorType.BooleanOr; + break; + case BinaryOperatorType.GreaterThan: + op = CodeBinaryOperatorType.GreaterThan; + break; + case BinaryOperatorType.GreaterThanOrEqual: + op = CodeBinaryOperatorType.GreaterThanOrEqual; + break; + case BinaryOperatorType.LessThan: + op = CodeBinaryOperatorType.LessThan; + break; + case BinaryOperatorType.LessThanOrEqual: + op = CodeBinaryOperatorType.LessThanOrEqual; + break; + case BinaryOperatorType.Add: + op = CodeBinaryOperatorType.Add; + break; + case BinaryOperatorType.Subtract: + op = CodeBinaryOperatorType.Subtract; + break; + case BinaryOperatorType.Multiply: + op = CodeBinaryOperatorType.Multiply; + break; + case BinaryOperatorType.Divide: + op = CodeBinaryOperatorType.Divide; + break; + case BinaryOperatorType.Modulus: + op = CodeBinaryOperatorType.Modulus; + break; + case BinaryOperatorType.Equality: + case BinaryOperatorType.InEquality: + BinaryOperatorResolveResult rr = Resolve(binaryOperatorExpression) as BinaryOperatorResolveResult; + if (rr != null && rr.Left.Type.IsReferenceType(context) == true) { + if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) + op = CodeBinaryOperatorType.IdentityEquality; + else + op = CodeBinaryOperatorType.IdentityInequality; + } else { + if (binaryOperatorExpression.Operator == BinaryOperatorType.Equality) { + op = CodeBinaryOperatorType.ValueEquality; + } else { + // CodeDom is retarded and does not support ValueInequality, so we'll simulate it using + // ValueEquality and Not... but CodeDom doesn't have Not either, so we use + // '(a == b) == false' + return new CodeBinaryOperatorExpression( + new CodeBinaryOperatorExpression( + Convert(binaryOperatorExpression.Left), + CodeBinaryOperatorType.ValueEquality, + Convert(binaryOperatorExpression.Right) + ), + CodeBinaryOperatorType.ValueEquality, + new CodePrimitiveExpression(false) + ); + } + } + break; + default: + // not supported: xor, shift, null coalescing + return MakeSnippetExpression(binaryOperatorExpression); + } + return new CodeBinaryOperatorExpression(Convert(binaryOperatorExpression.Left), op, Convert(binaryOperatorExpression.Right)); + } + + CodeObject IAstVisitor.VisitCastExpression(CastExpression castExpression, object data) + { + return new CodeCastExpression(Convert(castExpression.Type), Convert(castExpression.Expression)); + } + + CodeObject IAstVisitor.VisitCheckedExpression(CheckedExpression checkedExpression, object data) + { + return MakeSnippetExpression(checkedExpression); + } + + CodeObject IAstVisitor.VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) + { + return MakeSnippetExpression(conditionalExpression); + } + + CodeObject IAstVisitor.VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) + { + return new CodeDefaultValueExpression(Convert(defaultValueExpression.Type)); + } + + CodeObject IAstVisitor.VisitDirectionExpression(DirectionExpression directionExpression, object data) + { + System.CodeDom.FieldDirection direction; + if (directionExpression.FieldDirection == FieldDirection.Out) { + direction = System.CodeDom.FieldDirection.Out; + } else { + direction = System.CodeDom.FieldDirection.Ref; + } + return new CodeDirectionExpression(direction, Convert(directionExpression.Expression)); + } + + CodeObject IAstVisitor.VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + { + ResolveResult rr = Resolve(identifierExpression); + LocalResolveResult lrr = rr as LocalResolveResult; + if (lrr != null && lrr.IsParameter) { + if (lrr.Variable.Name == "value" && identifierExpression.Ancestors.Any(a => a is Accessor)) { + return new CodePropertySetValueReferenceExpression(); + } else { + return new CodeArgumentReferenceExpression(lrr.Variable.Name); + } + } + MemberResolveResult mrr = rr as MemberResolveResult; + if (mrr != null) { + return HandleMemberReference(null, identifierExpression.Identifier, identifierExpression.TypeArguments, mrr); + } + TypeResolveResult trr = rr as TypeResolveResult; + if (trr != null) { + CodeTypeReference typeRef; + if (useFullyQualifiedTypeNames) { + typeRef = Convert(trr.Type); + } else { + typeRef = new CodeTypeReference(identifierExpression.Identifier); + typeRef.TypeArguments.AddRange(Convert(identifierExpression.TypeArguments)); + } + return new CodeTypeReferenceExpression(typeRef); + } + MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult; + if (mgrr != null) { + return new CodeMethodReferenceExpression(new CodeThisReferenceExpression(), identifierExpression.Identifier, Convert(identifierExpression.TypeArguments)); + } + return new CodeVariableReferenceExpression(identifierExpression.Identifier); + } + + CodeObject IAstVisitor.VisitIndexerExpression(IndexerExpression indexerExpression, object data) + { + if (Resolve(indexerExpression) is ArrayAccessResolveResult) + return new CodeArrayIndexerExpression(Convert(indexerExpression.Target), Convert(indexerExpression.Arguments)); + else + return new CodeIndexerExpression(Convert(indexerExpression.Target), Convert(indexerExpression.Arguments)); + } + + CodeObject IAstVisitor.VisitInvocationExpression(InvocationExpression invocationExpression, object data) + { + MemberResolveResult rr = Resolve(invocationExpression) as MemberResolveResult; + CSharpInvocationResolveResult csRR = rr as CSharpInvocationResolveResult; + if (csRR != null && csRR.IsDelegateInvocation) { + return new CodeDelegateInvokeExpression(Convert(invocationExpression.Target), Convert(invocationExpression.Arguments)); + } + + Expression methodExpr = invocationExpression.Target; + while (methodExpr is ParenthesizedExpression) + methodExpr = ((ParenthesizedExpression)methodExpr).Expression; + CodeMethodReferenceExpression mr = null; + MemberReferenceExpression mre = methodExpr as MemberReferenceExpression; + if (mre != null) { + mr = new CodeMethodReferenceExpression(Convert(mre.Target), mre.MemberName, Convert(mre.TypeArguments)); + } + IdentifierExpression id = methodExpr as IdentifierExpression; + if (id != null) { + CodeExpression target; + if (rr != null && rr.Member.IsStatic) + target = new CodeTypeReferenceExpression(Convert(rr.Member.DeclaringType)); + else + target = new CodeThisReferenceExpression(); + + mr = new CodeMethodReferenceExpression(target, id.Identifier, Convert(id.TypeArguments)); + } + if (mr != null) + return new CodeMethodInvokeExpression(mr, Convert(invocationExpression.Arguments)); + else + return MakeSnippetExpression(invocationExpression); + } + + CodeObject IAstVisitor.VisitIsExpression(IsExpression isExpression, object data) + { + return MakeSnippetExpression(isExpression); + } + + CodeObject IAstVisitor.VisitLambdaExpression(LambdaExpression lambdaExpression, object data) + { + return MakeSnippetExpression(lambdaExpression); + } + + CodeObject IAstVisitor.VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) + { + CodeExpression target = Convert(memberReferenceExpression.Target); + ResolveResult rr = Resolve(memberReferenceExpression); + MemberResolveResult mrr = rr as MemberResolveResult; + if (mrr != null) { + return HandleMemberReference(target, memberReferenceExpression.MemberName, memberReferenceExpression.TypeArguments, mrr); + } else { + if (memberReferenceExpression.TypeArguments.Any() || rr is MethodGroupResolveResult) { + return new CodeMethodReferenceExpression(target, memberReferenceExpression.MemberName, Convert(memberReferenceExpression.TypeArguments)); + } else { + return new CodePropertyReferenceExpression(target, memberReferenceExpression.MemberName); + } + } + } + + CodeExpression HandleMemberReference(CodeExpression target, string identifier, AstNodeCollection typeArguments, MemberResolveResult mrr) + { + if (target == null) { + if (mrr.Member.IsStatic) + target = new CodeTypeReferenceExpression(Convert(mrr.Member.DeclaringType)); + else + target = new CodeThisReferenceExpression(); + } + if (mrr.Member is IField) { + return new CodeFieldReferenceExpression(target, identifier); + } else if (mrr.Member is IMethod) { + return new CodeMethodReferenceExpression(target, identifier, Convert(typeArguments)); + } else if (mrr.Member is IEvent) { + return new CodeEventReferenceExpression(target, identifier); + } else { + return new CodePropertyReferenceExpression(target, identifier); + } + } + + CodeObject IAstVisitor.VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) + { + return MakeSnippetExpression(namedArgumentExpression); + } + + CodeObject IAstVisitor.VisitNamedExpression(NamedExpression namedExpression, object data) + { + return MakeSnippetExpression(namedExpression); + } + + CodeObject IAstVisitor.VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data) + { + return new CodePrimitiveExpression(null); + } + + CodeObject IAstVisitor.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) + { + if (!objectCreateExpression.Initializer.IsNull) + return MakeSnippetExpression(objectCreateExpression); + return new CodeObjectCreateExpression(Convert(objectCreateExpression.Type), Convert(objectCreateExpression.Arguments)); + } + + CodeObject IAstVisitor.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) + { + return MakeSnippetExpression(anonymousTypeCreateExpression); + } + + CodeObject IAstVisitor.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) + { + // CodeDom generators will insert parentheses where necessary + return Convert(parenthesizedExpression.Expression); + } + + CodeObject IAstVisitor.VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) + { + return MakeSnippetExpression(pointerReferenceExpression); + } + + CodeObject IAstVisitor.VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + { + return new CodePrimitiveExpression(primitiveExpression.Value); + } + + CodeObject IAstVisitor.VisitSizeOfExpression(SizeOfExpression sizeOfExpression, object data) + { + return MakeSnippetExpression(sizeOfExpression); + } + + CodeObject IAstVisitor.VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data) + { + return MakeSnippetExpression(stackAllocExpression); + } + + CodeObject IAstVisitor.VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) + { + return new CodeThisReferenceExpression(); + } + + CodeObject IAstVisitor.VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) + { + return new CodeTypeOfExpression(Convert(typeOfExpression.Type)); + } + + CodeObject IAstVisitor.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) + { + return new CodeTypeReferenceExpression(Convert(typeReferenceExpression.Type)); + } + + CodeObject IAstVisitor.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + { + switch (unaryOperatorExpression.Operator) { + case UnaryOperatorType.Not: + return new CodeBinaryOperatorExpression( + Convert(unaryOperatorExpression.Expression), + CodeBinaryOperatorType.ValueEquality, + new CodePrimitiveExpression(false)); + case UnaryOperatorType.Minus: + return new CodeBinaryOperatorExpression( + new CodePrimitiveExpression(0), + CodeBinaryOperatorType.Subtract, + Convert(unaryOperatorExpression.Expression)); + case UnaryOperatorType.Plus: + return Convert(unaryOperatorExpression.Expression); + default: + return MakeSnippetExpression(unaryOperatorExpression); + } + } + + CodeObject IAstVisitor.VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data) + { + return MakeSnippetExpression(uncheckedExpression); + } + + CodeObject IAstVisitor.VisitEmptyExpression(EmptyExpression emptyExpression, object data) + { + return null; + } + + CodeObject IAstVisitor.VisitQueryExpression(QueryExpression queryExpression, object data) + { + return MakeSnippetExpression(queryExpression); + } + + CodeObject IAstVisitor.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQueryFromClause(QueryFromClause queryFromClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQueryLetClause(QueryLetClause queryLetClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQueryWhereClause(QueryWhereClause queryWhereClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQueryJoinClause(QueryJoinClause queryJoinClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQueryOrderClause(QueryOrderClause queryOrderClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQueryOrdering(QueryOrdering queryOrdering, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQuerySelectClause(QuerySelectClause querySelectClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitQueryGroupClause(QueryGroupClause queryGroupClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitAttribute(Attribute attribute, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitAttributeSection(AttributeSection attributeSection, object data) + { + throw new NotSupportedException(); + } + + CodeAttributeDeclaration Convert(Attribute attribute) + { + var attr = new CodeAttributeDeclaration(Convert(attribute.Type)); + foreach (Expression expr in attribute.Arguments) { + NamedExpression ne = expr as NamedExpression; + if (ne != null) + attr.Arguments.Add(new CodeAttributeArgument(ne.Identifier, Convert(ne.Expression))); + else + attr.Arguments.Add(new CodeAttributeArgument(Convert(expr))); + } + return attr; + } + + CodeAttributeDeclaration[] Convert(IEnumerable attributeSections) + { + List result = new List(); + foreach (AttributeSection section in attributeSections) { + foreach (Attribute attr in section.Attributes) { + CodeAttributeDeclaration attrDecl = Convert(attr); + if (attrDecl != null) + result.Add(attrDecl); + } + } + return result.ToArray(); + } + + CodeObject IAstVisitor.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) + { + CodeTypeDelegate d = new CodeTypeDelegate(delegateDeclaration.Name); + d.Attributes = ConvertMemberAttributes(delegateDeclaration.Modifiers); + d.CustomAttributes.AddRange(Convert(delegateDeclaration.Attributes)); + d.ReturnType = Convert(delegateDeclaration.ReturnType); + d.Parameters.AddRange(Convert(delegateDeclaration.Parameters)); + d.TypeParameters.AddRange(ConvertTypeParameters(delegateDeclaration.TypeParameters, delegateDeclaration.Constraints)); + return d; + } + + static MemberAttributes ConvertMemberAttributes(Modifiers modifiers) + { + MemberAttributes a = 0; + if ((modifiers & Modifiers.Abstract) != 0) + a |= MemberAttributes.Abstract; + if ((modifiers & Modifiers.Sealed) != 0) + a |= MemberAttributes.Final; + if ((modifiers & Modifiers.Static) != 0) + a |= MemberAttributes.Static; + if ((modifiers & Modifiers.Override) != 0) + a |= MemberAttributes.Override; + if ((modifiers & Modifiers.Const) != 0) + a |= MemberAttributes.Const; + if ((modifiers & Modifiers.New) != 0) + a |= MemberAttributes.New; + + if ((modifiers & Modifiers.Public) != 0) + a |= MemberAttributes.Public; + else if ((modifiers & (Modifiers.Protected | Modifiers.Internal)) == (Modifiers.Protected | Modifiers.Internal)) + a |= MemberAttributes.FamilyOrAssembly; + else if ((modifiers & Modifiers.Protected) != 0) + a |= MemberAttributes.Family; + else if ((modifiers & Modifiers.Internal) != 0) + a |= MemberAttributes.Assembly; + else if ((modifiers & Modifiers.Private) != 0) + a |= MemberAttributes.Private; + + return a; + } + + CodeObject IAstVisitor.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + { + CodeNamespace ns = new CodeNamespace(namespaceDeclaration.Name); + foreach (AstNode node in namespaceDeclaration.Members) { + CodeObject r = node.AcceptVisitor(this); + + CodeNamespaceImport import = r as CodeNamespaceImport; + if (import != null) + ns.Imports.Add(import); + + CodeTypeDeclaration typeDecl = r as CodeTypeDeclaration; + if (typeDecl != null) + ns.Types.Add(typeDecl); + } + return ns; + } + + Stack typeStack = new Stack(); + + CodeObject IAstVisitor.VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + { + bool isNestedType = typeStack.Count > 0; + CodeTypeDeclaration typeDecl = new CodeTypeDeclaration(typeDeclaration.Name); + typeDecl.Attributes = ConvertMemberAttributes(typeDeclaration.Modifiers); + typeDecl.CustomAttributes.AddRange(Convert(typeDeclaration.Attributes)); + + switch (typeDeclaration.ClassType) { + case ClassType.Struct: + typeDecl.IsStruct = true; + break; + case ClassType.Interface: + typeDecl.IsInterface = true; + break; + case ClassType.Enum: + typeDecl.IsEnum = true; + break; + default: + typeDecl.IsClass = true; + break; + } + typeDecl.IsPartial = (typeDeclaration.Modifiers & Modifiers.Partial) == Modifiers.Partial; + + typeDecl.BaseTypes.AddRange(Convert(typeDeclaration.BaseTypes)); + typeDecl.TypeParameters.AddRange(ConvertTypeParameters(typeDeclaration.TypeParameters, typeDeclaration.Constraints)); + + typeStack.Push(typeDecl); + foreach (var member in typeDeclaration.Members) { + CodeTypeMember m = member.AcceptVisitor(this) as CodeTypeMember; + if (m != null) + typeDecl.Members.Add(m); + } + typeStack.Pop(); + return typeDecl; + } + + void AddTypeMember(CodeTypeMember member) + { + if (typeStack.Count != 0) + typeStack.Peek().Members.Add(member); + } + + CodeObject IAstVisitor.VisitUsingAliasDeclaration(UsingAliasDeclaration usingAliasDeclaration, object data) + { + return new CodeSnippetTypeMember(MakeSnippet(usingAliasDeclaration)); + } + + CodeObject IAstVisitor.VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) + { + return new CodeNamespaceImport(usingDeclaration.Namespace); + } + + CodeObject IAstVisitor.VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data) + { + return new CodeSnippetTypeMember(MakeSnippet(externAliasDeclaration)); + } + + CodeObject IAstVisitor.VisitBlockStatement(BlockStatement blockStatement, object data) + { + return new CodeConditionStatement(new CodePrimitiveExpression(true), ConvertBlock(blockStatement)); + } + + CodeObject IAstVisitor.VisitBreakStatement(BreakStatement breakStatement, object data) + { + return MakeSnippetStatement(breakStatement); + } + + CodeObject IAstVisitor.VisitCheckedStatement(CheckedStatement checkedStatement, object data) + { + return MakeSnippetStatement(checkedStatement); + } + + CodeObject IAstVisitor.VisitContinueStatement(ContinueStatement continueStatement, object data) + { + return MakeSnippetStatement(continueStatement); + } + + CodeObject IAstVisitor.VisitDoWhileStatement(DoWhileStatement doWhileStatement, object data) + { + // do { } while (expr); + // + // emulate with: + // for (bool _do = true; _do; _do = expr) {} + string varName = "_do" + doWhileStatement.Ancestors.OfType().Count(); + return new CodeIterationStatement( + new CodeVariableDeclarationStatement(typeof(bool), varName, new CodePrimitiveExpression(true)), + new CodeVariableReferenceExpression(varName), + new CodeAssignStatement(new CodeVariableReferenceExpression(varName), Convert(doWhileStatement.Condition)), + ConvertEmbeddedStatement(doWhileStatement.EmbeddedStatement) + ); + } + + CodeObject IAstVisitor.VisitEmptyStatement(EmptyStatement emptyStatement, object data) + { + return null; + } + + CodeObject IAstVisitor.VisitExpressionStatement(ExpressionStatement expressionStatement, object data) + { + AssignmentExpression assignment = expressionStatement.Expression as AssignmentExpression; + if (assignment != null && assignment.Operator == AssignmentOperatorType.Assign) { + return new CodeAssignStatement(Convert(assignment.Left), Convert(assignment.Right)); + } + return new CodeExpressionStatement(Convert(expressionStatement.Expression)); + } + + CodeObject IAstVisitor.VisitFixedStatement(FixedStatement fixedStatement, object data) + { + return MakeSnippetStatement(fixedStatement); + } + + CodeObject IAstVisitor.VisitForeachStatement(ForeachStatement foreachStatement, object data) + { + return MakeSnippetStatement(foreachStatement); + } + + CodeObject IAstVisitor.VisitForStatement(ForStatement forStatement, object data) + { + if (forStatement.Initializers.Count != 1 || forStatement.Iterators.Count != 1) + return MakeSnippetStatement(forStatement); + return new CodeIterationStatement( + Convert(forStatement.Initializers.Single()), + Convert(forStatement.Condition), + Convert(forStatement.Iterators.Single()), + ConvertEmbeddedStatement(forStatement.EmbeddedStatement) + ); + } + + CodeObject IAstVisitor.VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, object data) + { + return MakeSnippetStatement(gotoCaseStatement); + } + + CodeObject IAstVisitor.VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, object data) + { + return MakeSnippetStatement(gotoDefaultStatement); + } + + CodeObject IAstVisitor.VisitGotoStatement(GotoStatement gotoStatement, object data) + { + return new CodeGotoStatement(gotoStatement.Label); + } + + CodeObject IAstVisitor.VisitIfElseStatement(IfElseStatement ifElseStatement, object data) + { + return new CodeConditionStatement( + Convert(ifElseStatement.Condition), + ConvertEmbeddedStatement(ifElseStatement.TrueStatement), + ConvertEmbeddedStatement(ifElseStatement.FalseStatement)); + } + + CodeObject IAstVisitor.VisitLabelStatement(LabelStatement labelStatement, object data) + { + return new CodeLabeledStatement(labelStatement.Label); + } + + CodeObject IAstVisitor.VisitLockStatement(LockStatement lockStatement, object data) + { + return MakeSnippetStatement(lockStatement); + } + + CodeObject IAstVisitor.VisitReturnStatement(ReturnStatement returnStatement, object data) + { + return new CodeMethodReturnStatement(Convert(returnStatement.Expression)); + } + + CodeObject IAstVisitor.VisitSwitchStatement(SwitchStatement switchStatement, object data) + { + return MakeSnippetStatement(switchStatement); + } + + CodeObject IAstVisitor.VisitSwitchSection(SwitchSection switchSection, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitCaseLabel(CaseLabel caseLabel, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitThrowStatement(ThrowStatement throwStatement, object data) + { + return new CodeThrowExceptionStatement(Convert(throwStatement.Expression)); + } + + CodeObject IAstVisitor.VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) + { + List catchClauses = new List(); + foreach (var catchClause in tryCatchStatement.CatchClauses) { + catchClauses.Add(new CodeCatchClause(catchClause.VariableName, Convert(catchClause.Type), ConvertBlock(catchClause.Body))); + } + return new CodeTryCatchFinallyStatement( + ConvertBlock(tryCatchStatement.TryBlock), + catchClauses.ToArray(), + ConvertBlock(tryCatchStatement.FinallyBlock)); + } + + CodeObject IAstVisitor.VisitCatchClause(CatchClause catchClause, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitUncheckedStatement(UncheckedStatement uncheckedStatement, object data) + { + return MakeSnippetStatement(uncheckedStatement); + } + + CodeObject IAstVisitor.VisitUnsafeStatement(UnsafeStatement unsafeStatement, object data) + { + return MakeSnippetStatement(unsafeStatement); + } + + CodeObject IAstVisitor.VisitUsingStatement(UsingStatement usingStatement, object data) + { + return MakeSnippetStatement(usingStatement); + } + + CodeObject IAstVisitor.VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data) + { + if (variableDeclarationStatement.Variables.Count != 1) + return MakeSnippetStatement(variableDeclarationStatement); + VariableInitializer vi = variableDeclarationStatement.Variables.Single(); + return new CodeVariableDeclarationStatement( + Convert(variableDeclarationStatement.Type), + vi.Name, + ConvertVariableInitializer(vi.Initializer, variableDeclarationStatement.Type)); + } + + CodeExpression ConvertVariableInitializer(Expression expr, AstType type) + { + ArrayInitializerExpression aie = expr as ArrayInitializerExpression; + if (aie != null) { + return new CodeArrayCreateExpression(Convert(type), Convert(aie.Elements)); + } else { + return Convert(expr); + } + } + + CodeObject IAstVisitor.VisitWhileStatement(WhileStatement whileStatement, object data) + { + return new CodeIterationStatement(null, Convert(whileStatement.Condition), null, ConvertEmbeddedStatement(whileStatement.EmbeddedStatement)); + } + + CodeObject IAstVisitor.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, object data) + { + return MakeSnippetStatement(yieldBreakStatement); + } + + CodeObject IAstVisitor.VisitYieldReturnStatement(YieldReturnStatement yieldStatement, object data) + { + return MakeSnippetStatement(yieldStatement); + } + + CodeObject IAstVisitor.VisitAccessor(Accessor accessor, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + CodeConstructor ctor = new CodeConstructor(); + ctor.Attributes = ConvertMemberAttributes(constructorDeclaration.Modifiers); + ctor.CustomAttributes.AddRange(Convert(constructorDeclaration.Attributes)); + if (constructorDeclaration.Initializer.ConstructorInitializerType == ConstructorInitializerType.This) { + ctor.ChainedConstructorArgs.AddRange(Convert(constructorDeclaration.Initializer.Arguments)); + } else { + ctor.BaseConstructorArgs.AddRange(Convert(constructorDeclaration.Initializer.Arguments)); + } + ctor.Parameters.AddRange(Convert(constructorDeclaration.Parameters)); + + ctor.Statements.AddRange(ConvertBlock(constructorDeclaration.Body)); + return ctor; + } + + CodeObject IAstVisitor.VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) + { + throw new NotSupportedException(); + } + + CodeObject IAstVisitor.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) + { + return new CodeSnippetTypeMember(MakeSnippet(destructorDeclaration)); + } + + CodeObject IAstVisitor.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) + { + TypeDeclaration td = enumMemberDeclaration.Parent as TypeDeclaration; + CodeMemberField f = new CodeMemberField(td != null ? td.Name : "Enum", enumMemberDeclaration.Name); + f.Attributes = MemberAttributes.Public | MemberAttributes.Static; + f.CustomAttributes.AddRange(Convert(enumMemberDeclaration.Attributes)); + f.InitExpression = Convert(enumMemberDeclaration.Initializer); + return f; + } + + CodeObject IAstVisitor.VisitEventDeclaration(EventDeclaration eventDeclaration, object data) + { + foreach (VariableInitializer vi in eventDeclaration.Variables) { + if (!vi.Initializer.IsNull) { + AddTypeMember(new CodeSnippetTypeMember(MakeSnippet(eventDeclaration))); + continue; + } + + CodeMemberEvent e = new CodeMemberEvent(); + e.Attributes = ConvertMemberAttributes(eventDeclaration.Modifiers); + e.CustomAttributes.AddRange(Convert(eventDeclaration.Attributes)); + e.Name = vi.Name; + e.Type = Convert(eventDeclaration.ReturnType); + AddTypeMember(e); + } + return null; + } + + CodeObject IAstVisitor.VisitCustomEventDeclaration(CustomEventDeclaration customEventDeclaration, object data) + { + return new CodeSnippetTypeMember(MakeSnippet(customEventDeclaration)); + } + + CodeObject IAstVisitor.VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + { + foreach (VariableInitializer vi in fieldDeclaration.Variables) { + CodeMemberField f = new CodeMemberField(Convert(fieldDeclaration.ReturnType), vi.Name); + f.Attributes = ConvertMemberAttributes(fieldDeclaration.Modifiers); + f.CustomAttributes.AddRange(Convert(fieldDeclaration.Attributes)); + f.InitExpression = ConvertVariableInitializer(vi.Initializer, fieldDeclaration.ReturnType); + AddTypeMember(f); + } + return null; + } + + CodeObject IAstVisitor.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) + { + CodeMemberProperty p = new CodeMemberProperty(); + p.Attributes = ConvertMemberAttributes(indexerDeclaration.Modifiers); + p.CustomAttributes.AddRange(Convert(indexerDeclaration.Attributes)); + p.Name = "Items"; + p.PrivateImplementationType = Convert(indexerDeclaration.PrivateImplementationType); + p.Parameters.AddRange(Convert(indexerDeclaration.Parameters)); + p.Type = Convert(indexerDeclaration.ReturnType); + + if (!indexerDeclaration.Getter.IsNull) { + p.HasGet = true; + p.GetStatements.AddRange(ConvertBlock(indexerDeclaration.Getter.Body)); + } + if (!indexerDeclaration.Setter.IsNull) { + p.HasSet = true; + p.SetStatements.AddRange(ConvertBlock(indexerDeclaration.Setter.Body)); + } + return p; + } + + CodeObject IAstVisitor.VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + { + CodeMemberMethod m = new CodeMemberMethod(); + m.Attributes = ConvertMemberAttributes(methodDeclaration.Modifiers); + + m.CustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget != "return"))); + m.ReturnTypeCustomAttributes.AddRange(Convert(methodDeclaration.Attributes.Where(a => a.AttributeTarget == "return"))); + + m.ReturnType = Convert(methodDeclaration.ReturnType); + m.PrivateImplementationType = Convert(methodDeclaration.PrivateImplementationType); + m.Name = methodDeclaration.Name; + m.TypeParameters.AddRange(ConvertTypeParameters(methodDeclaration.TypeParameters, methodDeclaration.Constraints)); + m.Parameters.AddRange(Convert(methodDeclaration.Parameters)); + + m.Statements.AddRange(ConvertBlock(methodDeclaration.Body)); + return m; + } + + CodeObject IAstVisitor.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) + { + CodeMemberMethod m = new CodeMemberMethod(); + m.Attributes = ConvertMemberAttributes(operatorDeclaration.Modifiers); + + m.CustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget != "return"))); + m.ReturnTypeCustomAttributes.AddRange(Convert(operatorDeclaration.Attributes.Where(a => a.AttributeTarget == "return"))); + + m.ReturnType = Convert(operatorDeclaration.ReturnType); + m.Name = operatorDeclaration.Name; + m.Parameters.AddRange(Convert(operatorDeclaration.Parameters)); + + m.Statements.AddRange(ConvertBlock(operatorDeclaration.Body)); + return m; + } + + CodeObject IAstVisitor.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data) + { + var p = new CodeParameterDeclarationExpression(Convert(parameterDeclaration.Type), parameterDeclaration.Name); + p.CustomAttributes.AddRange(Convert(parameterDeclaration.Attributes)); + switch (parameterDeclaration.ParameterModifier) { + case ParameterModifier.Ref: + p.Direction = System.CodeDom.FieldDirection.Ref; + break; + case ParameterModifier.Out: + p.Direction = System.CodeDom.FieldDirection.Out; + break; + } + return p; + } + + CodeParameterDeclarationExpression[] Convert(IEnumerable parameters) + { + List result = new List(); + foreach (ParameterDeclaration pd in parameters) { + CodeParameterDeclarationExpression pde = pd.AcceptVisitor(this) as CodeParameterDeclarationExpression; + if (pde != null) + result.Add(pde); + } + return result.ToArray(); + } + + CodeObject IAstVisitor.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) + { + CodeMemberProperty p = new CodeMemberProperty(); + p.Attributes = ConvertMemberAttributes(propertyDeclaration.Modifiers); + p.CustomAttributes.AddRange(Convert(propertyDeclaration.Attributes)); + p.Name = propertyDeclaration.Name; + p.PrivateImplementationType = Convert(propertyDeclaration.PrivateImplementationType); + p.Type = Convert(propertyDeclaration.ReturnType); + + if (!propertyDeclaration.Getter.IsNull) { + p.HasGet = true; + p.GetStatements.AddRange(ConvertBlock(propertyDeclaration.Getter.Body)); + } + if (!propertyDeclaration.Setter.IsNull) { + p.HasSet = true; + p.SetStatements.AddRange(ConvertBlock(propertyDeclaration.Setter.Body)); + } + return p; + } + + CodeObject IAstVisitor.VisitVariableInitializer(VariableInitializer variableInitializer, object data) + { + throw new NotSupportedException(); // should be handled by the parent node + } + + CodeObject IAstVisitor.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) + { + return new CodeSnippetTypeMember(MakeSnippet(fixedFieldDeclaration)); + } + + CodeObject IAstVisitor.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data) + { + throw new NotSupportedException(); // should be handled by the parent node + } + + CodeObject IAstVisitor.VisitCompilationUnit(CompilationUnit compilationUnit, object data) + { + CodeCompileUnit cu = new CodeCompileUnit(); + foreach (AstNode node in compilationUnit.Children) { + CodeObject o = node.AcceptVisitor(this); + + CodeNamespace ns = o as CodeNamespace; + if (ns != null) { + cu.Namespaces.Add(ns); + } + CodeTypeDeclaration td = o as CodeTypeDeclaration; + if (td != null) { + cu.Namespaces.Add(new CodeNamespace() { Types = { td } }); + } + } + return cu; + } + + CodeObject IAstVisitor.VisitSimpleType(SimpleType simpleType, object data) + { + if (useFullyQualifiedTypeNames) { + IType type = Resolve(simpleType).Type; + if (type.Kind != TypeKind.Unknown) + return Convert(type); + } + var tr = new CodeTypeReference(simpleType.Identifier); + tr.TypeArguments.AddRange(Convert(simpleType.TypeArguments)); + return tr; + } + + CodeObject IAstVisitor.VisitMemberType(MemberType memberType, object data) + { + if (memberType.IsDoubleColon && new SimpleType("global").IsMatch(memberType.Target)) { + var tr = new CodeTypeReference(memberType.MemberName, CodeTypeReferenceOptions.GlobalReference); + tr.TypeArguments.AddRange(Convert(memberType.TypeArguments)); + return tr; + } + if (useFullyQualifiedTypeNames || memberType.IsDoubleColon) { + IType type = Resolve(memberType).Type; + if (type.Kind != TypeKind.Unknown) + return Convert(type); + } + CodeTypeReference target = Convert(memberType.Target); + if (target == null) + return null; + target.BaseType = target.BaseType + "." + memberType.MemberName; + target.TypeArguments.AddRange(Convert(memberType.TypeArguments)); + return target; + } + + CodeObject IAstVisitor.VisitComposedType(ComposedType composedType, object data) + { + CodeTypeReference typeRef = Convert(composedType.BaseType); + if (typeRef == null) + return null; + if (composedType.HasNullableSpecifier) { + typeRef = new CodeTypeReference("System.Nullable") { TypeArguments = { typeRef } }; + } + foreach (ArraySpecifier s in composedType.ArraySpecifiers.Reverse()) { + typeRef = new CodeTypeReference(typeRef, s.Dimensions); + } + return typeRef; + } + + CodeObject IAstVisitor.VisitArraySpecifier(ArraySpecifier arraySpecifier, object data) + { + throw new NotSupportedException(); // handled by parent node + } + + CodeObject IAstVisitor.VisitPrimitiveType(PrimitiveType primitiveType, object data) + { + string keyword = primitiveType.Keyword; + for (TypeCode c = TypeCode.Empty; c <= TypeCode.String; c++) { + if (ReflectionHelper.GetCSharpNameByTypeCode(c) == keyword) + return new CodeTypeReference("System." + ReflectionHelper.GetShortNameByTypeCode(c)); + } + return new CodeTypeReference(primitiveType.Keyword); + } + + CodeObject IAstVisitor.VisitComment(Comment comment, object data) + { + return new CodeComment(comment.Content, comment.CommentType == CommentType.Documentation); + } + + CodeObject IAstVisitor.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) + { + throw new NotSupportedException(); // type parameters and constraints are handled together + } + + CodeObject IAstVisitor.VisitConstraint(Constraint constraint, object data) + { + throw new NotSupportedException(); + } + + CodeTypeParameter[] ConvertTypeParameters(IEnumerable typeParameters, IEnumerable constraints) + { + List result = new List(); + foreach (TypeParameterDeclaration tpDecl in typeParameters) { + CodeTypeParameter tp = new CodeTypeParameter(tpDecl.Name); + tp.CustomAttributes.AddRange(Convert(tpDecl.Attributes)); + foreach (Constraint constraint in constraints) { + if (constraint.TypeParameter == tp.Name) { + foreach (AstType baseType in constraint.BaseTypes) { + if (baseType is PrimitiveType && ((PrimitiveType)baseType).Keyword == "new") { + tp.HasConstructorConstraint = true; + } else { + CodeTypeReference tr = Convert(baseType); + if (tr != null) + tp.Constraints.Add(tr); + } + } + } + } + result.Add(tp); + } + return result.ToArray(); + } + + CodeObject IAstVisitor.VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, object data) + { + return null; + } + + CodeObject IAstVisitor.VisitIdentifier(Identifier identifier, object data) + { + return null; + } + + CodeObject IAstVisitor.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern, object data) + { + return null; + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/OutputVisitor/IOutputFormatter.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/IOutputFormatter.cs new file mode 100644 index 000000000..e1a87f694 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/IOutputFormatter.cs @@ -0,0 +1,59 @@ +// 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; + +namespace ICSharpCode.NRefactory.CSharp +{ + /// + /// Output formatter for the Output visitor. + /// + public interface IOutputFormatter + { + void StartNode(AstNode node); + void EndNode(AstNode node); + + /// + /// Writes an identifier. + /// If the identifier conflicts with a keyword, the output visitor will + /// call WriteToken("@") before calling WriteIdentifier(). + /// + void WriteIdentifier(string identifier); + + /// + /// Writes a keyword to the output. + /// + void WriteKeyword(string keyword); + + /// + /// Writes a token to the output. + /// + void WriteToken(string token); + void Space(); + + void OpenBrace(BraceStyle style); + void CloseBrace(BraceStyle style); + + void Indent(); + void Unindent(); + + void NewLine(); + + void WriteComment(CommentType commentType, string content); + } +} diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertParenthesesVisitor.cs similarity index 92% rename from ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs rename to ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertParenthesesVisitor.cs index 8e2e5981b..c3face7a8 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/InsertParenthesesVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/InsertParenthesesVisitor.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs b/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs similarity index 75% rename from ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs rename to ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs index a901cb78a..b85ab642a 100644 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/TextWriterOutputFormatter.cs +++ b/ICSharpCode.NRefactory.CSharp/OutputVisitor/TextWriterOutputFormatter.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs b/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs similarity index 81% rename from ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs rename to ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs index d9274ecee..e6eb0ed99 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/CSharpParser.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/CSharpParser.cs @@ -1,4 +1,4 @@ -// +// // CSharpParser.cs // // Author: @@ -61,9 +61,9 @@ namespace ICSharpCode.NRefactory.CSharp this.LocationsBag = locationsBag; } - public static AstLocation Convert (Mono.CSharp.Location loc) + public static TextLocation Convert (Mono.CSharp.Location loc) { - return new AstLocation (loc.Row, loc.Column); + return new TextLocation (loc.Row, loc.Column); } @@ -91,15 +91,27 @@ namespace ICSharpCode.NRefactory.CSharp { AstType result; if (memberName.Left != null) { - result = new MemberType () { MemberName = memberName.Name }; + result = new MemberType (); result.AddChild (ConvertToType (memberName.Left), MemberType.TargetRole); + var loc = LocationsBag.GetLocations (memberName.Left); + if (loc != null) + result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), MemberType.Roles.Dot); + result.AddChild (Identifier.Create (memberName.Name, Convert (memberName.Location)), MemberType.Roles.Identifier); } else { - result = new SimpleType () { Identifier = memberName.Name }; + result = new SimpleType () { IdentifierToken = Identifier.Create (memberName.Name, Convert (memberName.Location)) }; } if (memberName.TypeArguments != null && !memberName.TypeArguments.IsEmpty) { + var chevronLocs = LocationsBag.GetLocations (memberName.TypeArguments); + if (chevronLocs != null) + result.AddChild (new CSharpTokenNode (Convert (chevronLocs[chevronLocs.Count - 2]), 1), InvocationExpression.Roles.LChevron); + int i = 0; foreach (var arg in memberName.TypeArguments.Args) { result.AddChild (ConvertToType (arg), AstType.Roles.TypeArgument); + if (chevronLocs != null && i < chevronLocs.Count - 2) + result.AddChild (new CSharpTokenNode (Convert (chevronLocs [i++]), 1), InvocationExpression.Roles.Comma); } + if (chevronLocs != null) + result.AddChild (new CSharpTokenNode (Convert (chevronLocs[chevronLocs.Count - 1]), 1), InvocationExpression.Roles.RChevron); } return result; } @@ -128,6 +140,8 @@ namespace ICSharpCode.NRefactory.CSharp var memberType = new MemberType (); memberType.AddChild (ConvertToType (ma.LeftExpression), MemberType.TargetRole); + memberType.AddChild (new CSharpTokenNode (Convert (ma.DotLocation), 1), MemberType.Roles.Dot); + memberType.MemberNameToken = Identifier.Create (ma.Name, Convert (ma.Location)); AddTypeArguments (ma, memberType); @@ -148,9 +162,9 @@ namespace ICSharpCode.NRefactory.CSharp var ccSpec = cc.Spec; while (ccSpec != null) { if (ccSpec.IsNullable) { - result.HasNullableSpecifier = true; + result.AddChild (new CSharpTokenNode (Convert (ccSpec.Location), 1), ComposedType.NullableRole); } else if (ccSpec.IsPointer) { - result.PointerRank++; + result.AddChild (new CSharpTokenNode (Convert (ccSpec.Location), 1), ComposedType.PointerRole); } else { var location = LocationsBag.GetLocations (ccSpec); var spec = new ArraySpecifier () { Dimensions = ccSpec.Dimension }; @@ -190,29 +204,45 @@ namespace ICSharpCode.NRefactory.CSharp result.Type = ConvertToType (attr.TypeNameExpression); var loc = LocationsBag.GetLocations (attr); result.HasArgumentList = loc != null; + int pos = 0; if (loc != null) - result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), AttributeSection.Roles.LPar); + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.LPar); if (attr.PosArguments != null) { foreach (var arg in attr.PosArguments) { - result.AddChild ((Expression)arg.Expr.Accept (this), Attribute.Roles.Argument); + var na = arg as NamedArgument; + if (na != null) { + var newArg = new NamedArgumentExpression (); + newArg.AddChild (Identifier.Create (na.Name, Convert (na.Location)), NamedArgumentExpression.Roles.Identifier); + + var argLoc = LocationsBag.GetLocations (na); + if (argLoc != null) + newArg.AddChild (new CSharpTokenNode (Convert (argLoc [0]), 1), NamedArgumentExpression.Roles.Colon); + newArg.AddChild ((Expression)na.Expr.Accept (this), NamedExpression.Roles.Expression); + result.AddChild (newArg, Attribute.Roles.Argument); + } else { + result.AddChild ((Expression)arg.Expr.Accept (this), Attribute.Roles.Argument); + } + if (loc != null && pos + 1 < loc.Count) + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.Comma); } } 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); + if (loc != null && pos + 1 < loc.Count) + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.Comma); } } - if (loc != null) - result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), AttributeSection.Roles.RPar); + if (loc != null && pos < loc.Count) + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.RPar); yield return result; } @@ -222,19 +252,32 @@ namespace ICSharpCode.NRefactory.CSharp { if (optAttributes == null) return null; - AttributeSection result = new AttributeSection (); var loc = LocationsBag.GetLocations (optAttributes); + int pos = 0; if (loc != null) - result.AddChild (new CSharpTokenNode (Convert (loc [0]), 1), AttributeSection.Roles.LBracket); + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.LBracket); + + string target = optAttributes.First ().ExplicitTarget; + + if (!string.IsNullOrEmpty (target)) { + if (loc != null && pos < loc.Count - 1) { + result.AddChild (Identifier.Create (target, Convert (loc [pos++])), AttributeSection.Roles.Identifier); + } else { + result.AddChild (Identifier.Create (target), AttributeSection.Roles.Identifier); + } + if (loc != null && pos < loc.Count) + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.Colon); + } - result.AttributeTarget = optAttributes.First ().ExplicitTarget; foreach (var attr in GetAttributes (optAttributes)) { result.AddChild (attr, AttributeSection.AttributeRole); } - - if (loc != null) - result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), AttributeSection.Roles.RBracket); + // optional comma + if (loc != null && pos < loc.Count - 1 && !loc [pos].Equals (loc [pos + 1])) + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.Comma); + if (loc != null && pos < loc.Count) + result.AddChild (new CSharpTokenNode (Convert (loc [pos++]), 1), AttributeSection.Roles.RBracket); return result; } @@ -248,8 +291,8 @@ namespace ICSharpCode.NRefactory.CSharp nDecl.AddChild (new CSharpTokenNode (Convert (nspace.OpenBrace), 1), NamespaceDeclaration.Roles.LBrace); AddToNamespace (nDecl); namespaceStack.Push (nDecl); - } + VisitNamespaceUsings (nspace); VisitNamespaceBody (nspace); @@ -269,6 +312,13 @@ namespace ICSharpCode.NRefactory.CSharp Identifier newIdent = Identifier.Create (memberName.Name, Convert (memberName.Location)); namespaceDecl.InsertChildBefore (insertPos, newIdent, NamespaceDeclaration.Roles.Identifier); insertPos = newIdent; + + if (!memberName.DotLocation.IsNull) { + var dotToken = new CSharpTokenNode (Convert (memberName.DotLocation), 1); + namespaceDecl.InsertChildBefore (insertPos, dotToken, NamespaceDeclaration.Roles.Dot); + insertPos = dotToken; + } + memberName = memberName.Left; } } @@ -310,13 +360,17 @@ namespace ICSharpCode.NRefactory.CSharp var t = new MemberType(); t.IsDoubleColon = memberName.IsDoubleColon; t.AddChild (ConvertImport (memberName.Left), MemberType.TargetRole); + + if (!memberName.DotLocation.IsNull) + t.AddChild (new CSharpTokenNode (Convert (memberName.DotLocation), 1), MemberType.Roles.Dot); + t.AddChild (Identifier.Create (memberName.Name, Convert(memberName.Location)), MemberType.Roles.Identifier); - AddTypeArguments (t, (List)null, memberName.TypeArguments); + AddTypeArguments (t, memberName.TypeArguments); return t; } else { SimpleType t = new SimpleType(); t.AddChild (Identifier.Create (memberName.Name, Convert(memberName.Location)), SimpleType.Roles.Identifier); - AddTypeArguments (t, (List)null, memberName.TypeArguments); + AddTypeArguments (t, memberName.TypeArguments); return t; } } @@ -337,29 +391,41 @@ namespace ICSharpCode.NRefactory.CSharp var location = LocationsBag.GetMemberLocation (c); AddModifiers (newType, location); + int curLoc = 0; if (location != null) - newType.AddChild (new CSharpTokenNode (Convert (location[0]), "class".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), "class".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (Identifier.Create (c.MemberName.Name, Convert (c.MemberName.Location)), AstNode.Roles.Identifier); if (c.MemberName.TypeArguments != null) { - var typeArgLocation = LocationsBag.GetLocations (c.MemberName); - if (typeArgLocation != null) - newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); - AddTypeParameters (newType, typeArgLocation, c.MemberName.TypeArguments); - if (typeArgLocation != null) - newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); - AddConstraints (newType, c); + AddTypeParameters (newType, c.MemberName.TypeArguments); } + if (c.TypeBaseExpressions != null) { + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.Colon); + + var commaLocations = LocationsBag.GetLocations (c.TypeBaseExpressions); + int i = 0; foreach (var baseTypes in c.TypeBaseExpressions) { newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + if (commaLocations != null && i < commaLocations.Count) { + newType.AddChild (new CSharpTokenNode (Convert (commaLocations [i]), 1), TypeDeclaration.Roles.Comma); + i++; + } } } - if (location != null && location.Count > 1) - newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + + AddConstraints (newType, c); + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); base.Visit (c); - if (location != null && location.Count > 2) { - newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + if (location != null && curLoc < location.Count) { + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.RBrace); + + if (c.HasOptionalSemicolon) + newType.AddChild (new CSharpTokenNode (Convert (c.OptionalSemicolon), 1), AstNode.Roles.Semicolon); + } else { // parser error, set end node to max value. newType.AddChild (new ErrorNode (), AstNode.Roles.Error); @@ -375,31 +441,38 @@ namespace ICSharpCode.NRefactory.CSharp AddAttributeSection (newType, s); var location = LocationsBag.GetMemberLocation (s); AddModifiers (newType, location); + int curLoc = 0; if (location != null) - newType.AddChild (new CSharpTokenNode (Convert (location[0]), "struct".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), "struct".Length), TypeDeclaration.Roles.Keyword); newType.AddChild (Identifier.Create (s.MemberName.Name, Convert (s.MemberName.Location)), AstNode.Roles.Identifier); if (s.MemberName.TypeArguments != null) { - var typeArgLocation = LocationsBag.GetLocations (s.MemberName); - if (typeArgLocation != null) - newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); - AddTypeParameters (newType, typeArgLocation, s.MemberName.TypeArguments); - if (typeArgLocation != null) - newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); - AddConstraints (newType, s); + AddTypeParameters (newType, s.MemberName.TypeArguments); } if (s.TypeBaseExpressions != null) { + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.Colon); + var commaLocations = LocationsBag.GetLocations (s.TypeBaseExpressions); + int i = 0; foreach (var baseTypes in s.TypeBaseExpressions) { newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + if (commaLocations != null && i < commaLocations.Count) { + newType.AddChild (new CSharpTokenNode (Convert (commaLocations [i]), 1), TypeDeclaration.Roles.Comma); + i++; + } } } - if (location != null && location.Count > 1) - newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + AddConstraints (newType, s); + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); base.Visit (s); if (location != null && location.Count > 2) { - newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.RBrace); + if (s.HasOptionalSemicolon) + newType.AddChild (new CSharpTokenNode (Convert (s.OptionalSemicolon), 1), AstNode.Roles.Semicolon); } else { // parser error, set end node to max value. newType.AddChild (new ErrorNode (), AstNode.Roles.Error); @@ -415,29 +488,38 @@ namespace ICSharpCode.NRefactory.CSharp AddAttributeSection (newType, i); var location = LocationsBag.GetMemberLocation (i); AddModifiers (newType, location); + int curLoc = 0; if (location != null) - newType.AddChild (new CSharpTokenNode (Convert (location[0]), "interface".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), "interface".Length), TypeDeclaration.Roles.Keyword); newType.AddChild (Identifier.Create (i.MemberName.Name, Convert (i.MemberName.Location)), AstNode.Roles.Identifier); if (i.MemberName.TypeArguments != null) { - var typeArgLocation = LocationsBag.GetLocations (i.MemberName); - if (typeArgLocation != null) - newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); - AddTypeParameters (newType, typeArgLocation, i.MemberName.TypeArguments); - if (typeArgLocation != null) - newType.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); - AddConstraints (newType, i); + AddTypeParameters (newType, i.MemberName.TypeArguments); } + if (i.TypeBaseExpressions != null) { + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.Colon); + var commaLocations = LocationsBag.GetLocations (i.TypeBaseExpressions); + int j = 0; foreach (var baseTypes in i.TypeBaseExpressions) { newType.AddChild (ConvertToType (baseTypes), TypeDeclaration.BaseTypeRole); + if (commaLocations != null && j < commaLocations.Count) { + newType.AddChild (new CSharpTokenNode (Convert (commaLocations [j]), 1), TypeDeclaration.Roles.Comma); + j++; + } } } - if (location != null && location.Count > 1) - newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + + AddConstraints (newType, i); + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); base.Visit (i); if (location != null && location.Count > 2) { - newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.RBrace); + if (i.HasOptionalSemicolon) + newType.AddChild (new CSharpTokenNode (Convert (i.OptionalSemicolon), 1), AstNode.Roles.Semicolon); } else { // parser error, set end node to max value. newType.AddChild (new ErrorNode (), AstNode.Roles.Error); @@ -457,13 +539,7 @@ namespace ICSharpCode.NRefactory.CSharp newDelegate.AddChild (ConvertToType (d.ReturnType), AstNode.Roles.Type); newDelegate.AddChild (Identifier.Create (d.MemberName.Name, Convert (d.MemberName.Location)), AstNode.Roles.Identifier); if (d.MemberName.TypeArguments != null) { - var typeArgLocation = LocationsBag.GetLocations (d.MemberName); - if (typeArgLocation != null) - newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), TypeDeclaration.Roles.LChevron); - AddTypeParameters (newDelegate, typeArgLocation, d.MemberName.TypeArguments); - if (typeArgLocation != null) - newDelegate.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), TypeDeclaration.Roles.RChevron); - AddConstraints (newDelegate, d); + AddTypeParameters (newDelegate, d.MemberName.TypeArguments); } if (location != null) newDelegate.AddChild (new CSharpTokenNode (Convert (location[1]), 1), DelegateDeclaration.Roles.LPar); @@ -471,6 +547,9 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) { newDelegate.AddChild (new CSharpTokenNode (Convert (location[2]), 1), DelegateDeclaration.Roles.RPar); + } + AddConstraints (newDelegate, d); + if (location != null) { newDelegate.AddChild (new CSharpTokenNode (Convert (location[3]), 1), DelegateDeclaration.Roles.Semicolon); } AddType (newDelegate); @@ -502,19 +581,33 @@ namespace ICSharpCode.NRefactory.CSharp var location = LocationsBag.GetMemberLocation (e); AddModifiers (newType, location); + int curLoc = 0; if (location != null) - newType.AddChild (new CSharpTokenNode (Convert (location [0]), "enum".Length), TypeDeclaration.Roles.Keyword); + newType.AddChild (new CSharpTokenNode (Convert (location [curLoc++]), "enum".Length), TypeDeclaration.Roles.Keyword); newType.AddChild (Identifier.Create (e.MemberName.Name, Convert (e.MemberName.Location)), AstNode.Roles.Identifier); - if (e.BaseTypeExpression != null) + if (e.BaseTypeExpression != null) { + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.Colon); newType.AddChild (ConvertToType (e.BaseTypeExpression), TypeDeclaration.BaseTypeRole); + } - if (location != null && location.Count > 1) - newType.AddChild (new CSharpTokenNode (Convert (location[1]), 1), AstNode.Roles.LBrace); + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.LBrace); typeStack.Push (newType); - base.Visit (e); + + foreach (EnumMember member in e.OrderedAllMembers) { + Visit (member); + if (location != null && curLoc < location.Count - 1) //last one is closing brace + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.Comma); + } + if (location != null && location.Count > 2) { - newType.AddChild (new CSharpTokenNode (Convert (location[2]), 1), AstNode.Roles.RBrace); + if (location != null && curLoc < location.Count) + newType.AddChild (new CSharpTokenNode (Convert (location[curLoc++]), 1), AstNode.Roles.RBrace); + + if (e.HasOptionalSemicolon) + newType.AddChild (new CSharpTokenNode (Convert (e.OptionalSemicolon), 1), AstNode.Roles.Semicolon); } else { // parser error, set end node to max value. newType.AddChild (new ErrorNode (), AstNode.Roles.Error); @@ -530,6 +623,7 @@ namespace ICSharpCode.NRefactory.CSharp newField.AddChild (Identifier.Create (em.Name, Convert (em.Location)), AstNode.Roles.Identifier); if (em.Initializer != null) { + newField.AddChild (new CSharpTokenNode (Convert (em.Initializer.Location), 1), EnumMemberDeclaration.Roles.Assign); newField.AddChild ((Expression)em.Initializer.Accept (this), EnumMemberDeclaration.InitializerRole); } @@ -611,12 +705,13 @@ namespace ICSharpCode.NRefactory.CSharp foreach (var decl in f.Declarators) { var declLoc = LocationsBag.GetLocations (decl); if (declLoc != null) - newField.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + newField.AddChild (new CSharpTokenNode (Convert (declLoc [0]), 1), FieldDeclaration.Roles.Comma); variable = new VariableInitializer (); variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), VariableInitializer.Roles.Identifier); if (decl.Initializer != null) { - variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + if (declLoc != null) + variable.AddChild (new CSharpTokenNode (Convert (declLoc [1]), 1), FieldDeclaration.Roles.Assign); variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); } newField.AddChild (variable, FieldDeclaration.Roles.Variable); @@ -679,19 +774,22 @@ namespace ICSharpCode.NRefactory.CSharp AddAttributeSection (newOperator, o); AddModifiers (newOperator, location); - newOperator.AddChild (ConvertToType (o.TypeName), AstNode.Roles.Type); if (o.OperatorType == Operator.OpType.Implicit) { if (location != null) { newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "implicit".Length), OperatorDeclaration.OperatorTypeRole); newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); } + newOperator.AddChild (ConvertToType (o.TypeName), AstNode.Roles.Type); } else if (o.OperatorType == Operator.OpType.Explicit) { if (location != null) { newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "explicit".Length), OperatorDeclaration.OperatorTypeRole); newOperator.AddChild (new CSharpTokenNode (Convert (location[1]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); } + newOperator.AddChild (ConvertToType (o.TypeName), AstNode.Roles.Type); } else { + newOperator.AddChild (ConvertToType (o.TypeName), AstNode.Roles.Type); + if (location != null) newOperator.AddChild (new CSharpTokenNode (Convert (location[0]), "operator".Length), OperatorDeclaration.OperatorKeywordRole); @@ -705,9 +803,12 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) newOperator.AddChild (new CSharpTokenNode (Convert (location[3]), 1), OperatorDeclaration.Roles.RPar); - if (o.Block != null) + if (o.Block != null) { newOperator.AddChild ((BlockStatement)o.Block.Accept (this), OperatorDeclaration.Roles.Body); - + } else { + if (location != null && location.Count >= 5) + newOperator.AddChild (new CSharpTokenNode (Convert (location[4]), 1), MethodDeclaration.Roles.Semicolon); + } typeStack.Peek ().AddChild (newOperator, TypeDeclaration.MemberRole); } @@ -715,7 +816,14 @@ namespace ICSharpCode.NRefactory.CSharp { if (a.OptAttributes == null) return; - foreach (var attr in a.OptAttributes.Sections) { + AddAttributeSection (parent, a.OptAttributes); + } + + public void AddAttributeSection (AstNode parent, Attributes attrs) + { + if (attrs == null) + return; + foreach (var attr in attrs.Sections) { parent.AddChild (ConvertAttributeSection (attr), AttributedNode.AttributeRole); } } @@ -726,13 +834,18 @@ namespace ICSharpCode.NRefactory.CSharp AddAttributeSection (newIndexer, indexer); var location = LocationsBag.GetMemberLocation (indexer); AddModifiers (newIndexer, location); - - if (indexer.MemberName.Left != null) - newIndexer.AddChild (ConvertToType (indexer.MemberName.Left), IndexerDeclaration.PrivateImplementationTypeRole); newIndexer.AddChild (ConvertToType (indexer.TypeName), IndexerDeclaration.Roles.Type); + var name = indexer.MemberName; + if (name.Left != null) { + newIndexer.AddChild (ConvertToType (name.Left), IndexerDeclaration.PrivateImplementationTypeRole); + var privateImplTypeLoc = LocationsBag.GetLocations (name.Left); + if (privateImplTypeLoc != null) + newIndexer.AddChild (new CSharpTokenNode (Convert (privateImplTypeLoc[0]), 1), MethodDeclaration.Roles.Dot); + } + newIndexer.AddChild (Identifier.Create ("this", Convert (name.Location)), IndexerDeclaration.Roles.Identifier); if (location != null) - newIndexer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IndexerDeclaration.Roles.LBracket); + newIndexer.AddChild (new CSharpTokenNode (Convert (location [0]), 1), IndexerDeclaration.Roles.LBracket); AddParameter (newIndexer, indexer.ParameterInfo); if (location != null) newIndexer.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IndexerDeclaration.Roles.RBracket); @@ -789,19 +902,16 @@ namespace ICSharpCode.NRefactory.CSharp AddModifiers (newMethod, location); newMethod.AddChild (ConvertToType (m.TypeName), AstNode.Roles.Type); - if (m.MethodName.Left != null) + if (m.MethodName.Left != null) { newMethod.AddChild (ConvertToType (m.MethodName.Left), MethodDeclaration.PrivateImplementationTypeRole); - + var privateImplTypeLoc = LocationsBag.GetLocations (m.MethodName.Left); + if (privateImplTypeLoc != null) + newMethod.AddChild (new CSharpTokenNode (Convert (privateImplTypeLoc[0]), 1), MethodDeclaration.Roles.Dot); + } newMethod.AddChild (Identifier.Create (m.MethodName.Name, Convert (m.Location)), AstNode.Roles.Identifier); if (m.MemberName.TypeArguments != null) { - var typeArgLocation = LocationsBag.GetLocations (m.MemberName); - if (typeArgLocation != null) - newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[0]), 1), MemberReferenceExpression.Roles.LChevron); - AddTypeParameters (newMethod, typeArgLocation, m.MemberName.TypeArguments); - if (typeArgLocation != null) - newMethod.AddChild (new CSharpTokenNode (Convert (typeArgLocation[1]), 1), MemberReferenceExpression.Roles.RChevron); - AddConstraints (newMethod, m.GenericMethod); + AddTypeParameters (newMethod, m.MemberName.TypeArguments); } if (location != null) @@ -810,6 +920,9 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) newMethod.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RPar); + + AddConstraints (newMethod, m.GenericMethod); + if (m.Block != null) { var bodyBlock = (BlockStatement)m.Block.Accept (this); // if (m.Block is ToplevelBlock) { @@ -817,9 +930,13 @@ namespace ICSharpCode.NRefactory.CSharp // } else { newMethod.AddChild (bodyBlock, MethodDeclaration.Roles.Body); // } - } else if (location != null && location.Count < 3) { - // parser error, set end node to max value. - newMethod.AddChild (new ErrorNode (), AstNode.Roles.Error); + } else if (location != null) { + if (location.Count < 3) { + // parser error, set end node to max value. + newMethod.AddChild (new ErrorNode (), AstNode.Roles.Error); + } else { + newMethod.AddChild (new CSharpTokenNode (Convert (location[2]), 1), MethodDeclaration.Roles.Semicolon); + } } typeStack.Peek ().AddChild (newMethod, TypeDeclaration.MemberRole); } @@ -882,16 +999,21 @@ namespace ICSharpCode.NRefactory.CSharp var location = LocationsBag.GetMemberLocation (p); AddModifiers (newProperty, location); newProperty.AddChild (ConvertToType (p.TypeName), AstNode.Roles.Type); - if (p.MemberName.Left != null) + if (p.MemberName.Left != null) { newProperty.AddChild (ConvertToType (p.MemberName.Left), PropertyDeclaration.PrivateImplementationTypeRole); + var privateImplTypeLoc = LocationsBag.GetLocations (p.MemberName.Left); + if (privateImplTypeLoc != null) + newProperty.AddChild (new CSharpTokenNode (Convert (privateImplTypeLoc[0]), 1), MethodDeclaration.Roles.Dot); + } newProperty.AddChild (Identifier.Create (p.MemberName.Name, Convert (p.Location)), PropertyDeclaration.Roles.Identifier); if (location != null) newProperty.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MethodDeclaration.Roles.LBrace); + Accessor getAccessor = null; if (p.Get != null) { - Accessor getAccessor = new Accessor (); + getAccessor = new Accessor (); AddAttributeSection (getAccessor, p.Get); var getLocation = LocationsBag.GetMemberLocation (p.Get); AddModifiers (getAccessor, getLocation); @@ -901,13 +1023,13 @@ namespace ICSharpCode.NRefactory.CSharp getAccessor.AddChild ((BlockStatement)p.Get.Block.Accept (this), MethodDeclaration.Roles.Body); } else { if (getLocation != null && getLocation.Count > 0) - newProperty.AddChild (new CSharpTokenNode (Convert (getLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + getAccessor.AddChild (new CSharpTokenNode (Convert (getLocation[0]), 1), MethodDeclaration.Roles.Semicolon); } - newProperty.AddChild (getAccessor, PropertyDeclaration.GetterRole); } + Accessor setAccessor = null; if (p.Set != null) { - Accessor setAccessor = new Accessor (); + setAccessor = new Accessor (); AddAttributeSection (setAccessor, p.Set); var setLocation = LocationsBag.GetMemberLocation (p.Set); AddModifiers (setAccessor, setLocation); @@ -917,10 +1039,24 @@ namespace ICSharpCode.NRefactory.CSharp setAccessor.AddChild ((BlockStatement)p.Set.Block.Accept (this), MethodDeclaration.Roles.Body); } else { if (setLocation != null && setLocation.Count > 0) - newProperty.AddChild (new CSharpTokenNode (Convert (setLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + setAccessor.AddChild (new CSharpTokenNode (Convert (setLocation[0]), 1), MethodDeclaration.Roles.Semicolon); + } + } + if (getAccessor != null && setAccessor != null) { + if (getAccessor.StartLocation < setAccessor.StartLocation) { + newProperty.AddChild (getAccessor, PropertyDeclaration.GetterRole); + newProperty.AddChild (setAccessor, PropertyDeclaration.SetterRole); + } else { + newProperty.AddChild (setAccessor, PropertyDeclaration.SetterRole); + newProperty.AddChild (getAccessor, PropertyDeclaration.GetterRole); } - newProperty.AddChild (setAccessor, PropertyDeclaration.SetterRole); + } else { + if (getAccessor != null) + newProperty.AddChild (getAccessor, PropertyDeclaration.GetterRole); + if (setAccessor != null) + newProperty.AddChild (setAccessor, PropertyDeclaration.SetterRole); } + if (location != null && location.Count > 1) { newProperty.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MethodDeclaration.Roles.RBrace); } else { @@ -951,12 +1087,14 @@ namespace ICSharpCode.NRefactory.CSharp var initializerLocation = LocationsBag.GetLocations (c.Initializer); if (initializerLocation != null) - newConstructor.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.Colon); + newConstructor.AddChild (new CSharpTokenNode (Convert (initializerLocation[0]), 1), ConstructorDeclaration.Roles.Colon); + // this and base has the same length + initializer.AddChild (new CSharpTokenNode (Convert (c.Initializer.Location), "this".Length), ConstructorDeclaration.Roles.Keyword); if (initializerLocation != null) - initializer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.LPar); + initializer.AddChild (new CSharpTokenNode (Convert (initializerLocation[1]), 1), ConstructorDeclaration.Roles.LPar); AddArguments (initializer, LocationsBag.GetLocations (c.Initializer.Arguments), c.Initializer.Arguments); if (initializerLocation != null) - initializer.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ConstructorDeclaration.Roles.RPar); + initializer.AddChild (new CSharpTokenNode (Convert (initializerLocation[2]), 1), ConstructorDeclaration.Roles.RPar); newConstructor.AddChild (initializer, ConstructorDeclaration.InitializerRole); } @@ -1011,13 +1149,14 @@ namespace ICSharpCode.NRefactory.CSharp foreach (var decl in e.Declarators) { var declLoc = LocationsBag.GetLocations (decl); if (declLoc != null) - newEvent.AddChild (new CSharpTokenNode (Convert (declLoc[0]), 1), FieldDeclaration.Roles.Comma); + newEvent.AddChild (new CSharpTokenNode (Convert (declLoc [0]), 1), FieldDeclaration.Roles.Comma); variable = new VariableInitializer (); variable.AddChild (Identifier.Create (decl.Name.Value, Convert (decl.Name.Location)), VariableInitializer.Roles.Identifier); if (decl.Initializer != null) { - variable.AddChild (new CSharpTokenNode (Convert (decl.Initializer.Location), 1), FieldDeclaration.Roles.Assign); + if (declLoc != null) + variable.AddChild (new CSharpTokenNode (Convert (declLoc [1]), 1), FieldDeclaration.Roles.Assign); variable.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); } newEvent.AddChild (variable, FieldDeclaration.Roles.Variable); @@ -1040,8 +1179,12 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) newEvent.AddChild (new CSharpTokenNode (Convert (location[0]), "event".Length), CustomEventDeclaration.Roles.Keyword); newEvent.AddChild (ConvertToType (ep.TypeName), CustomEventDeclaration.Roles.Type); - if (ep.MemberName.Left != null) + if (ep.MemberName.Left != null) { newEvent.AddChild (ConvertToType (ep.MemberName.Left), CustomEventDeclaration.PrivateImplementationTypeRole); + var privateImplTypeLoc = LocationsBag.GetLocations (ep.MemberName.Left); + if (privateImplTypeLoc != null) + newEvent.AddChild (new CSharpTokenNode (Convert (privateImplTypeLoc[0]), 1), MethodDeclaration.Roles.Dot); + } newEvent.AddChild (Identifier.Create (ep.MemberName.Name, Convert (ep.Location)), CustomEventDeclaration.Roles.Identifier); @@ -1114,7 +1257,7 @@ namespace ICSharpCode.NRefactory.CSharp init.AddChild (Identifier.Create (decl.Variable.Name, Convert (decl.Variable.Location)), VariableInitializer.Roles.Identifier); if (decl.Initializer != null) { if (loc != null && loc.Count > 1) - result.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), VariableInitializer.Roles.Assign); + init.AddChild (new CSharpTokenNode (Convert (loc [1]), 1), VariableInitializer.Roles.Assign); init.AddChild ((Expression)decl.Initializer.Accept (this), VariableInitializer.Roles.Expression); } else { } @@ -1180,6 +1323,11 @@ namespace ICSharpCode.NRefactory.CSharp return result; } + public override object Visit (Mono.CSharp.EmptyExpression emptyExpression) + { + return new ICSharpCode.NRefactory.CSharp.EmptyExpression (Convert (emptyExpression.Location)); + } + public override object Visit (EmptyExpressionStatement emptyExpressionStatement) { return new EmptyExpression (Convert (emptyExpressionStatement.Location)); @@ -1323,9 +1471,10 @@ namespace ICSharpCode.NRefactory.CSharp var result = new GotoStatement (); var location = LocationsBag.GetLocations (gotoStatement); result.AddChild (new CSharpTokenNode (Convert (gotoStatement.loc), "goto".Length), GotoStatement.Roles.Keyword); - result.AddChild (Identifier.Create (gotoStatement.Target, Convert (gotoStatement.loc)), GotoStatement.Roles.Identifier); + var loc = location != null ? Convert (location [0]) : TextLocation.Empty; + result.AddChild (Identifier.Create (gotoStatement.Target, loc), GotoStatement.Roles.Identifier); if (location != null) - result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), GotoStatement.Roles.Semicolon); + result.AddChild (new CSharpTokenNode (Convert (location [1]), 1), GotoStatement.Roles.Semicolon); return result; } @@ -1334,6 +1483,9 @@ namespace ICSharpCode.NRefactory.CSharp { var result = new LabelStatement (); result.AddChild (Identifier.Create (labeledStatement.Name, Convert (labeledStatement.loc)), LabelStatement.Roles.Identifier); + var location = LocationsBag.GetLocations (labeledStatement); + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location [0]), 1), LabelStatement.Roles.Colon); return result; } @@ -1418,7 +1570,7 @@ namespace ICSharpCode.NRefactory.CSharp var loc = LocationsBag.GetLocations (u.Variables); if (loc != null) - initializer.AddChild (new CSharpTokenNode (Convert (loc[1]), 1), VariableInitializer.Roles.Assign); + initializer.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), VariableInitializer.Roles.Assign); if (u.Variables.Initializer != null) initializer.Initializer = u.Variables.Initializer.Accept (this) as Expression; @@ -1489,10 +1641,16 @@ namespace ICSharpCode.NRefactory.CSharp var newSection = new SwitchSection (); foreach (var caseLabel in section.Labels) { var newLabel = new CaseLabel (); - newLabel.AddChild (new CSharpTokenNode (Convert (caseLabel.Location), "case".Length), SwitchStatement.Roles.Keyword); - if (caseLabel.Label != null) + if (caseLabel.Label != null) { + newLabel.AddChild (new CSharpTokenNode (Convert (caseLabel.Location), "case".Length), SwitchStatement.Roles.Keyword); newLabel.AddChild ((Expression)caseLabel.Label.Accept (this), SwitchStatement.Roles.Expression); - + var colonLocation = LocationsBag.GetLocations (caseLabel); + if (colonLocation != null) + newLabel.AddChild (new CSharpTokenNode (Convert (colonLocation [0]), 1), SwitchStatement.Roles.Colon); + } else { + newLabel.AddChild (new CSharpTokenNode (Convert (caseLabel.Location), "default".Length), SwitchStatement.Roles.Keyword); + newLabel.AddChild (new CSharpTokenNode (new TextLocation (caseLabel.Location.Row, caseLabel.Location.Column + "default".Length), 1), SwitchStatement.Roles.Colon); + } newSection.AddChild (newLabel, SwitchSection.CaseLabelRole); } @@ -1715,16 +1873,16 @@ namespace ICSharpCode.NRefactory.CSharp public override object Visit (Yield yieldStatement) { - var result = new YieldStatement (); + var result = new YieldReturnStatement (); var location = LocationsBag.GetLocations (yieldStatement); - result.AddChild (new CSharpTokenNode (Convert (yieldStatement.loc), "yield".Length), YieldStatement.YieldKeywordRole); + result.AddChild (new CSharpTokenNode (Convert (yieldStatement.loc), "yield".Length), YieldReturnStatement.YieldKeywordRole); if (location != null) - result.AddChild (new CSharpTokenNode (Convert (location[0]), "return".Length), YieldStatement.ReturnKeywordRole); + result.AddChild (new CSharpTokenNode (Convert (location[0]), "return".Length), YieldReturnStatement.ReturnKeywordRole); if (yieldStatement.Expr != null) - result.AddChild ((Expression)yieldStatement.Expr.Accept (this), YieldStatement.Roles.Expression); + result.AddChild ((Expression)yieldStatement.Expr.Accept (this), YieldReturnStatement.Roles.Expression); if (location != null) - result.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), YieldStatement.Roles.Semicolon); + result.AddChild (new CSharpTokenNode (Convert (location[1]), ";".Length), YieldReturnStatement.Roles.Semicolon); return result; } @@ -1779,17 +1937,15 @@ namespace ICSharpCode.NRefactory.CSharp var leftExpr = memberAccess.LeftExpression.Accept (this); result.AddChild ((Expression)leftExpr, MemberReferenceExpression.Roles.TargetExpression); } + if (!memberAccess.DotLocation.IsNull) { + result.AddChild (new CSharpTokenNode (Convert (memberAccess.DotLocation), 1), MemberReferenceExpression.Roles.Dot); + } } - + result.AddChild (Identifier.Create (memberAccess.Name, Convert (memberAccess.Location)), MemberReferenceExpression.Roles.Identifier); if (memberAccess.TypeArguments != null) { - var location = LocationsBag.GetLocations (memberAccess); - if (location != null) - result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), MemberReferenceExpression.Roles.LChevron); - AddTypeArguments (result, location, memberAccess.TypeArguments); - if (location != null && location.Count > 1) - result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), MemberReferenceExpression.Roles.RChevron); + AddTypeArguments (result, memberAccess.TypeArguments); } return result; } @@ -1800,7 +1956,7 @@ namespace ICSharpCode.NRefactory.CSharp result.Target = new SimpleType (qualifiedAliasMember.alias, Convert (qualifiedAliasMember.Location)); result.IsDoubleColon = true; var location = LocationsBag.GetLocations (qualifiedAliasMember); - result.AddChild (Identifier.Create (qualifiedAliasMember.Name, location != null ? Convert (location[0]) : AstLocation.Empty), MemberReferenceExpression.Roles.Identifier); + result.AddChild (Identifier.Create (qualifiedAliasMember.Name, location != null ? Convert (location[0]) : TextLocation.Empty), MemberReferenceExpression.Roles.Identifier); return new TypeReferenceExpression () { Type = result }; } @@ -1814,7 +1970,10 @@ namespace ICSharpCode.NRefactory.CSharp } else { literalValue = constant.GetValueAsLiteral (); } - var result = new PrimitiveExpression (constant.GetValue (), Convert (constant.Location), literalValue); + object val = constant.GetValue (); + if (val is bool) + literalValue = (bool)val ? "true" : "false"; + var result = new PrimitiveExpression (val, Convert (constant.Location), literalValue); return result; } @@ -1823,12 +1982,7 @@ namespace ICSharpCode.NRefactory.CSharp var result = new IdentifierExpression (); result.AddChild (Identifier.Create (simpleName.Name, Convert (simpleName.Location)), IdentifierExpression.Roles.Identifier); if (simpleName.TypeArguments != null) { - var location = LocationsBag.GetLocations (simpleName); - if (location != null) - result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), IdentifierExpression.Roles.LChevron); - AddTypeArguments (result, location, simpleName.TypeArguments); - if (location != null && location.Count > 1) - result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), IdentifierExpression.Roles.RChevron); + AddTypeArguments (result, simpleName.TypeArguments); } return result; } @@ -2097,11 +2251,8 @@ namespace ICSharpCode.NRefactory.CSharp var paramLocation = LocationsBag.GetLocations (parameters); for (int i = 0; i < parameters.Count; i++) { - if (paramLocation != null && i > 0 && i - 1 < paramLocation.Count) - parent.AddChild (new CSharpTokenNode (Convert (paramLocation [i - 1]), 1), ParameterDeclaration.Roles.Comma); var p = (Parameter)parameters.FixedParameters [i]; var location = LocationsBag.GetLocations (p); - ParameterDeclaration parameterDeclarationExpression = new ParameterDeclaration (); AddAttributeSection (parameterDeclarationExpression, p); switch (p.ModFlags) { @@ -2123,8 +2274,9 @@ namespace ICSharpCode.NRefactory.CSharp default: if (p.HasExtensionMethodModifier) { parameterDeclarationExpression.ParameterModifier = ParameterModifier.This; - if (location != null) + if (location != null) { parameterDeclarationExpression.AddChild (new CSharpTokenNode (Convert (location [0]), "this".Length), ParameterDeclaration.Roles.Keyword); + } } break; } @@ -2138,54 +2290,83 @@ namespace ICSharpCode.NRefactory.CSharp parameterDeclarationExpression.AddChild ((Expression)p.DefaultValue.Accept (this), ParameterDeclaration.Roles.Expression); } parent.AddChild (parameterDeclarationExpression, InvocationExpression.Roles.Parameter); + if (paramLocation != null && i < paramLocation.Count) { + parent.AddChild (new CSharpTokenNode (Convert (paramLocation [i]), 1), ParameterDeclaration.Roles.Comma); + } } } - void AddTypeParameters (AstNode parent, List location, Mono.CSharp.TypeArguments typeArguments) + void AddTypeParameters (AstNode parent, Mono.CSharp.TypeArguments typeArguments) { if (typeArguments == null || typeArguments.IsEmpty) return; + var chevronLocs = LocationsBag.GetLocations (typeArguments); + if (chevronLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (chevronLocs[chevronLocs.Count - 2]), 1), InvocationExpression.Roles.LChevron); for (int i = 0; i < typeArguments.Count; i++) { - if (location != null && i > 0 && i - 1 < location.Count) - parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); + if (chevronLocs != null && i > 0 && i - 1 < chevronLocs.Count) + parent.AddChild (new CSharpTokenNode (Convert (chevronLocs[i - 1]), 1), InvocationExpression.Roles.Comma); var arg = (TypeParameterName)typeArguments.Args[i]; if (arg == null) continue; TypeParameterDeclaration tp = new TypeParameterDeclaration(); - // TODO: attributes -// if (arg.Variance != Variance.None) -// throw new NotImplementedException(); // TODO: variance + + List varianceLocation; + switch (arg.Variance) { + case Variance.Contravariant: + tp.Variance = VarianceModifier.Contravariant; + varianceLocation = LocationsBag.GetLocations (arg); + if (varianceLocation != null) + tp.AddChild (new CSharpTokenNode (Convert (varianceLocation[0]), "out".Length), TypeParameterDeclaration.VarianceRole); + break; + case Variance.Covariant: + tp.Variance = VarianceModifier.Covariant; + varianceLocation = LocationsBag.GetLocations (arg); + if (varianceLocation != null) + tp.AddChild (new CSharpTokenNode (Convert (varianceLocation[0]), "out".Length), TypeParameterDeclaration.VarianceRole); + break; + default: + tp.Variance = VarianceModifier.Invariant; + break; + + } + + AddAttributeSection (tp, arg.OptAttributes); + + switch (arg.Variance) { + case Variance.Covariant: + tp.Variance = VarianceModifier.Covariant; + break; + case Variance.Contravariant: + tp.Variance = VarianceModifier.Contravariant; + break; + } tp.AddChild (Identifier.Create (arg.Name, Convert (arg.Location)), InvocationExpression.Roles.Identifier); parent.AddChild (tp, InvocationExpression.Roles.TypeParameter); } + if (chevronLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (chevronLocs[chevronLocs.Count - 1]), 1), InvocationExpression.Roles.RChevron); } - void AddTypeArguments (AstNode parent, LocationsBag.MemberLocations location, Mono.CSharp.TypeArguments typeArguments) - { - if (typeArguments == null || typeArguments.IsEmpty) - return; - for (int i = 0; i < typeArguments.Count; i++) { - if (location != null && i > 0 && i - 1 < location.Count) - parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); - var arg = typeArguments.Args[i]; - if (arg == null) - continue; - parent.AddChild (ConvertToType (arg), InvocationExpression.Roles.TypeArgument); - } - } - - void AddTypeArguments (AstNode parent, List location, Mono.CSharp.TypeArguments typeArguments) + void AddTypeArguments (AstNode parent, Mono.CSharp.TypeArguments typeArguments) { if (typeArguments == null || typeArguments.IsEmpty) return; + var chevronLocs = LocationsBag.GetLocations (typeArguments); + if (chevronLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (chevronLocs[chevronLocs.Count - 2]), 1), InvocationExpression.Roles.LChevron); + for (int i = 0; i < typeArguments.Count; i++) { - if (location != null && i > 0 && i - 1 < location.Count) - parent.AddChild (new CSharpTokenNode (Convert (location[i - 1]), 1), InvocationExpression.Roles.Comma); var arg = typeArguments.Args[i]; if (arg == null) continue; parent.AddChild (ConvertToType (arg), InvocationExpression.Roles.TypeArgument); + if (chevronLocs != null && i < chevronLocs.Count - 2) + parent.AddChild (new CSharpTokenNode (Convert (chevronLocs[i]), 1), InvocationExpression.Roles.Comma); } + + if (chevronLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (chevronLocs[chevronLocs.Count - 1]), 1), InvocationExpression.Roles.RChevron); } void AddConstraints (AstNode parent, DeclSpace d) @@ -2196,13 +2377,17 @@ namespace ICSharpCode.NRefactory.CSharp Constraints c = d.PlainConstraints [i]; var location = LocationsBag.GetLocations (c); var constraint = new Constraint (); - if (location != null) - constraint.AddChild (new CSharpTokenNode (Convert (location [0]), "where".Length), InvocationExpression.Roles.Keyword); + constraint.AddChild (new CSharpTokenNode (Convert (c.Location), "where".Length), InvocationExpression.Roles.Keyword); constraint.AddChild (Identifier.Create (c.TypeParameter.Value, Convert (c.TypeParameter.Location)), InvocationExpression.Roles.Identifier); - if (location != null && location.Count > 1) - constraint.AddChild (new CSharpTokenNode (Convert (location [1]), 1), Constraint.ColonRole); - foreach (var expr in c.ConstraintExpressions) + if (location != null) + constraint.AddChild (new CSharpTokenNode (Convert (location [0]), 1), Constraint.ColonRole); + var commaLocs = LocationsBag.GetLocations (c.ConstraintExpressions); + int curComma = 0; + foreach (var expr in c.ConstraintExpressions) { constraint.AddChild (ConvertToType (expr), Constraint.BaseTypeRole); + if (commaLocs != null && curComma < commaLocs.Count) + constraint.AddChild (new CSharpTokenNode (Convert (commaLocs[curComma++]), 1), InvocationExpression.Roles.Comma); + } parent.AddChild (constraint, AstNode.Roles.Constraint); } } @@ -2216,7 +2401,7 @@ namespace ICSharpCode.NRefactory.CSharp var loc = LocationsBag.GetLocations (na); if (loc != null) - newArg.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), NamedArgumentExpression.Roles.Assign); + newArg.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), NamedArgumentExpression.Roles.Colon); if (arg.ArgType == Argument.AType.Out || arg.ArgType == Argument.AType.Ref) { DirectionExpression direction = new DirectionExpression (); @@ -2251,24 +2436,22 @@ 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) { - int idx = commaLocations.Count - i; - if (idx >= 0) - parent.AddChild (new CSharpTokenNode (Convert (commaLocations[idx]), 1), InvocationExpression.Roles.Comma); + if (commaLocations != null && i < commaLocations.Count) { + parent.AddChild (new CSharpTokenNode (Convert (commaLocations[i]), 1), InvocationExpression.Roles.Comma); } } if (commaLocations != null && commaLocations.Count > args.Count) - parent.AddChild (new CSharpTokenNode (Convert (commaLocations[0]), 1), InvocationExpression.Roles.Comma); + parent.AddChild (new CSharpTokenNode (Convert (commaLocations[args.Count]), 1), InvocationExpression.Roles.Comma); } public override object Visit (Invocation invocationExpression) { 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); @@ -2281,7 +2464,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); @@ -2306,18 +2488,88 @@ namespace ICSharpCode.NRefactory.CSharp var location = LocationsBag.GetLocations (par); if (location == null) { - result.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); + if (par.Expr != 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); + if (par.Expr != null) + namedExpression.AddChild ((Expression)par.Expr.Accept (this), AnonymousTypeCreateExpression.Roles.Expression); + result.AddChild (namedExpression, AnonymousTypeCreateExpression.Roles.Expression); } } return result; } + ArrayInitializerExpression ConvertCollectionOrObjectInitializers (CollectionOrObjectInitializers minit) + { + if (minit == null) + return null; + var init = new ArrayInitializerExpression (); + AddConvertCollectionOrObjectInitializers (init, minit); + return init; + } + + void AddConvertCollectionOrObjectInitializers (Expression init, CollectionOrObjectInitializers minit) + { + var initLoc = LocationsBag.GetLocations (minit); + var commaLoc = LocationsBag.GetLocations (minit.Initializers); + int curComma = 0; + if (initLoc != null) + init.AddChild (new CSharpTokenNode (Convert (initLoc [0]), 1), ArrayInitializerExpression.Roles.LBrace); + foreach (var expr in minit.Initializers) { + var collectionInit = expr as CollectionElementInitializer; + if (collectionInit != null) { + 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 (braceLocs != null) + parent.AddChild (new CSharpTokenNode (Convert (braceLocs [1]), 1), ArrayInitializerExpression.Roles.RBrace); + + init.AddChild (parent, ArrayInitializerExpression.Roles.Expression); + } else { + var eleInit = expr as ElementInitializer; + if (eleInit != null) { + 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) { + 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); + } + } + + init.AddChild (nexpr, ArrayInitializerExpression.Roles.Expression); + } + } + if (commaLoc != null && curComma < commaLoc.Count) + init.AddChild (new CSharpTokenNode (Convert (commaLoc [curComma++]), 1), ArrayInitializerExpression.Roles.Comma); + + } + 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) { @@ -2334,6 +2586,10 @@ namespace ICSharpCode.NRefactory.CSharp if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ObjectCreateExpression.Roles.RPar); + var init = ConvertCollectionOrObjectInitializers (newInitializeExpression.Initializers); + if (init != null) + result.AddChild (init, ObjectCreateExpression.InitializerRole); + return result; } @@ -2343,32 +2599,39 @@ namespace ICSharpCode.NRefactory.CSharp var result = new ArrayCreateExpression (); var location = LocationsBag.GetLocations (arrayCreationExpression); + result.AddChild (new CSharpTokenNode (Convert (arrayCreationExpression.Location), "new".Length), ArrayCreateExpression.Roles.Keyword); if (arrayCreationExpression.NewType != null) result.AddChild (ConvertToType (arrayCreationExpression.NewType), ArrayCreateExpression.Roles.Type); - if (location != null) - result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ArrayCreateExpression.Roles.LBracket); + + var next = arrayCreationExpression.Rank; if (arrayCreationExpression.Arguments != null) { + // skip first array rank. + next = next.Next; + + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[0]), 1), ArrayCreateExpression.Roles.LBracket); + var commaLocations = LocationsBag.GetLocations (arrayCreationExpression.Arguments); for (int i = 0 ;i < arrayCreationExpression.Arguments.Count; i++) { result.AddChild ((Expression)arrayCreationExpression.Arguments[i].Accept (this), ArrayCreateExpression.Roles.Argument); - if (commaLocations != null && i > 0) - result.AddChild (new CSharpTokenNode (Convert (commaLocations [commaLocations.Count - i]), 1), ArrayCreateExpression.Roles.Comma); + if (commaLocations != null && i < commaLocations.Count) + result.AddChild (new CSharpTokenNode (Convert (commaLocations [i]), 1), ArrayCreateExpression.Roles.Comma); } + if (location != null) + result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ArrayCreateExpression.Roles.RBracket); + } - var next = arrayCreationExpression.Rank.Next; + while (next != null) { ArraySpecifier spec = new ArraySpecifier (next.Dimension); var loc = LocationsBag.GetLocations (next); spec.AddChild (new CSharpTokenNode (Convert (next.Location), 1), ArraySpecifier.Roles.LBracket); + result.AddChild (spec, ArrayCreateExpression.AdditionalArraySpecifierRole); if (loc != null) result.AddChild (new CSharpTokenNode (Convert (loc[0]), 1), ArraySpecifier.Roles.RBracket); - result.AddChild (spec, ArrayCreateExpression.AdditionalArraySpecifierRole); next = next.Next; } - if (location != null) - result.AddChild (new CSharpTokenNode (Convert (location[1]), 1), ArrayCreateExpression.Roles.RBracket); - if (arrayCreationExpression.Initializers != null && arrayCreationExpression.Initializers.Count != 0) { var initLocation = LocationsBag.GetLocations (arrayCreationExpression.Initializers); ArrayInitializerExpression initializer = new ArrayInitializerExpression(); @@ -2377,8 +2640,8 @@ namespace ICSharpCode.NRefactory.CSharp var commaLocations = LocationsBag.GetLocations (arrayCreationExpression.Initializers.Elements); for (int i = 0; i < arrayCreationExpression.Initializers.Count; i++) { initializer.AddChild ((Expression)arrayCreationExpression.Initializers[i].Accept (this), ArrayInitializerExpression.Roles.Expression); - if (commaLocations != null && i > 0) { - initializer.AddChild (new CSharpTokenNode (Convert (commaLocations [commaLocations.Count - i]), 1), IndexerExpression.Roles.Comma); + if (commaLocations != null && i < commaLocations.Count) { + initializer.AddChild (new CSharpTokenNode (Convert (commaLocations [i]), 1), IndexerExpression.Roles.Comma); } } @@ -2768,10 +3031,10 @@ namespace ICSharpCode.NRefactory.CSharp var result = new QueryGroupClause (); var location = LocationsBag.GetLocations (groupBy); result.AddChild (new CSharpTokenNode (Convert (groupBy.Location), "group".Length), QueryGroupClause.GroupKeywordRole); - result.AddChild ((Expression)groupBy.ElementSelector.Accept (this), QueryGroupClause.KeyRole); + result.AddChild ((Expression)groupBy.ElementSelector.Accept (this), QueryGroupClause.ProjectionRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[0]), "by".Length), QueryGroupClause.ByKeywordRole); - result.AddChild ((Expression)groupBy.Expr.Accept (this), QueryGroupClause.ProjectionRole); + result.AddChild ((Expression)groupBy.Expr.Accept (this), QueryGroupClause.KeyRole); return result; } @@ -2803,21 +3066,26 @@ namespace ICSharpCode.NRefactory.CSharp var result = new QueryJoinClause (); var location = LocationsBag.GetLocations (join); result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); - - result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), QueryJoinClause.JoinIdentifierRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); - result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.Roles.Expression); + result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.InExpressionRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[1]), "on".Length), QueryJoinClause.OnKeywordRole); - // TODO: on expression + + var outer = join.OuterSelector.Statements.FirstOrDefault () as ContextualReturn; + if (outer != null) + result.AddChild ((Expression)outer.Expr.Accept (this), QueryJoinClause.OnExpressionRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[2]), "equals".Length), QueryJoinClause.EqualsKeywordRole); - // TODO: equals expression + + var inner = join.InnerSelector.Statements.FirstOrDefault () as ContextualReturn; + if (inner != null) + result.AddChild ((Expression)inner.Expr.Accept (this), QueryJoinClause.EqualsExpressionRole); return result; } @@ -2828,26 +3096,30 @@ namespace ICSharpCode.NRefactory.CSharp var location = LocationsBag.GetLocations (join); result.AddChild (new CSharpTokenNode (Convert (join.Location), "join".Length), QueryJoinClause.JoinKeywordRole); - result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + // mcs seems to have swapped IntoVariable with JoinVariable, so we'll swap it back here + result.AddChild (Identifier.Create (join.IntoVariable.Name, Convert (join.IntoVariable.Location)), QueryJoinClause.JoinIdentifierRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[0]), "in".Length), QueryJoinClause.InKeywordRole); - result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.Roles.Expression); + var outer = join.OuterSelector.Statements.FirstOrDefault () as ContextualReturn; + if (outer != null) + result.AddChild ((Expression)outer.Expr.Accept (this), QueryJoinClause.OnExpressionRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[1]), "on".Length), QueryJoinClause.OnKeywordRole); - - // TODO: on expression + result.AddChild ((Expression)join.Expr.Accept (this), QueryJoinClause.InExpressionRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[2]), "equals".Length), QueryJoinClause.EqualsKeywordRole); - // TODO: equals expression + var inner = join.InnerSelector.Statements.FirstOrDefault () as ContextualReturn; + if (inner != null) + result.AddChild ((Expression)inner.Expr.Accept (this), QueryJoinClause.EqualsExpressionRole); if (location != null) result.AddChild (new CSharpTokenNode (Convert (location[3]), "into".Length), QueryJoinClause.IntoKeywordRole); - result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), Identifier.Roles.Identifier); + result.AddChild (Identifier.Create (join.JoinVariable.Name, Convert (join.JoinVariable.Location)), QueryJoinClause.IntoIdentifierRole); return result; } @@ -2947,36 +3219,85 @@ namespace ICSharpCode.NRefactory.CSharp static void InsertComments (CompilerCompilationUnit top, ConversionVisitor conversionVisitor) { - var leaf = GetOuterLeft(conversionVisitor.Unit); + var leaf = GetOuterLeft (conversionVisitor.Unit); - foreach (var special in top.SpecialsBag.Specials) { + for (int i = 0; i < top.SpecialsBag.Specials.Count; i++) { + var special = top.SpecialsBag.Specials [i]; + Comment newLeaf = null; + var comment = special as SpecialsBag.Comment; - if (comment == null) - continue; - if (conversionVisitor.convertTypeSystemMode && (comment.CommentType != SpecialsBag.CommentType.Documentation)) + if (comment != null) { + if (conversionVisitor.convertTypeSystemMode && (comment.CommentType != SpecialsBag.CommentType.Documentation)) + continue; + var type = (CommentType)comment.CommentType; + var start = new TextLocation (comment.Line, comment.Col); + var end = new TextLocation (comment.EndLine, comment.EndCol); + newLeaf = new Comment (type, start, end) { + StartsLine = comment.StartsLine, + Content = comment.Content + }; + } else { + // TODO: Proper handling of pre processor directives (atm got treated as comments Ast wise) + var directive = special as SpecialsBag.PreProcessorDirective; + if (directive != null) { + newLeaf = new Comment (CommentType.SingleLine, new TextLocation (directive.Line, directive.Col), new TextLocation (directive.EndLine, directive.EndCol + 1)); + + if (!directive.Take) { + SpecialsBag.PreProcessorDirective endif = null; + int endifLevel = 0; + for (int j = i + 1; j < top.SpecialsBag.Specials.Count; j++) { + var s = top.SpecialsBag.Specials [j] as SpecialsBag.PreProcessorDirective; + if (s == null) + continue; + if (s.Cmd == Tokenizer.PreprocessorDirective.If) { + endifLevel++; + continue; + } + if (s.Cmd == Tokenizer.PreprocessorDirective.Endif || endifLevel == 0 && s.Cmd == Tokenizer.PreprocessorDirective.Else) { + if (endifLevel == 0) { + endif = s; + i = j; + break; + } + endifLevel--; + } + } + if (endif != null) + newLeaf = new Comment (CommentType.SingleLine, new TextLocation (directive.Line, directive.Col), new TextLocation (endif.EndLine, endif.EndCol)); + } + } + } + + if (newLeaf == null) continue; - var type = (CommentType)comment.CommentType; - var start = new AstLocation (comment.Line, comment.Col); - var end = new AstLocation (comment.EndLine, comment.EndCol); - var domComment = new Comment (type, start, end); - domComment.StartsLine = comment.StartsLine; - domComment.Content = comment.Content; while (true) { - var nextLeaf = NextLeaf(leaf); - // instert comment at the end + var nextLeaf = NextLeaf (leaf); + // insert comment at begin + if (newLeaf.StartLocation < leaf.StartLocation) { + var node = leaf.Parent ?? conversionVisitor.Unit; + while (node.Parent != null && node.FirstChild == leaf) { + leaf = node; + node = node.Parent; + } + node.InsertChildBefore (leaf, newLeaf, AstNode.Roles.Comment); + leaf = newLeaf; + break; + } + + // insert comment at the end if (nextLeaf == null) { var node = leaf.Parent ?? conversionVisitor.Unit; - node.AddChild(domComment, AstNode.Roles.Comment); - leaf = domComment; + node.AddChild (newLeaf, AstNode.Roles.Comment); + leaf = newLeaf; break; } // comment is between 2 nodes - if (leaf.EndLocation <= domComment.StartLocation && domComment.StartLocation <= nextLeaf.StartLocation) { + if (leaf.EndLocation <= newLeaf.StartLocation && newLeaf.StartLocation <= nextLeaf.StartLocation) { var node = leaf.Parent ?? conversionVisitor.Unit; - node.InsertChildAfter(leaf, domComment, AstNode.Roles.Comment); - leaf = domComment; + node.InsertChildAfter (leaf, newLeaf, AstNode.Roles.Comment); + leaf = newLeaf; break; } leaf = nextLeaf; @@ -2989,8 +3310,8 @@ namespace ICSharpCode.NRefactory.CSharp if (top == null) return null; CSharpParser.ConversionVisitor conversionVisitor = new ConversionVisitor (convertTypeSystemMode, top.LocationsBag); - conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); top.UsingsBag.Global.Accept (conversionVisitor); + conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); InsertComments (top, conversionVisitor); return conversionVisitor.Unit; } @@ -3050,7 +3371,7 @@ namespace ICSharpCode.NRefactory.CSharp public static void AdjustLineLocations (AstNode node, int line) { if (node is IRelocatable) { - ((IRelocatable)node).SetStartLocation (new AstLocation (node.StartLocation.Line + line, node.StartLocation.Column)); + ((IRelocatable)node).SetStartLocation (new TextLocation (node.StartLocation.Line + line, node.StartLocation.Column)); } foreach (var child in node.Children) { AdjustLineLocations (child, line); @@ -3062,8 +3383,8 @@ namespace ICSharpCode.NRefactory.CSharp if (top == null) return null; CSharpParser.ConversionVisitor conversionVisitor = new ConversionVisitor (GenerateTypeSystemMode, top.LocationsBag); - conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); top.UsingsBag.Global.Accept (conversionVisitor); + conversionVisitor.AddAttributeSection (conversionVisitor.Unit, top.ModuleCompiled); InsertComments (top, conversionVisitor); if (CompilationUnitCallback != null) CompilationUnitCallback (top); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs b/ICSharpCode.NRefactory.CSharp/Parser/ParsedFile.cs similarity index 56% rename from ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs rename to ICSharpCode.NRefactory.CSharp/Parser/ParsedFile.cs index 954518842..1483d73b6 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/ParsedFile.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/ParsedFile.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -12,12 +27,14 @@ namespace ICSharpCode.NRefactory.CSharp /// /// Represents a file that was parsed and converted for the type system. /// - public sealed class ParsedFile : AbstractFreezable, IParsedFile + [Serializable] + public sealed class CSharpParsedFile : AbstractFreezable, IParsedFile { readonly string fileName; readonly UsingScope rootUsingScope; IList topLevelTypeDefinitions = new List(); IList assemblyAttributes = new List(); + IList moduleAttributes = new List(); IList usingScopes = new List(); IList errors = new List (); @@ -27,10 +44,11 @@ namespace ICSharpCode.NRefactory.CSharp rootUsingScope.Freeze(); topLevelTypeDefinitions = FreezeList(topLevelTypeDefinitions); assemblyAttributes = FreezeList(assemblyAttributes); + moduleAttributes = FreezeList(moduleAttributes); usingScopes = FreezeList(usingScopes); } - public ParsedFile(string fileName, UsingScope rootUsingScope) + public CSharpParsedFile(string fileName, UsingScope rootUsingScope) { if (fileName == null) throw new ArgumentNullException("fileName"); @@ -44,10 +62,13 @@ namespace ICSharpCode.NRefactory.CSharp get { return fileName; } } - DateTime parseTime = DateTime.Now; - public DateTime ParseTime { - get { - return parseTime; + DateTime lastWriteTime = DateTime.UtcNow; + + public DateTime LastWriteTime { + get { return lastWriteTime; } + set { + CheckBeforeMutation(); + lastWriteTime = value; } } @@ -76,7 +97,11 @@ namespace ICSharpCode.NRefactory.CSharp get { return assemblyAttributes; } } - public UsingScope GetUsingScope(AstLocation location) + public IList ModuleAttributes { + get { return moduleAttributes; } + } + + public UsingScope GetUsingScope(TextLocation location) { foreach (UsingScope scope in usingScopes) { if (scope.Region.IsInside(location.Line, location.Column)) @@ -85,12 +110,12 @@ namespace ICSharpCode.NRefactory.CSharp return rootUsingScope; } - public ITypeDefinition GetTopLevelTypeDefinition(AstLocation location) + public ITypeDefinition GetTopLevelTypeDefinition(TextLocation location) { return FindEntity(topLevelTypeDefinitions, location); } - public ITypeDefinition GetTypeDefinition(AstLocation location) + public ITypeDefinition GetInnermostTypeDefinition(TextLocation location) { ITypeDefinition parent = null; ITypeDefinition type = GetTopLevelTypeDefinition(location); @@ -101,9 +126,9 @@ namespace ICSharpCode.NRefactory.CSharp return parent; } - public IMember GetMember(AstLocation location) + public IMember GetMember(TextLocation location) { - ITypeDefinition type = GetTypeDefinition(location); + ITypeDefinition type = GetInnermostTypeDefinition(location); if (type == null) return null; return FindEntity(type.Methods, location) @@ -112,7 +137,7 @@ namespace ICSharpCode.NRefactory.CSharp ?? (IMember)FindEntity(type.Events, location); } - static T FindEntity(IList list, AstLocation location) where T : class, IEntity + static T FindEntity(IList list, TextLocation location) where T : class, IEntity { // This could be improved using a binary search foreach (T entity in list) { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs b/ICSharpCode.NRefactory.CSharp/Parser/TypeSystemConvertVisitor.cs similarity index 80% rename from ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs rename to ICSharpCode.NRefactory.CSharp/Parser/TypeSystemConvertVisitor.cs index ccd273ba5..259d14697 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/TypeSystemConvertVisitor.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/TypeSystemConvertVisitor.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -19,11 +34,22 @@ namespace ICSharpCode.NRefactory.CSharp /// public class TypeSystemConvertVisitor : DepthFirstAstVisitor { - readonly ParsedFile parsedFile; + readonly CSharpParsedFile parsedFile; UsingScope usingScope; DefaultTypeDefinition currentTypeDefinition; DefaultMethod currentMethod; + IInterningProvider interningProvider = new SimpleInterningProvider(); + + /// + /// Gets/Sets the interning provider to use. + /// The default value is a new instance. + /// + public IInterningProvider InterningProvider { + get { return interningProvider; } + set { interningProvider = value; } + } + /// /// Creates a new TypeSystemConvertVisitor. /// @@ -35,7 +61,7 @@ namespace ICSharpCode.NRefactory.CSharp throw new ArgumentNullException("pc"); if (fileName == null) throw new ArgumentNullException("fileName"); - this.parsedFile = new ParsedFile(fileName, new UsingScope(pc)); + this.parsedFile = new CSharpParsedFile(fileName, new UsingScope(pc)); this.usingScope = parsedFile.RootUsingScope; } @@ -45,7 +71,7 @@ namespace ICSharpCode.NRefactory.CSharp /// The parsed file to which members should be added. /// The current using scope. /// The current type definition. - public TypeSystemConvertVisitor(ParsedFile parsedFile, UsingScope currentUsingScope = null, DefaultTypeDefinition currentTypeDefinition = null) + public TypeSystemConvertVisitor(CSharpParsedFile parsedFile, UsingScope currentUsingScope = null, DefaultTypeDefinition currentTypeDefinition = null) { if (parsedFile == null) throw new ArgumentNullException("parsedFile"); @@ -54,11 +80,17 @@ namespace ICSharpCode.NRefactory.CSharp this.currentTypeDefinition = currentTypeDefinition; } - public ParsedFile ParsedFile { + public CSharpParsedFile Convert(AstNode node) + { + node.AcceptVisitor(this, null); + return parsedFile; + } + + public CSharpParsedFile ParsedFile { get { return parsedFile; } } - DomRegion MakeRegion(AstLocation start, AstLocation end) + DomRegion MakeRegion(TextLocation start, TextLocation end) { return new DomRegion(parsedFile.FileName, start.Line, start.Column, end.Line, end.Column); } @@ -97,17 +129,23 @@ namespace ICSharpCode.NRefactory.CSharp public override IEntity VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) { - ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, true) as ITypeOrNamespaceReference; - if (u != null) + ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, SimpleNameLookupMode.TypeInUsingDeclaration) as ITypeOrNamespaceReference; + if (u != null) { + if (interningProvider != null) + u = interningProvider.Intern(u); usingScope.Usings.Add(u); + } return null; } public override IEntity VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) { - ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, true) as ITypeOrNamespaceReference; - if (u != null) + ITypeOrNamespaceReference u = ConvertType(usingDeclaration.Import, SimpleNameLookupMode.TypeInUsingDeclaration) as ITypeOrNamespaceReference; + if (u != null) { + if (interningProvider != null) + u = interningProvider.Intern(u); usingScope.UsingAliases.Add(new KeyValuePair(usingDeclaration.Alias, u)); + } return null; } #endregion @@ -134,10 +172,11 @@ namespace ICSharpCode.NRefactory.CSharp DefaultTypeDefinition newType; if (currentTypeDefinition != null) { newType = new DefaultTypeDefinition(currentTypeDefinition, name); - newType.TypeParameters.AddRange(currentTypeDefinition.TypeParameters); + foreach (var typeParameter in currentTypeDefinition.TypeParameters) + newType.TypeParameters.Add(typeParameter); currentTypeDefinition.NestedTypes.Add(newType); } else { - newType = new DefaultTypeDefinition(usingScope.ProjectContent, usingScope.NamespaceName, name); + newType = new DefaultTypeDefinition(parsedFile, usingScope.NamespaceName, name); parsedFile.TopLevelTypeDefinitions.Add(newType); } return newType; @@ -146,22 +185,31 @@ namespace ICSharpCode.NRefactory.CSharp public override IEntity VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { var td = currentTypeDefinition = CreateTypeDefinition(typeDeclaration.Name); - td.ClassType = typeDeclaration.ClassType; td.Region = MakeRegion(typeDeclaration); td.BodyRegion = MakeBraceRegion(typeDeclaration); td.AddDefaultConstructorIfRequired = true; - ConvertAttributes(td.Attributes, typeDeclaration.Attributes); ApplyModifiers(td, typeDeclaration.Modifiers); - if (td.ClassType == ClassType.Interface) - td.IsAbstract = true; // interfaces are implicitly abstract - else if (td.ClassType == ClassType.Enum || td.ClassType == ClassType.Struct) - td.IsSealed = true; // enums/structs are implicitly sealed + switch (typeDeclaration.ClassType) { + case ClassType.Enum: + td.Kind = TypeKind.Enum; + break; + case ClassType.Interface: + td.Kind = TypeKind.Interface; + td.IsAbstract = true; // interfaces are implicitly abstract + break; + case ClassType.Struct: + td.Kind = TypeKind.Struct; + td.IsSealed = true; // enums/structs are implicitly sealed + break; + } + + ConvertAttributes(td.Attributes, typeDeclaration.Attributes); ConvertTypeParameters(td.TypeParameters, typeDeclaration.TypeParameters, typeDeclaration.Constraints, EntityType.TypeDefinition); foreach (AstType baseType in typeDeclaration.BaseTypes) { - td.BaseTypes.Add(ConvertType(baseType)); + td.BaseTypes.Add(ConvertType(baseType, SimpleNameLookupMode.BaseTypeReference)); } foreach (AttributedNode member in typeDeclaration.Members) { @@ -171,13 +219,16 @@ namespace ICSharpCode.NRefactory.CSharp td.HasExtensionMethods = td.Methods.Any(m => m.IsExtensionMethod); currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; + if (interningProvider != null) { + td.ApplyInterningProvider(interningProvider); + } return td; } public override IEntity VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { var td = currentTypeDefinition = CreateTypeDefinition(delegateDeclaration.Name); - td.ClassType = ClassType.Delegate; + td.Kind = TypeKind.Delegate; td.Region = MakeRegion(delegateDeclaration); td.BaseTypes.Add(multicastDelegateReference); @@ -201,6 +252,9 @@ namespace ICSharpCode.NRefactory.CSharp } currentTypeDefinition = (DefaultTypeDefinition)currentTypeDefinition.DeclaringTypeDefinition; + if (interningProvider != null) { + td.ApplyInterningProvider(interningProvider); + } return td; } @@ -234,7 +288,8 @@ namespace ICSharpCode.NRefactory.CSharp DefaultMethod invoke = new DefaultMethod(delegateType, "Invoke"); invoke.Accessibility = Accessibility.Public; invoke.IsSynthetic = true; - invoke.Parameters.AddRange(parameters); + foreach (var p in parameters) + invoke.Parameters.Add(p); invoke.ReturnType = returnType; invoke.Region = region; delegateType.Methods.Add(invoke); @@ -242,7 +297,8 @@ namespace ICSharpCode.NRefactory.CSharp DefaultMethod beginInvoke = new DefaultMethod(delegateType, "BeginInvoke"); beginInvoke.Accessibility = Accessibility.Public; beginInvoke.IsSynthetic = true; - beginInvoke.Parameters.AddRange(invoke.Parameters); + foreach (var p in parameters) + beginInvoke.Parameters.Add(p); beginInvoke.Parameters.Add(delegateAsyncCallbackParameter); beginInvoke.Parameters.Add(delegateObjectParameter); beginInvoke.ReturnType = delegateResultParameter.Type; @@ -287,19 +343,25 @@ namespace ICSharpCode.NRefactory.CSharp field.IsReadOnly = (modifiers & Modifiers.Readonly) != 0; field.ReturnType = ConvertType(fieldDeclaration.ReturnType); - if ((modifiers & Modifiers.Fixed) != 0) { - field.ReturnType = PointerTypeReference.Create(field.ReturnType); - } if ((modifiers & Modifiers.Const) != 0) { field.ConstantValue = ConvertConstantValue(field.ReturnType, vi.Initializer); } currentTypeDefinition.Fields.Add(field); + if (interningProvider != null) { + field.ApplyInterningProvider(interningProvider); + } } return isSingleField ? field : null; } + public override IEntity VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) + { + // TODO: add support for fixed fields + return base.VisitFixedFieldDeclaration(fixedFieldDeclaration, data); + } + public override IEntity VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) { DefaultField field = new DefaultField(currentTypeDefinition, enumMemberDeclaration.Name); @@ -321,6 +383,9 @@ namespace ICSharpCode.NRefactory.CSharp } currentTypeDefinition.Fields.Add(field); + if (interningProvider != null) { + field.ApplyInterningProvider(interningProvider); + } return field; } #endregion @@ -350,6 +415,9 @@ namespace ICSharpCode.NRefactory.CSharp currentTypeDefinition.Methods.Add(m); currentMethod = null; + if (interningProvider != null) { + m.ApplyInterningProvider(interningProvider); + } return m; } @@ -413,6 +481,9 @@ namespace ICSharpCode.NRefactory.CSharp ConvertParameters(m.Parameters, operatorDeclaration.Parameters); currentTypeDefinition.Methods.Add(m); + if (interningProvider != null) { + m.ApplyInterningProvider(interningProvider); + } return m; } #endregion @@ -441,6 +512,9 @@ namespace ICSharpCode.NRefactory.CSharp ApplyModifiers(ctor, modifiers); currentTypeDefinition.Methods.Add(ctor); + if (interningProvider != null) { + ctor.ApplyInterningProvider(interningProvider); + } return ctor; } #endregion @@ -459,6 +533,9 @@ namespace ICSharpCode.NRefactory.CSharp ConvertAttributes(dtor.Attributes, destructorDeclaration.Attributes); currentTypeDefinition.Methods.Add(dtor); + if (interningProvider != null) { + dtor.ApplyInterningProvider(interningProvider); + } return dtor; } #endregion @@ -479,12 +556,15 @@ namespace ICSharpCode.NRefactory.CSharp p.Getter = ConvertAccessor(propertyDeclaration.Getter, p.Accessibility); p.Setter = ConvertAccessor(propertyDeclaration.Setter, p.Accessibility); currentTypeDefinition.Properties.Add(p); + if (interningProvider != null) { + p.ApplyInterningProvider(interningProvider); + } return p; } public override IEntity VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) { - DefaultProperty p = new DefaultProperty(currentTypeDefinition, "Items"); + DefaultProperty p = new DefaultProperty(currentTypeDefinition, "Item"); p.EntityType = EntityType.Indexer; p.Region = MakeRegion(indexerDeclaration); p.BodyRegion = MakeBraceRegion(indexerDeclaration); @@ -499,6 +579,9 @@ namespace ICSharpCode.NRefactory.CSharp p.Setter = ConvertAccessor(indexerDeclaration.Setter, p.Accessibility); ConvertParameters(p.Parameters, indexerDeclaration.Parameters); currentTypeDefinition.Properties.Add(p); + if (interningProvider != null) { + p.ApplyInterningProvider(interningProvider); + } return p; } @@ -552,6 +635,9 @@ namespace ICSharpCode.NRefactory.CSharp } currentTypeDefinition.Events.Add(ev); + if (interningProvider != null) { + ev.ApplyInterningProvider(interningProvider); + } } return isSingleEvent ? ev : null; } @@ -574,6 +660,9 @@ namespace ICSharpCode.NRefactory.CSharp e.RemoveAccessor = ConvertAccessor(eventDeclaration.RemoveAccessor, e.Accessibility); currentTypeDefinition.Events.Add(e); + if (interningProvider != null) { + e.ApplyInterningProvider(interningProvider); + } return e; } #endregion @@ -589,9 +678,10 @@ namespace ICSharpCode.NRefactory.CSharp static void ApplyModifiers(TypeSystem.Implementation.AbstractMember m, Modifiers modifiers) { - // members from interfaces are always Public. - if (m.DeclaringTypeDefinition.ClassType == ClassType.Interface) { + // members from interfaces are always Public+Abstract. + if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) { m.Accessibility = Accessibility.Public; + m.IsAbstract = true; return; } m.Accessibility = GetAccessibility(modifiers) ?? Accessibility.Private; @@ -628,6 +718,8 @@ namespace ICSharpCode.NRefactory.CSharp // non-assembly attributes are handled by their parent entity if (attributeSection.AttributeTarget == "assembly") { ConvertAttributes(parsedFile.AssemblyAttributes, attributeSection); + } else if (attributeSection.AttributeTarget == "module") { + ConvertAttributes(parsedFile.ModuleAttributes, attributeSection); } return null; } @@ -646,20 +738,26 @@ namespace ICSharpCode.NRefactory.CSharp } } - IAttribute ConvertAttribute(CSharp.Attribute attr) + internal static ITypeReference ConvertAttributeType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope) { - DomRegion region = MakeRegion(attr); - ITypeReference type = ConvertType(attr.Type); - if (!attr.Type.GetChildByRole(AstNode.Roles.Identifier).IsVerbatim) { + ITypeReference tr = ConvertType(type, parentTypeDefinition, parentMethodDefinition, parentUsingScope, SimpleNameLookupMode.Type); + if (!type.GetChildByRole(AstNode.Roles.Identifier).IsVerbatim) { // Try to add "Attribute" suffix, but only if the identifier // (=last identifier in fully qualified name) isn't a verbatim identifier. - SimpleTypeOrNamespaceReference st = type as SimpleTypeOrNamespaceReference; - MemberTypeOrNamespaceReference mt = type as MemberTypeOrNamespaceReference; + SimpleTypeOrNamespaceReference st = tr as SimpleTypeOrNamespaceReference; + MemberTypeOrNamespaceReference mt = tr as MemberTypeOrNamespaceReference; if (st != null) - type = new AttributeTypeReference(st, st.AddSuffix("Attribute")); + return new AttributeTypeReference(st, st.AddSuffix("Attribute")); else if (mt != null) - type = new AttributeTypeReference(mt, mt.AddSuffix("Attribute")); + return new AttributeTypeReference(mt, mt.AddSuffix("Attribute")); } + return tr; + } + + IAttribute ConvertAttribute(CSharp.Attribute attr) + { + DomRegion region = MakeRegion(attr); + ITypeReference type = ConvertAttributeType(attr.Type, currentTypeDefinition, currentMethod, usingScope); List positionalArguments = null; List> namedCtorArguments = null; List> namedArguments = null; @@ -670,12 +768,12 @@ namespace ICSharpCode.NRefactory.CSharp namedCtorArguments = new List>(); namedCtorArguments.Add(new KeyValuePair(nae.Identifier, ConvertAttributeArgument(nae.Expression))); } else { - AssignmentExpression ae = expr as AssignmentExpression; - if (ae != null && ae.Left is IdentifierExpression && ae.Operator == AssignmentOperatorType.Assign) { - string name = ((IdentifierExpression)ae.Left).Identifier; + NamedExpression namedExpression = expr as NamedExpression; + if (namedExpression != null) { + string name = namedExpression.Identifier; if (namedArguments == null) namedArguments = new List>(); - namedArguments.Add(new KeyValuePair(name, ConvertAttributeArgument(ae.Right))); + namedArguments.Add(new KeyValuePair(name, ConvertAttributeArgument(namedExpression.Expression))); } else { if (positionalArguments == null) positionalArguments = new List(); @@ -688,28 +786,32 @@ namespace ICSharpCode.NRefactory.CSharp #endregion #region Types - ITypeReference ConvertType(AstType type, bool isInUsingDeclaration = false) + ITypeReference ConvertType(AstType type, SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type) { - return ConvertType(type, currentTypeDefinition, currentMethod, usingScope, isInUsingDeclaration); + return ConvertType(type, currentTypeDefinition, currentMethod, usingScope, lookupMode); } - internal static ITypeReference ConvertType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope, bool isInUsingDeclaration) + internal static ITypeReference ConvertType(AstType type, ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope, SimpleNameLookupMode lookupMode) { SimpleType s = type as SimpleType; if (s != null) { List typeArguments = new List(); foreach (var ta in s.TypeArguments) { - typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration)); + typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode)); } if (typeArguments.Count == 0 && parentMethodDefinition != null) { - // SimpleTypeOrNamespaceReference doesn't support method type parameters, - // so we directly handle them here. + // SimpleTypeOrNamespaceReference doesn't have a 'current method' context + // so we have to handle method type parameters here. foreach (ITypeParameter tp in parentMethodDefinition.TypeParameters) { if (tp.Name == s.Identifier) return tp; } } - return new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration); + if (typeArguments.Count == 0 && string.IsNullOrEmpty(s.Identifier)) { + // empty SimpleType is used for typeof(List<>). + return SharedTypes.UnboundTypeArgument; + } + return new SimpleTypeOrNamespaceReference(s.Identifier, typeArguments, parentTypeDefinition, parentUsingScope, lookupMode); } PrimitiveType p = type as PrimitiveType; @@ -742,7 +844,7 @@ namespace ICSharpCode.NRefactory.CSharp case "double": return KnownTypeReference.Double; case "decimal": - return ReflectionHelper.ToTypeReference(TypeCode.Decimal); + return KnownTypeReference.Decimal; case "char": return KnownTypeReference.Char; case "void": @@ -762,19 +864,19 @@ namespace ICSharpCode.NRefactory.CSharp t = null; } } else { - t = ConvertType(m.Target, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration) as ITypeOrNamespaceReference; + t = ConvertType(m.Target, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode) as ITypeOrNamespaceReference; } if (t == null) return SharedTypes.UnknownType; List typeArguments = new List(); foreach (var ta in m.TypeArguments) { - typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration)); + typeArguments.Add(ConvertType(ta, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode)); } return new MemberTypeOrNamespaceReference(t, m.MemberName, typeArguments, parentTypeDefinition, parentUsingScope); } ComposedType c = type as ComposedType; if (c != null) { - ITypeReference t = ConvertType(c.BaseType, parentTypeDefinition, parentMethodDefinition, parentUsingScope, isInUsingDeclaration); + ITypeReference t = ConvertType(c.BaseType, parentTypeDefinition, parentMethodDefinition, parentUsingScope, lookupMode); if (c.HasNullableSpecifier) { t = NullableType.Create(t); } @@ -794,25 +896,28 @@ namespace ICSharpCode.NRefactory.CSharp #region Constant Values IConstantValue ConvertConstantValue(ITypeReference targetType, AstNode expression) { - ConstantValueBuilder b = new ConstantValueBuilder(); - b.convertVisitor = this; + return ConvertConstantValue(targetType, expression, currentTypeDefinition, currentMethod, usingScope); + } + + internal static IConstantValue ConvertConstantValue(ITypeReference targetType, AstNode expression, + ITypeDefinition parentTypeDefinition, IMethod parentMethodDefinition, UsingScope parentUsingScope) + { + ConstantValueBuilder b = new ConstantValueBuilder(parentTypeDefinition, parentMethodDefinition, parentUsingScope, false); ConstantExpression c = expression.AcceptVisitor(b, null); if (c == null) - return null; + return new ErrorConstantValue(targetType); PrimitiveConstantExpression pc = c as PrimitiveConstantExpression; if (pc != null && pc.Type == targetType) { // Save memory by directly using a SimpleConstantValue. return new SimpleConstantValue(targetType, pc.Value); } // cast to the desired type - return new CSharpConstantValue(new ConstantCast(targetType, c), usingScope, currentTypeDefinition); + return new CSharpConstantValue(new ConstantCast(targetType, c), parentUsingScope, parentTypeDefinition); } IConstantValue ConvertAttributeArgument(Expression expression) { - ConstantValueBuilder b = new ConstantValueBuilder(); - b.convertVisitor = this; - b.isAttributeArgument = true; + ConstantValueBuilder b = new ConstantValueBuilder(currentTypeDefinition, currentMethod, usingScope, true); ConstantExpression c = expression.AcceptVisitor(b, null); if (c == null) return null; @@ -827,8 +932,23 @@ namespace ICSharpCode.NRefactory.CSharp sealed class ConstantValueBuilder : DepthFirstAstVisitor { - internal TypeSystemConvertVisitor convertVisitor; - internal bool isAttributeArgument; + readonly ITypeDefinition currentTypeDefinition; + readonly IMethod currentMethod; + readonly UsingScope usingScope; + readonly bool isAttributeArgument; + + public ConstantValueBuilder(ITypeDefinition currentTypeDefinition, IMethod currentMethod, UsingScope usingScope, bool isAttributeArgument) + { + this.currentTypeDefinition = currentTypeDefinition; + this.currentMethod = currentMethod; + this.usingScope = usingScope; + this.isAttributeArgument = isAttributeArgument; + } + + ITypeReference ConvertType(AstType type) + { + return TypeSystemConvertVisitor.ConvertType(type, currentTypeDefinition, currentMethod, usingScope, SimpleNameLookupMode.Type); + } protected override ConstantExpression VisitChildren(AstNode node, object data) { @@ -854,7 +974,7 @@ namespace ICSharpCode.NRefactory.CSharp ITypeReference[] result = new ITypeReference[count]; int pos = 0; foreach (AstType type in types) { - result[pos++] = convertVisitor.ConvertType(type); + result[pos++] = ConvertType(type); } return result; } @@ -870,7 +990,7 @@ namespace ICSharpCode.NRefactory.CSharp if (tre != null) { // handle "int.MaxValue" return new ConstantMemberReference( - convertVisitor.ConvertType(tre.Type), + ConvertType(tre.Type), memberReferenceExpression.MemberName, ConvertTypeArguments(memberReferenceExpression.TypeArguments)); } @@ -892,7 +1012,7 @@ namespace ICSharpCode.NRefactory.CSharp ConstantExpression v = castExpression.Expression.AcceptVisitor(this, data); if (v == null) return null; - return new ConstantCast(convertVisitor.ConvertType(castExpression.Type), v); + return new ConstantCast(ConvertType(castExpression.Type), v); } public override ConstantExpression VisitCheckedExpression(CheckedExpression checkedExpression, object data) @@ -915,7 +1035,7 @@ namespace ICSharpCode.NRefactory.CSharp public override ConstantExpression VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) { - return new ConstantDefaultValue(convertVisitor.ConvertType(defaultValueExpression.Type)); + return new ConstantDefaultValue(ConvertType(defaultValueExpression.Type)); } public override ConstantExpression VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) @@ -943,26 +1063,29 @@ namespace ICSharpCode.NRefactory.CSharp return new ConstantBinaryOperator(left, binaryOperatorExpression.Operator, right); } - static readonly GetClassTypeReference systemType = new GetClassTypeReference("System", "Type", 0); - public override ConstantExpression VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) { if (isAttributeArgument) { - return new PrimitiveConstantExpression(systemType, convertVisitor.ConvertType(typeOfExpression.Type)); + return new PrimitiveConstantExpression(KnownTypeReference.Type, ConvertType(typeOfExpression.Type)); } else { return null; } } - public override ConstantExpression VisitArrayCreateExpression(ArrayCreateExpression arrayObjectCreateExpression, object data) + public override ConstantExpression VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) { - var initializer = arrayObjectCreateExpression.Initializer; - if (isAttributeArgument && !initializer.IsNull) { + var initializer = arrayCreateExpression.Initializer; + // Attributes only allow one-dimensional arrays + if (isAttributeArgument && !initializer.IsNull && arrayCreateExpression.Arguments.Count < 2) { ITypeReference type; - if (arrayObjectCreateExpression.Type.IsNull) + if (arrayCreateExpression.Type.IsNull) { type = null; - else - type = convertVisitor.ConvertType(arrayObjectCreateExpression.Type); + } else { + type = ConvertType(arrayCreateExpression.Type); + foreach (var spec in arrayCreateExpression.AdditionalArraySpecifiers.Reverse()) { + type = ArrayTypeReference.Create(type, spec.Dimensions); + } + } ConstantExpression[] elements = new ConstantExpression[initializer.Elements.Count]; int pos = 0; foreach (Expression expr in initializer.Elements) { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/AssemblyInfo.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/AssemblyInfo.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/AssemblyInfo.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog b/ICSharpCode.NRefactory.CSharp/Parser/mcs/ChangeLog similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/ChangeLog rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/ChangeLog diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/CryptoConvert.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/CryptoConvert.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/CryptoConvert.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile b/ICSharpCode.NRefactory.CSharp/Parser/mcs/Makefile similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/Makefile rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/Makefile diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/MonoSymbolFile.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolFile.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/MonoSymbolFile.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/MonoSymbolTable.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolTable.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/MonoSymbolTable.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/MonoSymbolWriter.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/MonoSymbolWriter.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/MonoSymbolWriter.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES b/ICSharpCode.NRefactory.CSharp/Parser/mcs/NOTES similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/NOTES rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/NOTES diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE b/ICSharpCode.NRefactory.CSharp/Parser/mcs/OPTIMIZE similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/OPTIMIZE rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/OPTIMIZE diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO b/ICSharpCode.NRefactory.CSharp/Parser/mcs/OTODO similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/OTODO rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/OTODO diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN b/ICSharpCode.NRefactory.CSharp/Parser/mcs/PLAN similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/PLAN rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/PLAN diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/README b/ICSharpCode.NRefactory.CSharp/Parser/mcs/README similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/README rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/README diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO b/ICSharpCode.NRefactory.CSharp/Parser/mcs/TODO similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/TODO rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/TODO diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs index 5576bcc5f..d52dc82d3 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/anonymous.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/anonymous.cs @@ -193,7 +193,7 @@ namespace Mono.CSharp { protected HoistedThis hoisted_this; // Local variable which holds this storey instance - public LocalTemporary Instance; + public Expression Instance; public AnonymousMethodStorey (Block block, TypeContainer parent, MemberBase host, TypeParameter[] tparams, string name) : base (parent, MakeMemberName (host, name, unique_id, tparams, block.StartLocation), @@ -236,7 +236,12 @@ namespace Mono.CSharp { protected Field AddCompilerGeneratedField (string name, FullNamedExpression type) { - const Modifiers mod = Modifiers.INTERNAL | Modifiers.COMPILER_GENERATED; + return AddCompilerGeneratedField (name, type, false); + } + + protected Field AddCompilerGeneratedField (string name, FullNamedExpression type, bool privateAccess) + { + Modifiers mod = Modifiers.COMPILER_GENERATED | (privateAccess ? Modifiers.PRIVATE : Modifiers.INTERNAL); Field f = new Field (this, type, mod, new MemberName (name, Location), null); AddField (f); return f; @@ -391,21 +396,47 @@ namespace Mono.CSharp { SymbolWriter.OpenCompilerGeneratedBlock (ec); // - // Create an instance of a storey + // Create an instance of this storey // - var storey_type_expr = CreateStoreyTypeExpression (ec); - ResolveContext rc = new ResolveContext (ec.MemberContext); rc.CurrentBlock = block; - Expression e = new New (storey_type_expr, null, Location).Resolve (rc); - e.Emit (ec); - Instance = new LocalTemporary (storey_type_expr.Type); - Instance.Store (ec); + var storey_type_expr = CreateStoreyTypeExpression (ec); + var source = new New (storey_type_expr, null, Location).Resolve (rc); + + // + // When the current context is async (or iterator) lift local storey + // instantiation to the currect storey + // + if (ec.CurrentAnonymousMethod is StateMachineInitializer) { + // + // Unfortunately, normal capture mechanism could not be used because we are + // too late in the pipeline and standart assign cannot be used either due to + // recursive nature of GetStoreyInstanceExpression + // + var field = ec.CurrentAnonymousMethod.Storey.AddCompilerGeneratedField ( + LocalVariable.GetCompilerGeneratedName (block), storey_type_expr, true); + + field.Define (); + field.Emit (); + + var fexpr = new FieldExpr (field, Location); + fexpr.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location); + fexpr.EmitAssign (ec, source, false, false); + + Instance = fexpr; + } else { + var local = TemporaryVariableReference.Create (source.Type, block, Location); + local.EmitAssign (ec, source); + + Instance = local; + } EmitHoistedFieldsInitialization (rc, ec); - SymbolWriter.DefineScopeVariable (ID, Instance.Builder); + // TODO: Implement properly + //SymbolWriter.DefineScopeVariable (ID, Instance.Builder); + SymbolWriter.CloseCompilerGeneratedBlock (ec); } @@ -526,10 +557,11 @@ namespace Mono.CSharp { if (f == null) { if (am.Storey == this) { // - // Access inside of same storey (S -> S) + // Access from inside of same storey (S -> S) // return new CompilerGeneratedThis (CurrentType, Location); } + // // External field access // @@ -583,6 +615,11 @@ namespace Mono.CSharp { this.hv = hv; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { return hv.CreateExpressionTree (); @@ -637,6 +674,11 @@ namespace Mono.CSharp { GetFieldExpression (ec).Emit (ec); } + public Expression EmitToField (EmitContext ec) + { + return GetFieldExpression (ec); + } + // // Creates field access expression for hoisted variable // @@ -692,7 +734,7 @@ namespace Mono.CSharp { GetFieldExpression (ec).Emit (ec, leave_copy); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { GetFieldExpression (ec).EmitAssign (ec, source, leave_copy, false); } @@ -760,12 +802,20 @@ namespace Mono.CSharp { { readonly string name; - public HoistedLocalVariable (AnonymousMethodStorey scope, LocalVariable local, string name) - : base (scope, name, local.Type) + public HoistedLocalVariable (AnonymousMethodStorey storey, LocalVariable local, string name) + : base (storey, name, local.Type) { this.name = local.Name; } + // + // For compiler generated local variables + // + public HoistedLocalVariable (AnonymousMethodStorey storey, Field field) + : base (storey, field) + { + } + public override void EmitSymbolInfo () { SymbolWriter.DefineCapturedLocal (storey.ID, name, field.Name); @@ -1021,7 +1071,7 @@ namespace Mono.CSharp { var body = CompatibleMethodBody (ec, tic, InternalType.Arglist, delegate_type); if (body != null) { if (is_async) { - AsyncInitializer.Create (body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc); + AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, null, loc); } am = body.Compatible (ec, body, is_async); @@ -1037,6 +1087,11 @@ namespace Mono.CSharp { return am.ReturnType; } + public override bool ContainsEmitWithAwait () + { + return false; + } + // // Returns AnonymousMethod container if this anonymous method // expression can be implicitly converted to the delegate type `delegate_type' @@ -1102,7 +1157,7 @@ namespace Mono.CSharp { } } else { if (is_async) { - AsyncInitializer.Create (body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, body.ReturnType, loc); + AsyncInitializer.Create (ec, body.Block, body.Parameters, ec.CurrentMemberDefinition.Parent, body.ReturnType, loc); } am = body.Compatible (ec); @@ -1190,12 +1245,13 @@ namespace Mono.CSharp { if (!DoResolveParameters (ec)) return null; +#if !STATIC // FIXME: The emitted code isn't very careful about reachability // so, ensure we have a 'ret' at the end BlockContext bc = ec as BlockContext; if (bc != null && bc.CurrentBranching != null && bc.CurrentBranching.CurrentUsageVector.IsUnreachable) bc.NeedReturnLabel (); - +#endif return this; } @@ -1280,11 +1336,6 @@ namespace Mono.CSharp { { EmitContext ec = new EmitContext (this, ig, ReturnType); ec.CurrentAnonymousMethod = AnonymousMethod; - if (AnonymousMethod.return_label != null) { - ec.HasReturnLabel = true; - ec.ReturnLabel = (Label) AnonymousMethod.return_label; - } - return ec; } @@ -1330,8 +1381,6 @@ namespace Mono.CSharp { public TypeSpec ReturnType; - object return_label; - protected AnonymousExpression (ParametersBlock block, TypeSpec return_type, Location loc) { this.ReturnType = return_type; @@ -1380,9 +1429,6 @@ namespace Mono.CSharp { bool res = Block.Resolve (ec.CurrentBranching, aec, null); - if (aec.HasReturnLabel) - return_label = aec.ReturnLabel; - if (am != null && am.ReturnTypeInference != null) { am.ReturnTypeInference.FixAllTypes (ec); ReturnType = am.ReturnTypeInference.InferredTypeArguments [0]; @@ -1403,6 +1449,11 @@ namespace Mono.CSharp { return res ? this : null; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public void SetHasThisAccess () { ExplicitBlock b = block; @@ -1629,13 +1680,13 @@ namespace Mono.CSharp { // if (is_static) { - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); } else if (storey != null) { Expression e = storey.GetStoreyInstanceExpression (ec).Resolve (new ResolveContext (ec.MemberContext)); if (e != null) e.Emit (ec); } else { - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); } var delegate_method = method.Spec; diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs similarity index 86% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs index a24606689..2192b9c9e 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/argument.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/argument.cs @@ -103,6 +103,28 @@ namespace Mono.CSharp return Expr.CreateExpressionTree (ec); } + + public virtual void Emit (EmitContext ec) + { + if (!IsByRef) { + Expr.Emit (ec); + return; + } + + AddressOp mode = AddressOp.Store; + if (ArgType == AType.Ref) + mode |= AddressOp.Load; + + IMemoryLocation ml = (IMemoryLocation) Expr; + ml.AddressOf (ec, mode); + } + + public Argument EmitToField (EmitContext ec) + { + var res = Expr.EmitToField (ec); + return res == Expr ? this : new Argument (res, ArgType); + } + public string GetSignatureForError () { if (Expr.eclass == ExprClass.MethodGroup) @@ -141,21 +163,6 @@ namespace Mono.CSharp Expr = ErrorExpression.Instance; // } } - - public virtual void Emit (EmitContext ec) - { - if (!IsByRef) { - Expr.Emit (ec); - return; - } - - AddressOp mode = AddressOp.Store; - if (ArgType == AType.Ref) - mode |= AddressOp.Load; - - IMemoryLocation ml = (IMemoryLocation) Expr; - ml.AddressOf (ec, mode); - } } public class MovableArgument : Argument @@ -182,12 +189,12 @@ namespace Mono.CSharp variable.Release (ec); } - public void EmitAssign (EmitContext ec) + public void EmitToVariable (EmitContext ec) { var type = Expr.Type; if (IsByRef) { var ml = (IMemoryLocation) Expr; - ml.AddressOf (ec, AddressOp.Load); + ml.AddressOf (ec, AddressOp.LoadStore); type = ReferenceContainer.MakeType (ec.Module, type); } else { Expr.Emit (ec); @@ -246,13 +253,16 @@ namespace Mono.CSharp ordered.Add (arg); } - public override Expression[] Emit (EmitContext ec, bool dup_args) + public override Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait) { foreach (var a in ordered) { - a.EmitAssign (ec); + if (prepareAwait) + a.EmitToField (ec); + else + a.EmitToVariable (ec); } - return base.Emit (ec, dup_args); + return base.Emit (ec, dup_args, prepareAwait); } } @@ -264,6 +274,11 @@ namespace Mono.CSharp args = new List (capacity); } + private Arguments (List args) + { + this.args = args; + } + public void Add (Argument arg) { args.Add (arg); @@ -274,6 +289,16 @@ namespace Mono.CSharp this.args.AddRange (args.args); } + public bool ContainsEmitWithAwait () + { + foreach (var arg in args) { + if (arg.Expr.ContainsEmitWithAwait ()) + return true; + } + + return false; + } + public ArrayInitializer CreateDynamicBinderArguments (ResolveContext rc) { Location loc = Location.Null; @@ -395,46 +420,58 @@ namespace Mono.CSharp // public void Emit (EmitContext ec) { - Emit (ec, false); + Emit (ec, false, false); } // - // if `dup_args' is true, a copy of the arguments will be left - // on the stack and return value will contain an array of access - // expressions - // NOTE: It's caller responsibility is to release temporary variables + // if `dup_args' is true or any of arguments contains await. + // A copy of all arguments will be returned to the caller // - public virtual Expression[] Emit (EmitContext ec, bool dup_args) + public virtual Arguments Emit (EmitContext ec, bool dup_args, bool prepareAwait) { - Expression[] temps; + List dups; - if (dup_args && Count != 0) - temps = new Expression [Count]; + if ((dup_args && Count != 0) || prepareAwait) + dups = new List (Count); else - temps = null; + dups = null; - int i = 0; LocalTemporary lt; foreach (Argument a in args) { + if (prepareAwait) { + dups.Add (a.EmitToField (ec)); + continue; + } + a.Emit (ec); - if (!dup_args) + + if (!dup_args) { continue; + } - if (a.Expr is Constant || a.Expr is This) { + if (a.Expr.IsSideEffectFree) { // - // No need to create a temporary variable for constants + // No need to create a temporary variable for side effect free expressions. I assume + // all side-effect free expressions are cheap, this has to be tweaked when we become + // more aggressive on detection // - temps[i] = a.Expr; + dups.Add (a); } else { ec.Emit (OpCodes.Dup); - temps[i] = lt = new LocalTemporary (a.Type); + + // TODO: Release local temporary on next Emit + // Need to add a flag to argument to indicate this + lt = new LocalTemporary (a.Type); lt.Store (ec); - } - ++i; + dups.Add (new Argument (lt, a.ArgType)); + } } - return temps; + if (dups != null) + return new Arguments (dups); + + return null; } public List.Enumerator GetEnumerator () @@ -497,9 +534,9 @@ namespace Mono.CSharp public Arguments MarkOrderedArgument (NamedArgument a) { // - // Constant expression have no effect on left-to-right execution + // An expression has no effect on left-to-right execution // - if (a.Expr is Constant) + if (a.Expr.IsSideEffectFree) return this; ArgumentsOrdered ra = this as ArgumentsOrdered; @@ -511,6 +548,12 @@ namespace Mono.CSharp if (la == a) break; + // + // When the argument is filled later by default expression + // + if (la == null) + continue; + var ma = la as MovableArgument; if (ma == null) { ma = new MovableArgument (la); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/assembly.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/assembly.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/assembly.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs index 6fd2a7a03..2a82f240b 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/assign.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/assign.cs @@ -51,7 +51,7 @@ namespace Mono.CSharp { // be data on the stack that it can use to compuatate its value. This is // for expressions like a [f ()] ++, where you can't call `f ()' twice. // - void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load); + void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound); /* For simple assignments, this interface is very simple, EmitAssign is called with source @@ -201,6 +201,11 @@ namespace Mono.CSharp { builder = null; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (1); @@ -236,9 +241,9 @@ namespace Mono.CSharp { Emit (ec); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { - if (prepare_for_load) + if (isCompound) throw new NotImplementedException (); source.Emit (ec); @@ -294,12 +299,6 @@ namespace Mono.CSharp { this.loc = loc; } - public override Expression CreateExpressionTree (ResolveContext ec) - { - ec.Report.Error (832, loc, "An expression tree cannot contain an assignment operator"); - return null; - } - public Expression Target { get { return target; } } @@ -310,6 +309,17 @@ namespace Mono.CSharp { } } + public override bool ContainsEmitWithAwait () + { + return target.ContainsEmitWithAwait () || source.ContainsEmitWithAwait (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + ec.Report.Error (832, loc, "An expression tree cannot contain an assignment operator"); + return null; + } + protected override Expression DoResolve (ResolveContext ec) { bool ok = true; @@ -546,10 +556,6 @@ namespace Mono.CSharp { base.EmitStatement (ec); } - public bool IsComplexInitializer { - get { return !(source is Constant); } - } - public bool IsDefaultInitializer { get { Constant c = source as Constant; @@ -560,6 +566,12 @@ namespace Mono.CSharp { return c.IsDefaultInitializer (fe.Type); } } + + public override bool IsSideEffectFree { + get { + return source.IsSideEffectFree; + } + } } // @@ -570,13 +582,19 @@ namespace Mono.CSharp { // This is just a hack implemented for arrays only public sealed class TargetExpression : Expression { - Expression child; + readonly Expression child; + public TargetExpression (Expression child) { this.child = child; this.loc = child.Location; } + public override bool ContainsEmitWithAwait () + { + return child.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -593,6 +611,11 @@ namespace Mono.CSharp { { child.Emit (ec); } + + public override Expression EmitToField (EmitContext ec) + { + return child.EmitToField (ec); + } } // Used for underlying binary operator diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs similarity index 64% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs index 1a1345013..24c138ece 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/async.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/async.cs @@ -1,4 +1,4 @@ -// +// // async.cs: Asynchronous functions // // Author: @@ -7,11 +7,14 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2011 Novell, Inc. +// Copyright 2011 Xamarin Inc. // using System; using System.Collections.Generic; using System.Linq; +using System.Collections; + #if STATIC using IKVM.Reflection.Emit; #else @@ -43,18 +46,13 @@ namespace Mono.CSharp throw new NotImplementedException ("ET"); } - protected override Expression DoResolve (ResolveContext rc) + public override bool ContainsEmitWithAwait () { - if (rc.HasSet (ResolveContext.Options.FinallyScope)) { - rc.Report.Error (1984, loc, - "The `await' operator cannot be used in the body of a finally clause"); - } - - if (rc.HasSet (ResolveContext.Options.CatchScope)) { - rc.Report.Error (1985, loc, - "The `await' operator cannot be used in the body of a catch clause"); - } + return true; + } + protected override Expression DoResolve (ResolveContext rc) + { if (rc.HasSet (ResolveContext.Options.LockScope)) { rc.Report.Error (1996, loc, "The `await' operator cannot be used in the body of a lock statement"); @@ -92,7 +90,13 @@ namespace Mono.CSharp stmt.EmitPrologue (ec); stmt.Emit (ec); } - + + public override Expression EmitToField (EmitContext ec) + { + stmt.EmitPrologue (ec); + return stmt.GetResultExpression (ec); + } + public void EmitAssign (EmitContext ec, FieldExpr field) { stmt.EmitPrologue (ec); @@ -126,11 +130,27 @@ namespace Mono.CSharp } } + sealed class GetResultInvocation : Invocation + { + public GetResultInvocation (MethodGroupExpr mge, Arguments arguments) + : base (null, arguments) + { + mg = mge; + type = mg.BestCandidateReturnType; + } + + public override Expression EmitToField (EmitContext ec) + { + return this; + } + } + Field awaiter; - PropertyExpr is_completed; + PropertySpec is_completed; MethodSpec on_completed; MethodSpec get_result; TypeSpec type; + TypeSpec result_type; public AwaitStatement (Expression expr, Location loc) : base (expr, loc) @@ -139,6 +159,12 @@ namespace Mono.CSharp #region Properties + bool IsDynamic { + get { + return is_completed == null; + } + } + public TypeSpec Type { get { return type; @@ -147,13 +173,18 @@ namespace Mono.CSharp public TypeSpec ResultType { get { - return get_result.ReturnType; + return result_type; } } #endregion protected override void DoEmit (EmitContext ec) + { + GetResultExpression (ec).Emit (ec); + } + + public Expression GetResultExpression (EmitContext ec) { var fe_awaiter = new FieldExpr (awaiter, loc); fe_awaiter.InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, loc); @@ -161,10 +192,15 @@ namespace Mono.CSharp // // result = awaiter.GetResult (); // - var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc); - mg_result.InstanceExpression = fe_awaiter; + if (IsDynamic) { + var rc = new ResolveContext (ec.MemberContext); + return new Invocation (new MemberAccess (fe_awaiter, "GetResult"), new Arguments (0)).Resolve (rc); + } else { + var mg_result = MethodGroupExpr.CreatePredefined (get_result, fe_awaiter.Type, loc); + mg_result.InstanceExpression = fe_awaiter; - mg_result.EmitCall (ec, new Arguments (0)); + return new GetResultInvocation (mg_result, new Arguments (0)); + } } public void EmitPrologue (EmitContext ec) @@ -177,11 +213,35 @@ namespace Mono.CSharp // fe_awaiter.EmitAssign (ec, expr, false, false); - is_completed.InstanceExpression = fe_awaiter; - is_completed.EmitBranchable (ec, resume_point, true); + Label skip_continuation = ec.DefineLabel (); - var mg_completed = MethodGroupExpr.CreatePredefined (on_completed, fe_awaiter.Type, loc); - mg_completed.InstanceExpression = fe_awaiter; + Expression completed_expr; + if (IsDynamic) { + var rc = new ResolveContext (ec.MemberContext); + + Arguments dargs = new Arguments (1); + dargs.Add (new Argument (fe_awaiter)); + completed_expr = new DynamicMemberBinder ("IsCompleted", dargs, loc).Resolve (rc); + } else { + var pe = PropertyExpr.CreatePredefined (is_completed, loc); + pe.InstanceExpression = fe_awaiter; + completed_expr = pe; + } + + completed_expr.EmitBranchable (ec, skip_continuation, true); + + base.DoEmit (ec); + + // + // The stack has to be empty before calling await continuation. We handle this + // by lifting values which would be left on stack into class fields. The process + // is quite complicated and quite hard to test because any expression can possibly + // leave a value on the stack. + // + // Following assert fails when some of expression called before is missing EmitToField + // or parent expression fails to find await in children expressions + // + ec.AssertEmptyStack (); var args = new Arguments (1); var storey = (AsyncTaskStorey) machine_initializer.Storey; @@ -190,12 +250,27 @@ namespace Mono.CSharp args.Add (new Argument (fe_cont)); - // - // awaiter.OnCompleted (continuation); - // - mg_completed.EmitCall (ec, args); + if (IsDynamic) { + var rc = new ResolveContext (ec.MemberContext); + var mg_expr = new Invocation (new MemberAccess (fe_awaiter, "OnCompleted"), args).Resolve (rc); - base.DoEmit (ec); + ExpressionStatement es = (ExpressionStatement) mg_expr; + es.EmitStatement (ec); + } else { + var mg_completed = MethodGroupExpr.CreatePredefined (on_completed, fe_awaiter.Type, loc); + mg_completed.InstanceExpression = fe_awaiter; + + // + // awaiter.OnCompleted (continuation); + // + mg_completed.EmitCall (ec, args); + } + + // Return ok + machine_initializer.EmitLeave (ec, unwind_protect); + + ec.MarkLabel (resume_point); + ec.MarkLabel (skip_continuation); } public void EmitStatement (EmitContext ec) @@ -231,13 +306,21 @@ namespace Mono.CSharp if (!base.Resolve (bc)) return false; + Arguments args = new Arguments (0); + type = expr.Type; // - // The task result is of dynamic type + // The await expression is of dynamic type // - if (expr.Type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) - throw new NotImplementedException ("dynamic await"); + if (type.BuiltinType == BuiltinTypeSpec.Type.Dynamic) { + result_type = type; + + awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (type, loc); + + expr = new Invocation (new MemberAccess (expr, "GetAwaiter"), args).Resolve (bc); + return true; + } // // Check whether the expression is awaitable @@ -246,40 +329,28 @@ namespace Mono.CSharp if (ama == null) return false; - Arguments args = new Arguments (0); - var errors_printer = new SessionReportPrinter (); var old = bc.Report.SetPrinter (errors_printer); ama = new Invocation (ama, args).Resolve (bc); + bc.Report.SetPrinter (old); if (errors_printer.ErrorsCount > 0 || !MemberAccess.IsValidDotExpression (ama.Type)) { - bc.Report.SetPrinter (old); - Error_WrongGetAwaiter (bc, loc, expr.Type); + Error_WrongGetAwaiter (bc, expr.Location, expr.Type); return false; } var awaiter_type = ama.Type; awaiter = ((AsyncTaskStorey) machine_initializer.Storey).AddAwaiter (awaiter_type, loc); + expr = ama; // // Predefined: bool IsCompleted { get; } // - var is_completed_ma = new MemberAccess (expr, "IsCompleted").Resolve (bc); - if (is_completed_ma != null) { - is_completed = is_completed_ma as PropertyExpr; - if (is_completed != null && is_completed.Type.BuiltinType == BuiltinTypeSpec.Type.Bool && is_completed.IsInstance && is_completed.Getter != null) { - // valid - } else { - bc.Report.SetPrinter (old); - Error_WrongAwaiterPattern (bc, awaiter_type); - return false; - } - } - - bc.Report.SetPrinter (old); + is_completed = MemberCache.FindMember (awaiter_type, MemberFilter.Property ("IsCompleted", bc.Module.Compiler.BuiltinTypes.Bool), + BindingRestriction.InstanceOnly) as PropertySpec; - if (errors_printer.ErrorsCount > 0) { + if (is_completed == null || !is_completed.HasGet) { Error_WrongAwaiterPattern (bc, awaiter_type); return false; } @@ -312,6 +383,8 @@ namespace Mono.CSharp return false; } + result_type = get_result.ReturnType; + return true; } } @@ -353,7 +426,7 @@ namespace Mono.CSharp #endregion - public static void Create (ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc) + public static void Create (IMemberContext context, ParametersBlock block, ParametersCompiled parameters, TypeContainer host, TypeSpec returnType, Location loc) { if (returnType != null && returnType.Kind != MemberKind.Void && returnType != host.Module.PredefinedTypes.Task.TypeSpec && @@ -385,11 +458,12 @@ namespace Mono.CSharp } } - // TODO: Warning - //if (!block.HasAwait) { - //} + if (!block.IsAsync) { + host.Compiler.Report.Warning (1998, 1, loc, + "Async block lacks `await' operator and will run synchronously"); + } - block.WrapIntoAsyncTask (host, returnType); + block.WrapIntoAsyncTask (context, host, returnType); } protected override BlockContext CreateBlockContext (ResolveContext rc) @@ -399,6 +473,7 @@ namespace Mono.CSharp if (lambda != null) return_inference = lambda.ReturnTypeInference; + ctx.StartFlowBranching (this, rc.CurrentBranching); return ctx; } @@ -422,17 +497,31 @@ namespace Mono.CSharp { var storey = (AsyncTaskStorey) Storey; storey.Instance.Emit (ec); - ec.Emit (OpCodes.Call, storey.StateMachineMethod.Spec); + var move_next_entry = storey.StateMachineMethod.Spec; + if (storey.MemberName.Arity > 0) { + move_next_entry = MemberCache.GetMember (storey.Instance.Type, move_next_entry); + } + + ec.Emit (OpCodes.Call, move_next_entry); + + // + // Emits return .$builder.Task; + // if (storey.Task != null) { - // - // async.$builder.Task; - // + var builder_field = storey.Builder.Spec; + var task_get = storey.Task.Get; + + if (storey.MemberName.Arity > 0) { + builder_field = MemberCache.GetMember (storey.Instance.Type, builder_field); + task_get = MemberCache.GetMember (builder_field.MemberType, task_get); + } + var pe_task = new PropertyExpr (storey.Task, loc) { - InstanceExpression = new FieldExpr (storey.Builder, loc) { + InstanceExpression = new FieldExpr (builder_field, loc) { InstanceExpression = storey.Instance }, - Getter = storey.Task.Get + Getter = task_get }; pe_task.Emit (ec); @@ -440,33 +529,60 @@ namespace Mono.CSharp ec.Emit (OpCodes.Ret); } - - public override void InjectYield (EmitContext ec, Expression expr, int resume_pc, bool unwind_protect, Label resume_point) - { - base.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); - } } class AsyncTaskStorey : StateMachine { + sealed class ParametersLoadStatement : Statement + { + readonly FieldSpec[] fields; + readonly TypeSpec[] parametersTypes; + readonly int thisParameterIndex; + + public ParametersLoadStatement (FieldSpec[] fields, TypeSpec[] parametersTypes, int thisParameterIndex) + { + this.fields = fields; + this.parametersTypes = parametersTypes; + this.thisParameterIndex = thisParameterIndex; + } + + protected override void CloneTo (CloneContext clonectx, Statement target) + { + throw new NotImplementedException (); + } + + protected override void DoEmit (EmitContext ec) + { + for (int i = 0; i < fields.Length; ++i) { + var field = fields[i]; + if (field == null) + continue; + + ec.EmitArgumentLoad (thisParameterIndex); + ec.EmitArgumentLoad (i); + if (parametersTypes[i] is ReferenceContainer) + ec.EmitLoadFromPtr (field.MemberType); + + ec.Emit (OpCodes.Stfld, field); + } + } + } + int awaiters; Field builder, continuation; readonly TypeSpec return_type; MethodSpec set_result; + MethodSpec set_exception; PropertySpec task; LocalVariable hoisted_return; + int locals_captured; - public AsyncTaskStorey (AsyncInitializer initializer, TypeSpec type) - : base (initializer.OriginalBlock, initializer.Host, null, null, "async") + public AsyncTaskStorey (IMemberContext context, AsyncInitializer initializer, TypeSpec type) + : base (initializer.OriginalBlock, initializer.Host,context.CurrentMemberDefinition as MemberBase, context.CurrentTypeParameters, "async") { return_type = type; } - public Field AddAwaiter (TypeSpec type, Location loc) - { - return AddCompilerGeneratedField ("$awaiter" + awaiters++.ToString ("X"), new TypeExpression (type, loc)); - } - #region Properties public Field Builder { @@ -501,17 +617,34 @@ namespace Mono.CSharp #endregion + public Field AddAwaiter (TypeSpec type, Location loc) + { + return AddCompilerGeneratedField ("$awaiter" + awaiters++.ToString ("X"), new TypeExpression (type, loc), true); + } + + public Field AddCapturedLocalVariable (TypeSpec type) + { + if (mutator != null) + type = mutator.Mutate (type); + + var field = AddCompilerGeneratedField ("$" + locals_captured++.ToString ("X"), new TypeExpression (type, Location), true); + field.Define (); + + return field; + } + protected override bool DoDefineMembers () { var action = Module.PredefinedTypes.Action.Resolve (); if (action != null) { - continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location)); + continuation = AddCompilerGeneratedField ("$continuation", new TypeExpression (action, Location), true); continuation.ModFlags |= Modifiers.READONLY; } PredefinedType builder_type; PredefinedMember bf; PredefinedMember sr; + PredefinedMember se; bool has_task_return_type = false; var pred_members = Module.PredefinedMembers; @@ -519,32 +652,41 @@ namespace Mono.CSharp builder_type = Module.PredefinedTypes.AsyncVoidMethodBuilder; bf = pred_members.AsyncVoidMethodBuilderCreate; sr = pred_members.AsyncVoidMethodBuilderSetResult; + se = pred_members.AsyncVoidMethodBuilderSetException; } else if (return_type == Module.PredefinedTypes.Task.TypeSpec) { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilder; bf = pred_members.AsyncTaskMethodBuilderCreate; sr = pred_members.AsyncTaskMethodBuilderSetResult; + se = pred_members.AsyncTaskMethodBuilderSetException; task = pred_members.AsyncTaskMethodBuilderTask.Resolve (Location); } else { builder_type = Module.PredefinedTypes.AsyncTaskMethodBuilderGeneric; bf = pred_members.AsyncTaskMethodBuilderGenericCreate; sr = pred_members.AsyncTaskMethodBuilderGenericSetResult; + se = pred_members.AsyncTaskMethodBuilderGenericSetException; task = pred_members.AsyncTaskMethodBuilderGenericTask.Resolve (Location); has_task_return_type = true; } set_result = sr.Resolve (Location); + set_exception = se.Resolve (Location); var builder_factory = bf.Resolve (Location); var bt = builder_type.Resolve (); - if (bt == null || set_result == null || builder_factory == null) + if (bt == null || set_result == null || builder_factory == null || set_exception == null) return false; // // Inflate generic Task types // if (has_task_return_type) { - bt = bt.MakeGenericType (Module, return_type.TypeArguments); + var task_return_type = return_type.TypeArguments; + if (mutator != null) + task_return_type = mutator.Mutate (task_return_type); + + bt = bt.MakeGenericType (Module, task_return_type); builder_factory = MemberCache.GetMember (bt, builder_factory); set_result = MemberCache.GetMember (bt, set_result); + set_exception = MemberCache.GetMember (bt, set_exception); if (task != null) task = MemberCache.GetMember (bt, task); @@ -589,6 +731,22 @@ namespace Mono.CSharp return true; } + public void EmitSetException (EmitContext ec, LocalVariableReference exceptionVariable) + { + // + // $builder.SetException (Exception) + // + var mg = MethodGroupExpr.CreatePredefined (set_exception, set_exception.DeclaringType, Location); + mg.InstanceExpression = new FieldExpr (Builder, Location) { + InstanceExpression = new CompilerGeneratedThis (ec.CurrentType, Location) + }; + + Arguments args = new Arguments (1); + args.Add (new Argument (exceptionVariable)); + + mg.EmitCall (ec, args); + } + public void EmitSetResult (EmitContext ec) { // diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs index b58a81351..71c3b0663 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/attribute.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/attribute.cs @@ -82,7 +82,7 @@ namespace Mono.CSharp { public abstract string[] ValidAttributeTargets { get; } }; - public class Attribute : Expression + public class Attribute { public readonly string ExplicitTarget; public AttributeTargets Target; @@ -94,6 +94,8 @@ namespace Mono.CSharp { bool resolve_error; bool arg_resolved; readonly bool nameEscaped; + readonly Location loc; + public TypeSpec Type; // // An attribute can be attached to multiple targets (e.g. multiple fields) @@ -123,6 +125,12 @@ namespace Mono.CSharp { this.nameEscaped = nameEscaped; } + public Location Location { + get { + return loc; + } + } + void AddModuleCharSet (ResolveContext rc) { const string dll_import_char_set = "CharSet"; @@ -326,7 +334,7 @@ namespace Mono.CSharp { return Type; } - public override string GetSignatureForError () + public string GetSignatureForError () { if (Type != null) return TypeManager.CSharpName (Type); @@ -337,7 +345,7 @@ namespace Mono.CSharp { public bool HasSecurityAttribute { get { PredefinedAttribute pa = context.Module.PredefinedAttributes.Security; - return pa.IsDefined && TypeSpec.IsBaseClass (type, pa.TypeSpec, false); + return pa.IsDefined && TypeSpec.IsBaseClass (Type, pa.TypeSpec, false); } } @@ -468,7 +476,7 @@ namespace Mono.CSharp { } } - return ConstructorLookup (ec, Type, ref PosArguments, loc); + return Expression.ConstructorLookup (ec, Type, ref PosArguments, loc); } bool ResolveNamedArguments (ResolveContext ec) @@ -489,10 +497,10 @@ namespace Mono.CSharp { a.Resolve (ec); - Expression member = Expression.MemberLookup (ec, false, Type, name, 0, MemberLookupRestrictions.ExactArity, loc); + Expression member = Expression.MemberLookup (ec, false, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc); if (member == null) { - member = Expression.MemberLookup (ec, true, Type, name, 0, MemberLookupRestrictions.ExactArity, loc); + member = Expression.MemberLookup (ec, true, Type, name, 0, Expression.MemberLookupRestrictions.ExactArity, loc); if (member != null) { // TODO: ec.Report.SymbolRelatedToPreviousError (member); @@ -680,7 +688,7 @@ namespace Mono.CSharp { { if (!arg_resolved) { // corlib only case when obsolete is used before is resolved - var c = type.MemberDefinition as Class; + var c = Type.MemberDefinition as Class; if (c != null && !c.HasMembersDefined) c.Define (); @@ -919,7 +927,7 @@ namespace Mono.CSharp { public override int GetHashCode () { - return type.GetHashCode () ^ Target.GetHashCode (); + return Type.GetHashCode () ^ Target.GetHashCode (); } /// @@ -1087,21 +1095,6 @@ namespace Mono.CSharp { return null; return e.TypeArgument; } - - public override Expression CreateExpressionTree (ResolveContext ec) - { - throw new NotSupportedException ("ET"); - } - - protected override Expression DoResolve (ResolveContext ec) - { - throw new NotImplementedException (); - } - - public override void Emit (EmitContext ec) - { - throw new NotImplementedException (); - } } public class Attributes diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/cfold.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/cfold.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/cfold.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs index 83fbea0b3..3959f351b 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/class.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/class.cs @@ -99,7 +99,7 @@ namespace Mono.CSharp return tc.GetSignatureForError (); } - public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) { return null; } @@ -319,6 +319,12 @@ namespace Mono.CSharp } } + public TypeSpec[] Interfaces { + get { + return iface_exprs; + } + } + #endregion public override void Accept (StructuralVisitor visitor) @@ -756,7 +762,7 @@ namespace Mono.CSharp ExpressionStatement s = fi.ResolveStatement (ec); if (s == null) { s = EmptyExpressionStatement.Instance; - } else if (fi.IsComplexInitializer) { + } else if (!fi.IsSideEffectFree) { has_complex_initializer |= true; } @@ -2455,18 +2461,19 @@ namespace Mono.CSharp } } - public override IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + public override ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) { DeclSpace top_level = Parent; if (top_level != null) { - var candidates = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity); - if (candidates != null) { - scope = NamespaceEntry; - return candidates; + var methods = NamespaceEntry.NS.LookupExtensionMethod (this, extensionType, name, arity); + if (methods != null) { + return new ExtensionMethodCandidates (methods, NamespaceEntry, NamespaceEntry.NS) { + HasUninspectedMembers = true + }; } } - return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity, ref scope); + return NamespaceEntry.LookupExtensionMethod (extensionType, name, arity); } protected override TypeAttributes TypeAttr { @@ -2805,7 +2812,10 @@ namespace Mono.CSharp } } - if ((field.IsStatic && (!ftype.IsGeneric || ftype == CurrentType))) + // + // Static fields of exactly same type are allowed + // + if (field.IsStatic && ftype == s.CurrentType) continue; if (!CheckFieldTypeCycle (ftype)) { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs similarity index 60% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs index abd114d2f..8764c79fe 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/codegen.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/codegen.cs @@ -51,16 +51,6 @@ namespace Mono.CSharp /// public LocalBuilder return_value; - /// - /// The location where return has to jump to return the - /// value - /// - public Label ReturnLabel; - - /// - /// If we already defined the ReturnLabel - /// - public bool HasReturnLabel; /// /// Current loop begin and end labels. @@ -87,13 +77,17 @@ namespace Mono.CSharp DynamicSiteClass dynamic_site_container; + Label? return_label; + public EmitContext (IMemberContext rc, ILGenerator ig, TypeSpec return_type) { this.member_context = rc; this.ig = ig; - this.return_type = return_type; + if (rc.Module.Compiler.Settings.Checked) + flags |= Options.CheckedScope; + #if STATIC ig.__CleverExceptionBlockAssistance (); #endif @@ -101,6 +95,12 @@ namespace Mono.CSharp #region Properties + internal AsyncTaskStorey AsyncTaskStorey { + get { + return CurrentAnonymousMethod.Storey as AsyncTaskStorey; + } + } + public BuiltinTypes BuiltinTypes { get { return MemberContext.Module.Compiler.BuiltinTypes; @@ -119,6 +119,12 @@ namespace Mono.CSharp get { return member_context.CurrentMemberDefinition; } } + public bool HasReturnLabel { + get { + return return_label.HasValue; + } + } + public bool IsStatic { get { return member_context.IsStatic; } } @@ -156,8 +162,27 @@ namespace Mono.CSharp return return_type; } } + + // + // The label where we have to jump before leaving the context + // + public Label ReturnLabel { + get { + return return_label.Value; + } + } + #endregion + public void AssertEmptyStack () + { +#if STATIC + if (ig.__StackHeight != 0) + throw new InternalErrorException ("Await yields with non-empty stack in `{0}", + member_context.GetSignatureForError ()); +#endif + } + /// /// This is called immediately before emitting an IL opcode to tell the symbol /// writer to which source line this opcode belongs. @@ -228,6 +253,14 @@ namespace Mono.CSharp return dynamic_site_container; } + public Label CreateReturnLabel () + { + if (!return_label.HasValue) + return_label = DefineLabel (); + + return return_label.Value; + } + public LocalBuilder DeclareLocal (TypeSpec type, bool pinned) { if (IsAnonymousStoreyMutateRequired) @@ -241,6 +274,17 @@ namespace Mono.CSharp return ig.DefineLabel (); } + // + // Creates temporary field in current async storey + // + public FieldExpr GetTemporaryField (TypeSpec type) + { + var f = AsyncTaskStorey.AddCapturedLocalVariable (type); + var fexpr = new FieldExpr (f, Location.Null); + fexpr.InstanceExpression = new CompilerGeneratedThis (CurrentType, Location.Null); + return fexpr; + } + public void MarkLabel (Label label) { ig.MarkLabel (label); @@ -271,16 +315,6 @@ namespace Mono.CSharp ig.Emit (opcode, arg); } - public void Emit (OpCode opcode, int arg) - { - ig.Emit (opcode, arg); - } - - public void Emit (OpCode opcode, byte arg) - { - ig.Emit (opcode, arg); - } - public void Emit (OpCode opcode, Label label) { ig.Emit (opcode, label); @@ -333,7 +367,11 @@ namespace Mono.CSharp public void EmitArrayNew (ArrayContainer ac) { if (ac.Rank == 1) { - Emit (OpCodes.Newarr, ac.Element); + var type = IsAnonymousStoreyMutateRequired ? + CurrentAnonymousMethod.Storey.Mutator.Mutate (ac.Element) : + ac.Element; + + ig.Emit (OpCodes.Newarr, type.GetMetaInfo ()); } else { if (IsAnonymousStoreyMutateRequired) ac = (ArrayContainer) ac.Mutate (CurrentAnonymousMethod.Storey.Mutator); @@ -350,7 +388,11 @@ namespace Mono.CSharp ig.Emit (OpCodes.Call, ac.GetAddressMethod ()); } else { - Emit (OpCodes.Ldelema, ac.Element); + var type = IsAnonymousStoreyMutateRequired ? + CurrentAnonymousMethod.Storey.Mutator.Mutate (ac.Element) : + ac.Element; + + ig.Emit (OpCodes.Ldelema, type.GetMetaInfo ()); } } @@ -367,6 +409,7 @@ namespace Mono.CSharp return; } + var type = ac.Element; if (type.Kind == MemberKind.Enum) type = EnumSpec.GetUnderlyingType (type); @@ -374,52 +417,59 @@ namespace Mono.CSharp switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Byte: case BuiltinTypeSpec.Type.Bool: - Emit (OpCodes.Ldelem_U1); - return; + ig.Emit (OpCodes.Ldelem_U1); + break; case BuiltinTypeSpec.Type.SByte: - Emit (OpCodes.Ldelem_I1); - return; + ig.Emit (OpCodes.Ldelem_I1); + break; case BuiltinTypeSpec.Type.Short: - Emit (OpCodes.Ldelem_I2); - return; + ig.Emit (OpCodes.Ldelem_I2); + break; case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Char: - Emit (OpCodes.Ldelem_U2); - return; + ig.Emit (OpCodes.Ldelem_U2); + break; case BuiltinTypeSpec.Type.Int: - Emit (OpCodes.Ldelem_I4); - return; + ig.Emit (OpCodes.Ldelem_I4); + break; case BuiltinTypeSpec.Type.UInt: - Emit (OpCodes.Ldelem_U4); - return; + ig.Emit (OpCodes.Ldelem_U4); + break; case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.Long: - Emit (OpCodes.Ldelem_I8); - return; + ig.Emit (OpCodes.Ldelem_I8); + break; case BuiltinTypeSpec.Type.Float: - Emit (OpCodes.Ldelem_R4); - return; - case BuiltinTypeSpec.Type.Double: - Emit (OpCodes.Ldelem_R8); - return; - case BuiltinTypeSpec.Type.IntPtr: - Emit (OpCodes.Ldelem_I); - return; - } - - switch (type.Kind) { - case MemberKind.Struct: - Emit (OpCodes.Ldelema, type); - Emit (OpCodes.Ldobj, type); + ig.Emit (OpCodes.Ldelem_R4); break; - case MemberKind.TypeParameter: - Emit (OpCodes.Ldelem, type); + case BuiltinTypeSpec.Type.Double: + ig.Emit (OpCodes.Ldelem_R8); break; - case MemberKind.PointerType: - Emit (OpCodes.Ldelem_I); + case BuiltinTypeSpec.Type.IntPtr: + ig.Emit (OpCodes.Ldelem_I); break; default: - Emit (OpCodes.Ldelem_Ref); + switch (type.Kind) { + case MemberKind.Struct: + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + ig.Emit (OpCodes.Ldelema, type.GetMetaInfo ()); + ig.Emit (OpCodes.Ldobj, type.GetMetaInfo ()); + break; + case MemberKind.TypeParameter: + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + ig.Emit (OpCodes.Ldelem, type.GetMetaInfo ()); + break; + case MemberKind.PointerType: + ig.Emit (OpCodes.Ldelem_I); + break; + default: + ig.Emit (OpCodes.Ldelem_Ref); + break; + } break; } } @@ -486,6 +536,11 @@ namespace Mono.CSharp } public void EmitInt (int i) + { + EmitIntConstant (i); + } + + void EmitIntConstant (int i) { switch (i) { case -1: @@ -540,18 +595,14 @@ namespace Mono.CSharp public void EmitLong (long l) { if (l >= int.MinValue && l <= int.MaxValue) { - EmitInt (unchecked ((int) l)); + EmitIntConstant (unchecked ((int) l)); ig.Emit (OpCodes.Conv_I8); - return; - } - - if (l >= 0 && l <= uint.MaxValue) { - EmitInt (unchecked ((int) l)); + } else if (l >= 0 && l <= uint.MaxValue) { + EmitIntConstant (unchecked ((int) l)); ig.Emit (OpCodes.Conv_U8); - return; + } else { + ig.Emit (OpCodes.Ldc_I8, l); } - - ig.Emit (OpCodes.Ldc_I8, l); } // @@ -565,53 +616,103 @@ namespace Mono.CSharp switch (type.BuiltinType) { case BuiltinTypeSpec.Type.Int: ig.Emit (OpCodes.Ldind_I4); - return; + break; case BuiltinTypeSpec.Type.UInt: ig.Emit (OpCodes.Ldind_U4); - return; + break; case BuiltinTypeSpec.Type.Short: ig.Emit (OpCodes.Ldind_I2); - return; + break; case BuiltinTypeSpec.Type.UShort: case BuiltinTypeSpec.Type.Char: ig.Emit (OpCodes.Ldind_U2); - return; + break; case BuiltinTypeSpec.Type.Byte: ig.Emit (OpCodes.Ldind_U1); - return; + break; case BuiltinTypeSpec.Type.SByte: case BuiltinTypeSpec.Type.Bool: ig.Emit (OpCodes.Ldind_I1); - return; + break; case BuiltinTypeSpec.Type.ULong: case BuiltinTypeSpec.Type.Long: ig.Emit (OpCodes.Ldind_I8); - return; + break; case BuiltinTypeSpec.Type.Float: ig.Emit (OpCodes.Ldind_R4); - return; + break; case BuiltinTypeSpec.Type.Double: ig.Emit (OpCodes.Ldind_R8); - return; + break; case BuiltinTypeSpec.Type.IntPtr: ig.Emit (OpCodes.Ldind_I); - return; - } - - switch (type.Kind) { - case MemberKind.Struct: - case MemberKind.TypeParameter: - Emit (OpCodes.Ldobj, type); break; - case MemberKind.PointerType: - ig.Emit (OpCodes.Ldind_I); + default: + switch (type.Kind) { + case MemberKind.Struct: + case MemberKind.TypeParameter: + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + ig.Emit (OpCodes.Ldobj, type.GetMetaInfo ()); + break; + case MemberKind.PointerType: + ig.Emit (OpCodes.Ldind_I); + break; + default: + ig.Emit (OpCodes.Ldind_Ref); + break; + } break; + } + } + + public void EmitNull () + { + ig.Emit (OpCodes.Ldnull); + } + + public void EmitArgumentAddress (int pos) + { + if (!IsStatic) + ++pos; + + if (pos > byte.MaxValue) + ig.Emit (OpCodes.Ldarga, pos); + else + ig.Emit (OpCodes.Ldarga_S, (byte) pos); + } + + public void EmitArgumentLoad (int pos) + { + if (!IsStatic) + ++pos; + + switch (pos) { + case 0: ig.Emit (OpCodes.Ldarg_0); break; + case 1: ig.Emit (OpCodes.Ldarg_1); break; + case 2: ig.Emit (OpCodes.Ldarg_2); break; + case 3: ig.Emit (OpCodes.Ldarg_3); break; default: - ig.Emit (OpCodes.Ldind_Ref); + if (pos > byte.MaxValue) + ig.Emit (OpCodes.Ldarg, pos); + else + ig.Emit (OpCodes.Ldarg_S, (byte) pos); break; } } + public void EmitArgumentStore (int pos) + { + if (!IsStatic) + ++pos; + + if (pos > byte.MaxValue) + ig.Emit (OpCodes.Starg, pos); + else + ig.Emit (OpCodes.Starg_S, (byte) pos); + } + // // The stack contains the pointer and the value of type `type' // @@ -650,10 +751,23 @@ namespace Mono.CSharp return; } - if (type.IsStruct || TypeManager.IsGenericParameter (type)) - Emit (OpCodes.Stobj, type); - else + switch (type.Kind) { + case MemberKind.Struct: + case MemberKind.TypeParameter: + if (IsAnonymousStoreyMutateRequired) + type = CurrentAnonymousMethod.Storey.Mutator.Mutate (type); + + ig.Emit (OpCodes.Stobj, type.GetMetaInfo ()); + break; + default: ig.Emit (OpCodes.Stind_Ref); + break; + } + } + + public void EmitThis () + { + ig.Emit (OpCodes.Ldarg_0); } /// @@ -716,13 +830,203 @@ namespace Mono.CSharp { if (return_value == null){ return_value = DeclareLocal (return_type, false); - if (!HasReturnLabel){ - ReturnLabel = DefineLabel (); - HasReturnLabel = true; - } } return return_value; } } + + struct CallEmitter + { + public Expression InstanceExpression; + + // + // When set leaves an extra copy of all arguments on the stack + // + public bool DuplicateArguments; + + // + // Does not emit InstanceExpression load when InstanceExpressionOnStack + // is set. Used by compound assignments. + // + public bool InstanceExpressionOnStack; + + // + // Any of arguments contains await expression + // + public bool HasAwaitArguments; + + // + // When dealing with await arguments the original arguments are converted + // into a new set with hoisted stack results + // + public Arguments EmittedArguments; + + public void Emit (EmitContext ec, MethodSpec method, Arguments Arguments, Location loc) + { + // Speed up the check by not doing it on not allowed targets + if (method.ReturnType.Kind == MemberKind.Void && method.IsConditionallyExcluded (ec.Module.Compiler, loc)) + return; + + EmitPredefined (ec, method, Arguments); + } + + public void EmitPredefined (EmitContext ec, MethodSpec method, Arguments Arguments) + { + Expression instance_copy = null; + + if (!HasAwaitArguments && ec.HasSet (BuilderContext.Options.AsyncBody)) { + HasAwaitArguments = Arguments != null && Arguments.ContainsEmitWithAwait (); + if (HasAwaitArguments && InstanceExpressionOnStack) { + throw new NotSupportedException (); + } + } + + OpCode call_op; + LocalTemporary lt = null; + + if (method.IsStatic) { + call_op = OpCodes.Call; + } else { + if (IsVirtualCallRequired (InstanceExpression, method)) { + call_op = OpCodes.Callvirt; + } else { + call_op = OpCodes.Call; + } + + if (HasAwaitArguments) { + instance_copy = InstanceExpression.EmitToField (ec); + if (Arguments == null) + EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op); + } else if (!InstanceExpressionOnStack) { + var instance_on_stack_type = EmitCallInstance (ec, InstanceExpression, method.DeclaringType, call_op); + + if (DuplicateArguments) { + ec.Emit (OpCodes.Dup); + if (Arguments != null && Arguments.Count != 0) { + lt = new LocalTemporary (instance_on_stack_type); + lt.Store (ec); + instance_copy = lt; + } + } + } + } + + if (Arguments != null && !InstanceExpressionOnStack) { + EmittedArguments = Arguments.Emit (ec, DuplicateArguments, HasAwaitArguments); + if (EmittedArguments != null) { + if (instance_copy != null) { + EmitCallInstance (ec, instance_copy, method.DeclaringType, call_op); + + if (lt != null) + lt.Release (ec); + } + + EmittedArguments.Emit (ec); + } + } + + if (call_op == OpCodes.Callvirt && (InstanceExpression.Type.IsGenericParameter || InstanceExpression.Type.IsStruct)) { + ec.Emit (OpCodes.Constrained, InstanceExpression.Type); + } + + // + // Set instance expression to actual result expression. When it contains await it can be + // picked up by caller + // + InstanceExpression = instance_copy; + + if (method.Parameters.HasArglist) { + var varargs_types = GetVarargsTypes (method, Arguments); + ec.Emit (call_op, method, varargs_types); + return; + } + + // + // If you have: + // this.DoFoo (); + // and DoFoo is not virtual, you can omit the callvirt, + // because you don't need the null checking behavior. + // + ec.Emit (call_op, method); + } + + static TypeSpec EmitCallInstance (EmitContext ec, Expression instance, TypeSpec declaringType, OpCode callOpcode) + { + var instance_type = instance.Type; + + // + // Push the instance expression + // + if ((instance_type.IsStruct && (callOpcode == OpCodes.Callvirt || (callOpcode == OpCodes.Call && declaringType == instance_type))) || + instance_type.IsGenericParameter || declaringType.IsNullableType) { + // + // If the expression implements IMemoryLocation, then + // we can optimize and use AddressOf on the + // return. + // + // If not we have to use some temporary storage for + // it. + var iml = instance as IMemoryLocation; + if (iml != null) { + iml.AddressOf (ec, AddressOp.Load); + } else { + LocalTemporary temp = new LocalTemporary (instance_type); + instance.Emit (ec); + temp.Store (ec); + temp.AddressOf (ec, AddressOp.Load); + temp.Release (ec); + } + + return ReferenceContainer.MakeType (ec.Module, instance_type); + } + + if (instance_type.IsEnum || instance_type.IsStruct) { + instance.Emit (ec); + ec.Emit (OpCodes.Box, instance_type); + return ec.BuiltinTypes.Object; + } + + instance.Emit (ec); + return instance_type; + } + + static MetaType[] GetVarargsTypes (MethodSpec method, Arguments arguments) + { + AParametersCollection pd = method.Parameters; + + Argument a = arguments[pd.Count - 1]; + Arglist list = (Arglist) a.Expr; + + return list.ArgumentTypes; + } + + // + // Used to decide whether call or callvirt is needed + // + static bool IsVirtualCallRequired (Expression instance, MethodSpec method) + { + // + // There are 2 scenarious where we emit callvirt + // + // Case 1: A method is virtual and it's not used to call base + // Case 2: A method instance expression can be null. In this casen callvirt ensures + // correct NRE exception when the method is called + // + var decl_type = method.DeclaringType; + if (decl_type.IsStruct || decl_type.IsEnum) + return false; + + if (instance is BaseThis) + return false; + + // + // It's non-virtual and will never be null + // + if (!method.IsVirtual && (instance is This || instance is New || instance is ArrayCreation || instance is DelegateCreation)) + return false; + + return true; + } + } } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc b/ICSharpCode.NRefactory.CSharp/Parser/mcs/compiler.doc similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/compiler.doc rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/compiler.doc diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/complete.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/complete.cs index 965416e79..a8641784e 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/complete.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/complete.cs @@ -43,19 +43,24 @@ namespace Mono.CSharp { } } - public override void EmitStatement (EmitContext ec) + public override bool ContainsEmitWithAwait () { - // Do nothing + return false; } - public override void Emit (EmitContext ec) + public override Expression CreateExpressionTree (ResolveContext ec) + { + return null; + } + + public override void EmitStatement (EmitContext ec) { // Do nothing } - public override Expression CreateExpressionTree (ResolveContext ec) + public override void Emit (EmitContext ec) { - return null; + // Do nothing } } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/const.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/const.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/const.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs index 2848e46a7..b00fee56c 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/constant.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/constant.cs @@ -78,6 +78,11 @@ namespace Mono.CSharp { return c; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public virtual Constant ConvertImplicitly (TypeSpec type) { if (this.type == type) @@ -309,7 +314,13 @@ namespace Mono.CSharp { public virtual bool IsOneInteger { get { return false; } - } + } + + public override bool IsSideEffectFree { + get { + return true; + } + } // // Returns true iff 1) the stack type of this is one of Object, @@ -427,9 +438,9 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { if (Value) - ec.Emit (OpCodes.Ldc_I4_1); + ec.EmitInt (1); else - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); } public override bool IsDefaultValue { @@ -1945,7 +1956,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { if (Value == null) { - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); return; } @@ -2050,7 +2061,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); // Only to make verifier happy if (type.IsGenericParameter) @@ -2152,7 +2163,7 @@ namespace Mono.CSharp { // // Emits null pointer // - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.Emit (OpCodes.Conv_U); } } @@ -2162,7 +2173,8 @@ namespace Mono.CSharp { /// used by BitwiseAnd to ensure that the second expression is invoked /// regardless of the value of the left side. /// - public class SideEffectConstant : Constant { + public class SideEffectConstant : Constant + { public readonly Constant value; Expression side_effect; @@ -2178,6 +2190,12 @@ namespace Mono.CSharp { this.side_effect = side_effect; } + public override bool IsSideEffectFree { + get { + return false; + } + } + public override object GetValue () { return value.GetValue (); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs similarity index 91% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs index 316968454..06c64500d 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/context.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/context.cs @@ -7,18 +7,13 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc. // Copyright 2004-2009 Novell, Inc. +// Copyright 2011 Xamarin Inc. // using System; using System.Collections.Generic; using System.IO; -#if STATIC -using IKVM.Reflection.Emit; -#else -using System.Reflection.Emit; -#endif - namespace Mono.CSharp { public enum LookupMode @@ -58,7 +53,7 @@ namespace Mono.CSharp string GetSignatureForError (); - IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope); + ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity); FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc); FullNamedExpression LookupNamespaceAlias (string name); } @@ -75,18 +70,7 @@ namespace Mono.CSharp { FlowBranching current_flow_branching; - TypeSpec return_type; - - /// - /// The location where return has to jump to return the - /// value - /// - public Label ReturnLabel; // TODO: It's emit dependant - - /// - /// If we already defined the ReturnLabel - /// - public bool HasReturnLabel; + readonly TypeSpec return_type; public int FlowOffset; @@ -116,6 +100,10 @@ namespace Mono.CSharp get { return current_flow_branching; } } + public TypeSpec ReturnType { + get { return return_type; } + } + // // Starts a new code branching. This inherits the state of all local // variables and parameters from the current branching. @@ -145,9 +133,9 @@ namespace Mono.CSharp return branching; } - public FlowBranchingException StartFlowBranching (ExceptionStatement stmt) + public FlowBranchingTryFinally StartFlowBranching (TryFinallyBlock stmt) { - FlowBranchingException branching = new FlowBranchingException (CurrentBranching, stmt); + FlowBranchingTryFinally branching = new FlowBranchingTryFinally (CurrentBranching, stmt); current_flow_branching = branching; return branching; } @@ -159,13 +147,20 @@ namespace Mono.CSharp return branching; } - public FlowBranchingIterator StartFlowBranching (StateMachineInitializer iterator, FlowBranching parent) + public FlowBranchingIterator StartFlowBranching (Iterator iterator, FlowBranching parent) { FlowBranchingIterator branching = new FlowBranchingIterator (parent, iterator); current_flow_branching = branching; return branching; } + public FlowBranchingAsync StartFlowBranching (AsyncInitializer asyncBody, FlowBranching parent) + { + var branching = new FlowBranchingAsync (parent, asyncBody); + current_flow_branching = branching; + return branching; + } + public FlowBranchingToplevel StartFlowBranching (ParametersBlock stmt, FlowBranching parent) { FlowBranchingToplevel branching = new FlowBranchingToplevel (parent, stmt); @@ -196,19 +191,11 @@ namespace Mono.CSharp current_flow_branching = current_flow_branching.Parent; } - // - // This method is used during the Resolution phase to flag the - // need to define the ReturnLabel - // +#if !STATIC public void NeedReturnLabel () { - if (!HasReturnLabel) - HasReturnLabel = true; - } - - public TypeSpec ReturnType { - get { return return_type; } } +#endif } // @@ -484,7 +471,7 @@ namespace Mono.CSharp // FIXME: IsIterator is too aggressive, we should capture only if child // block contains yield - if (CurrentAnonymousMethod.IsIterator) + if (CurrentAnonymousMethod.IsIterator || CurrentAnonymousMethod is AsyncInitializer) return true; return local.Block.ParametersBlock != CurrentBlock.ParametersBlock.Original; @@ -519,9 +506,9 @@ namespace Mono.CSharp return MemberContext.GetSignatureForError (); } - public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) { - return MemberContext.LookupExtensionMethod (extensionType, name, arity, ref scope); + return MemberContext.LookupExtensionMethod (extensionType, name, arity); } public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) @@ -685,18 +672,11 @@ namespace Mono.CSharp /// CheckedScope = 1 << 0, - /// - /// The constant check state is always set to `true' and cant be changed - /// from the command line. The source code can change this setting with - /// the `checked' and `unchecked' statements and expressions. - /// - ConstantCheckState = 1 << 1, - - AllCheckStateFlags = CheckedScope | ConstantCheckState, - OmitDebugInfo = 1 << 2, - ConstructorScope = 1 << 3 + ConstructorScope = 1 << 3, + + AsyncBody = 1 << 4 } // utility helper for CheckExpr, UnCheckExpr, Checked and Unchecked statements @@ -725,7 +705,7 @@ namespace Mono.CSharp } } - Options flags; + protected Options flags; public bool HasSet (Options options) { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs index 020c84275..73361860f 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/convert.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/convert.cs @@ -8,6 +8,7 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc. // Copyright 2003-2008 Novell, Inc. +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // using System; @@ -198,7 +199,7 @@ namespace Mono.CSharp { return ImplicitReferenceConversionExists (expr_type, target_type, true); } - static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter) + public static bool ImplicitReferenceConversionExists (TypeSpec expr_type, TypeSpec target_type, bool refOnlyTypeParameter) { // It's here only to speed things up if (target_type.IsStruct) diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs similarity index 65% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs index 0cee24dd0..ab4fdfce2 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.cs @@ -4,14 +4,15 @@ // // cs-parser.jay: The Parser for the C# compiler // -// Authors: Miguel de Icaza (miguel@gnu.org) +// Authors: Miguel de Icaza (miguel@gnome.org) // Ravi Pratap (ravi@ximian.com) -// Marek Safar (marek.safar@gmail.com) +// Marek Safar (marek.safar@gmail.com) // // Dual Licensed under the terms of the GNU GPL and the MIT X11 license // // (C) 2001 Ximian, Inc (http://www.ximian.com) -// (C) 2004 Novell, Inc +// (C) 2004-2011 Novell, Inc +// Copyright 2011 Xamarin Inc. // // TODO: // (1) Figure out why error productions dont work. `type-declaration' is a @@ -145,8 +146,12 @@ namespace Mono.CSharp UsingsBag ubag; List> mod_locations; Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation; - Location savedAttrParenOpenLocation, savedAttrParenCloseLocation; + Location savedAttrParenOpenLocation, savedAttrParenCloseLocation, savedOperatorLocation; Stack> locationListStack = new Stack> (); // used for type parameters + List attributeCommas = new List (); + List attributeArgumentCommas = new List (); + List parameterListCommas = new List (); + List enumCommas = new List (); object lastYYVal; @@ -302,24 +307,9 @@ namespace Mono.CSharp //t "$$9 :", //t "$$10 :", //t "$$11 :", -//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$8 type_declaration_name $$9 opt_class_base opt_type_parameter_constraints_clauses $$10 struct_body $$11 opt_semicolon", -//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT error", //t "$$12 :", -//t "struct_body : OPEN_BRACE $$12 opt_struct_member_declarations CLOSE_BRACE", -//t "opt_struct_member_declarations :", -//t "opt_struct_member_declarations : struct_member_declarations", -//t "struct_member_declarations : struct_member_declaration", -//t "struct_member_declarations : struct_member_declarations struct_member_declaration", -//t "struct_member_declaration : constant_declaration", -//t "struct_member_declaration : field_declaration", -//t "struct_member_declaration : method_declaration", -//t "struct_member_declaration : property_declaration", -//t "struct_member_declaration : event_declaration", -//t "struct_member_declaration : indexer_declaration", -//t "struct_member_declaration : operator_declaration", -//t "struct_member_declaration : constructor_declaration", -//t "struct_member_declaration : type_declaration", -//t "struct_member_declaration : destructor_declaration", +//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT $$8 type_declaration_name $$9 opt_class_base opt_type_parameter_constraints_clauses $$10 OPEN_BRACE $$11 opt_class_member_declarations CLOSE_BRACE $$12 opt_semicolon", +//t "struct_declaration : opt_attributes opt_modifiers opt_partial STRUCT error", //t "$$13 :", //t "constant_declaration : opt_attributes opt_modifiers CONST type IDENTIFIER $$13 constant_initializer opt_constant_declarators SEMICOLON", //t "opt_constant_declarators :", @@ -525,7 +515,8 @@ namespace Mono.CSharp //t "$$56 :", //t "$$57 :", //t "$$58 :", -//t "enum_declaration : opt_attributes opt_modifiers ENUM type_declaration_name opt_enum_base $$56 OPEN_BRACE $$57 opt_enum_member_declarations $$58 CLOSE_BRACE opt_semicolon", +//t "$$59 :", +//t "enum_declaration : opt_attributes opt_modifiers ENUM $$56 type_declaration_name opt_enum_base $$57 OPEN_BRACE $$58 opt_enum_member_declarations $$59 CLOSE_BRACE opt_semicolon", //t "opt_enum_base :", //t "opt_enum_base : COLON type", //t "opt_enum_base : COLON error", @@ -535,12 +526,12 @@ namespace Mono.CSharp //t "enum_member_declarations : enum_member_declaration", //t "enum_member_declarations : enum_member_declarations COMMA enum_member_declaration", //t "enum_member_declaration : opt_attributes IDENTIFIER", -//t "$$59 :", -//t "enum_member_declaration : opt_attributes IDENTIFIER $$59 ASSIGN constant_expression", //t "$$60 :", +//t "enum_member_declaration : opt_attributes IDENTIFIER $$60 ASSIGN constant_expression", //t "$$61 :", //t "$$62 :", -//t "delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$60 opt_formal_parameter_list CLOSE_PARENS $$61 opt_type_parameter_constraints_clauses $$62 SEMICOLON", +//t "$$63 :", +//t "delegate_declaration : opt_attributes opt_modifiers DELEGATE member_type type_declaration_name OPEN_PARENS $$61 opt_formal_parameter_list CLOSE_PARENS $$62 opt_type_parameter_constraints_clauses $$63 SEMICOLON", //t "opt_nullable :", //t "opt_nullable : INTERR_NULLABLE", //t "namespace_or_type_name : member_name", @@ -553,8 +544,8 @@ namespace Mono.CSharp //t "opt_type_argument_list : OP_GENERICS_LT error", //t "type_arguments : type", //t "type_arguments : type_arguments COMMA type", -//t "$$63 :", -//t "type_declaration_name : IDENTIFIER $$63 opt_type_parameter_list", +//t "$$64 :", +//t "type_declaration_name : IDENTIFIER $$64 opt_type_parameter_list", //t "member_declaration_name : method_declaration_name", //t "method_declaration_name : type_declaration_name", //t "method_declaration_name : explicit_interface IDENTIFIER opt_type_parameter_list", @@ -700,8 +691,8 @@ namespace Mono.CSharp //t "array_creation_expression : NEW rank_specifier array_initializer", //t "array_creation_expression : NEW new_expr_type OPEN_BRACKET CLOSE_BRACKET OPEN_BRACKET_EXPR error CLOSE_BRACKET", //t "array_creation_expression : NEW new_expr_type error", -//t "$$64 :", -//t "new_expr_type : $$64 simple_type", +//t "$$65 :", +//t "new_expr_type : $$65 simple_type", //t "anonymous_type_expression : NEW OPEN_BRACE anonymous_type_parameters_opt_comma CLOSE_BRACE", //t "anonymous_type_parameters_opt_comma : anonymous_type_parameters_opt", //t "anonymous_type_parameters_opt_comma : anonymous_type_parameters COMMA", @@ -727,8 +718,8 @@ namespace Mono.CSharp //t "array_initializer : OPEN_BRACE variable_initializer_list opt_comma CLOSE_BRACE", //t "variable_initializer_list : variable_initializer", //t "variable_initializer_list : variable_initializer_list COMMA variable_initializer", -//t "$$65 :", -//t "typeof_expression : TYPEOF $$65 open_parens_any typeof_type_expression CLOSE_PARENS", +//t "$$66 :", +//t "typeof_expression : TYPEOF $$66 open_parens_any typeof_type_expression CLOSE_PARENS", //t "typeof_type_expression : type_and_void", //t "typeof_type_expression : unbound_type_name", //t "typeof_type_expression : error", @@ -743,14 +734,14 @@ namespace Mono.CSharp //t "checked_expression : CHECKED open_parens_any expression CLOSE_PARENS", //t "unchecked_expression : UNCHECKED open_parens_any expression CLOSE_PARENS", //t "pointer_member_access : primary_expression OP_PTR IDENTIFIER opt_type_argument_list", -//t "$$66 :", -//t "anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$66 block", //t "$$67 :", -//t "anonymous_method_expression : ASYNC DELEGATE opt_anonymous_method_signature $$67 block", +//t "anonymous_method_expression : DELEGATE opt_anonymous_method_signature $$67 block", +//t "$$68 :", +//t "anonymous_method_expression : ASYNC DELEGATE opt_anonymous_method_signature $$68 block", //t "opt_anonymous_method_signature :", //t "opt_anonymous_method_signature : anonymous_method_signature", -//t "$$68 :", -//t "anonymous_method_signature : OPEN_PARENS $$68 opt_formal_parameter_list CLOSE_PARENS", +//t "$$69 :", +//t "anonymous_method_signature : OPEN_PARENS $$69 opt_formal_parameter_list CLOSE_PARENS", //t "default_value_expression : DEFAULT open_parens_any type CLOSE_PARENS", //t "unary_expression : primary_expression", //t "unary_expression : BANG prefixed_unary_expression", @@ -821,20 +812,20 @@ namespace Mono.CSharp //t "opt_lambda_parameter_list : lambda_parameter_list", //t "lambda_expression_body : lambda_expression_body_simple", //t "lambda_expression_body : block", -//t "$$69 :", -//t "lambda_expression_body_simple : $$69 expression_or_error", +//t "$$70 :", +//t "lambda_expression_body_simple : $$70 expression_or_error", //t "expression_or_error : expression", //t "expression_or_error : error", -//t "$$70 :", -//t "lambda_expression : IDENTIFIER ARROW $$70 lambda_expression_body", //t "$$71 :", -//t "lambda_expression : ASYNC IDENTIFIER ARROW $$71 lambda_expression_body", +//t "lambda_expression : IDENTIFIER ARROW $$71 lambda_expression_body", //t "$$72 :", +//t "lambda_expression : ASYNC IDENTIFIER ARROW $$72 lambda_expression_body", //t "$$73 :", -//t "lambda_expression : OPEN_PARENS_LAMBDA $$72 opt_lambda_parameter_list CLOSE_PARENS ARROW $$73 lambda_expression_body", //t "$$74 :", +//t "lambda_expression : OPEN_PARENS_LAMBDA $$73 opt_lambda_parameter_list CLOSE_PARENS ARROW $$74 lambda_expression_body", //t "$$75 :", -//t "lambda_expression : ASYNC OPEN_PARENS_LAMBDA $$74 opt_lambda_parameter_list CLOSE_PARENS ARROW $$75 lambda_expression_body", +//t "$$76 :", +//t "lambda_expression : ASYNC OPEN_PARENS_LAMBDA $$75 opt_lambda_parameter_list CLOSE_PARENS ARROW $$76 lambda_expression_body", //t "expression : assignment_expression", //t "expression : non_assignment_expression", //t "non_assignment_expression : conditional_expression", @@ -846,11 +837,11 @@ namespace Mono.CSharp //t "undocumented_expressions : MAKEREF open_parens_any expression CLOSE_PARENS", //t "constant_expression : expression", //t "boolean_expression : expression", -//t "$$76 :", //t "$$77 :", //t "$$78 :", //t "$$79 :", -//t "class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$76 type_declaration_name $$77 opt_class_base opt_type_parameter_constraints_clauses $$78 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$79 opt_semicolon", +//t "$$80 :", +//t "class_declaration : opt_attributes opt_modifiers opt_partial CLASS $$77 type_declaration_name $$78 opt_class_base opt_type_parameter_constraints_clauses $$79 OPEN_BRACE opt_class_member_declarations CLOSE_BRACE $$80 opt_semicolon", //t "opt_partial :", //t "opt_partial : PARTIAL", //t "opt_modifiers :", @@ -890,12 +881,12 @@ namespace Mono.CSharp //t "opt_type_parameter_variance : type_parameter_variance", //t "type_parameter_variance : OUT", //t "type_parameter_variance : IN", -//t "$$80 :", -//t "block : OPEN_BRACE $$80 opt_statement_list block_end", +//t "$$81 :", +//t "block : OPEN_BRACE $$81 opt_statement_list block_end", //t "block_end : CLOSE_BRACE", //t "block_end : COMPLETE_COMPLETION", -//t "$$81 :", -//t "block_prepared : OPEN_BRACE $$81 opt_statement_list CLOSE_BRACE", +//t "$$82 :", +//t "block_prepared : OPEN_BRACE $$82 opt_statement_list CLOSE_BRACE", //t "opt_statement_list :", //t "opt_statement_list : statement_list", //t "statement_list : statement", @@ -940,8 +931,8 @@ namespace Mono.CSharp //t "embedded_statement : labeled_statement", //t "embedded_statement : error", //t "empty_statement : SEMICOLON", -//t "$$82 :", -//t "labeled_statement : IDENTIFIER COLON $$82 statement", +//t "$$83 :", +//t "labeled_statement : IDENTIFIER COLON $$83 statement", //t "variable_type : variable_type_simple", //t "variable_type : variable_type_simple rank_specifiers", //t "variable_type_simple : primary_expression_or_type opt_nullable", @@ -953,15 +944,17 @@ namespace Mono.CSharp //t "pointer_stars : pointer_star", //t "pointer_stars : pointer_star pointer_stars", //t "pointer_star : STAR", -//t "$$83 :", -//t "block_variable_declaration : variable_type IDENTIFIER $$83 opt_local_variable_initializer opt_variable_declarators SEMICOLON", //t "$$84 :", -//t "block_variable_declaration : CONST variable_type IDENTIFIER $$84 const_variable_initializer opt_const_declarators SEMICOLON", +//t "block_variable_declaration : variable_type IDENTIFIER $$84 opt_local_variable_initializer opt_variable_declarators SEMICOLON", +//t "$$85 :", +//t "block_variable_declaration : CONST variable_type IDENTIFIER $$85 const_variable_initializer opt_const_declarators SEMICOLON", //t "opt_local_variable_initializer :", //t "opt_local_variable_initializer : ASSIGN block_variable_initializer", //t "opt_local_variable_initializer : error", //t "opt_variable_declarators :", //t "opt_variable_declarators : variable_declarators", +//t "opt_using_or_fixed_variable_declarators :", +//t "opt_using_or_fixed_variable_declarators : variable_declarators", //t "variable_declarators : variable_declarator", //t "variable_declarators : variable_declarators variable_declarator", //t "variable_declarator : COMMA IDENTIFIER", @@ -987,15 +980,15 @@ namespace Mono.CSharp //t "selection_statement : switch_statement", //t "if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement", //t "if_statement : IF open_parens_any boolean_expression CLOSE_PARENS embedded_statement ELSE embedded_statement", -//t "$$85 :", -//t "switch_statement : SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE $$85 opt_switch_sections CLOSE_BRACE", +//t "$$86 :", +//t "switch_statement : SWITCH open_parens_any expression CLOSE_PARENS OPEN_BRACE $$86 opt_switch_sections CLOSE_BRACE", //t "opt_switch_sections :", //t "opt_switch_sections : switch_sections", //t "switch_sections : switch_section", //t "switch_sections : switch_sections switch_section", //t "switch_sections : error", -//t "$$86 :", -//t "switch_section : switch_labels $$86 statement_list", +//t "$$87 :", +//t "switch_section : switch_labels $$87 statement_list", //t "switch_labels : switch_label", //t "switch_labels : switch_labels switch_label", //t "switch_label : CASE constant_expression COLON", @@ -1006,14 +999,14 @@ namespace Mono.CSharp //t "iteration_statement : foreach_statement", //t "while_statement : WHILE open_parens_any boolean_expression CLOSE_PARENS embedded_statement", //t "do_statement : DO embedded_statement WHILE open_parens_any boolean_expression CLOSE_PARENS SEMICOLON", -//t "$$87 :", -//t "for_statement : FOR open_parens_any $$87 for_statement_cont", +//t "$$88 :", +//t "for_statement : FOR open_parens_any $$88 for_statement_cont", //t "for_statement_cont : opt_for_initializer SEMICOLON opt_for_condition SEMICOLON opt_for_iterator CLOSE_PARENS embedded_statement", //t "for_statement_cont : error", //t "opt_for_initializer :", //t "opt_for_initializer : for_initializer", -//t "$$88 :", -//t "for_initializer : variable_type IDENTIFIER $$88 opt_local_variable_initializer opt_variable_declarators", +//t "$$89 :", +//t "for_initializer : variable_type IDENTIFIER $$89 opt_local_variable_initializer opt_variable_declarators", //t "for_initializer : statement_expression_list", //t "opt_for_condition :", //t "opt_for_condition : boolean_expression", @@ -1023,8 +1016,8 @@ namespace Mono.CSharp //t "statement_expression_list : statement_expression", //t "statement_expression_list : statement_expression_list COMMA statement_expression", //t "foreach_statement : FOREACH open_parens_any type IN expression CLOSE_PARENS", -//t "$$89 :", -//t "foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$89 embedded_statement", +//t "$$90 :", +//t "foreach_statement : FOREACH open_parens_any type IDENTIFIER IN expression CLOSE_PARENS $$90 embedded_statement", //t "jump_statement : break_statement", //t "jump_statement : continue_statement", //t "jump_statement : goto_statement", @@ -1051,20 +1044,20 @@ namespace Mono.CSharp //t "opt_identifier :", //t "opt_identifier : IDENTIFIER", //t "catch_clause : CATCH block", -//t "$$90 :", -//t "catch_clause : CATCH open_parens_any type opt_identifier CLOSE_PARENS $$90 block_prepared", +//t "$$91 :", +//t "catch_clause : CATCH open_parens_any type opt_identifier CLOSE_PARENS $$91 block_prepared", //t "catch_clause : CATCH open_parens_any error", //t "checked_statement : CHECKED block", //t "unchecked_statement : UNCHECKED block", -//t "$$91 :", -//t "unsafe_statement : UNSAFE $$91 block", -//t "lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement", //t "$$92 :", +//t "unsafe_statement : UNSAFE $$92 block", +//t "lock_statement : LOCK open_parens_any expression CLOSE_PARENS embedded_statement", //t "$$93 :", -//t "fixed_statement : FIXED open_parens_any variable_type IDENTIFIER $$92 using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS $$93 embedded_statement", //t "$$94 :", +//t "fixed_statement : FIXED open_parens_any variable_type IDENTIFIER $$93 using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS $$94 embedded_statement", //t "$$95 :", -//t "using_statement : USING open_parens_any variable_type IDENTIFIER $$94 using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS $$95 embedded_statement", +//t "$$96 :", +//t "using_statement : USING open_parens_any variable_type IDENTIFIER $$95 using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS $$96 embedded_statement", //t "using_statement : USING open_parens_any expression CLOSE_PARENS embedded_statement", //t "using_or_fixed_variable_initializer :", //t "using_or_fixed_variable_initializer : ASSIGN variable_initializer", @@ -1076,18 +1069,18 @@ namespace Mono.CSharp //t "first_from_clause : FROM_FIRST type IDENTIFIER IN expression", //t "nested_from_clause : FROM IDENTIFIER IN expression", //t "nested_from_clause : FROM type IDENTIFIER IN expression", -//t "$$96 :", -//t "from_clause : FROM IDENTIFIER IN $$96 expression", //t "$$97 :", -//t "from_clause : FROM type IDENTIFIER IN $$97 expression", +//t "from_clause : FROM IDENTIFIER IN $$97 expression", +//t "$$98 :", +//t "from_clause : FROM type IDENTIFIER IN $$98 expression", //t "query_body : opt_query_body_clauses select_or_group_clause opt_query_continuation", //t "query_body : opt_query_body_clauses COMPLETE_COMPLETION", //t "query_body : error", -//t "$$98 :", -//t "select_or_group_clause : SELECT $$98 expression", //t "$$99 :", +//t "select_or_group_clause : SELECT $$99 expression", //t "$$100 :", -//t "select_or_group_clause : GROUP $$99 expression $$100 BY expression", +//t "$$101 :", +//t "select_or_group_clause : GROUP $$100 expression $$101 BY expression", //t "opt_query_body_clauses :", //t "opt_query_body_clauses : query_body_clauses", //t "query_body_clauses : query_body_clause", @@ -1097,28 +1090,28 @@ namespace Mono.CSharp //t "query_body_clause : where_clause", //t "query_body_clause : join_clause", //t "query_body_clause : orderby_clause", -//t "$$101 :", -//t "let_clause : LET IDENTIFIER ASSIGN $$101 expression", //t "$$102 :", -//t "where_clause : WHERE $$102 expression", +//t "let_clause : LET IDENTIFIER ASSIGN $$102 expression", //t "$$103 :", +//t "where_clause : WHERE $$103 expression", //t "$$104 :", //t "$$105 :", -//t "join_clause : JOIN IDENTIFIER IN $$103 expression ON $$104 expression EQUALS $$105 expression opt_join_into", //t "$$106 :", +//t "join_clause : JOIN IDENTIFIER IN $$104 expression ON $$105 expression EQUALS $$106 expression opt_join_into", //t "$$107 :", //t "$$108 :", -//t "join_clause : JOIN type IDENTIFIER IN $$106 expression ON $$107 expression EQUALS $$108 expression opt_join_into", +//t "$$109 :", +//t "join_clause : JOIN type IDENTIFIER IN $$107 expression ON $$108 expression EQUALS $$109 expression opt_join_into", //t "opt_join_into :", //t "opt_join_into : INTO IDENTIFIER", -//t "$$109 :", -//t "orderby_clause : ORDERBY $$109 orderings", -//t "orderings : order_by", //t "$$110 :", -//t "orderings : order_by COMMA $$110 orderings_then_by", -//t "orderings_then_by : then_by", +//t "orderby_clause : ORDERBY $$110 orderings", +//t "orderings : order_by", //t "$$111 :", -//t "orderings_then_by : orderings_then_by COMMA $$111 then_by", +//t "orderings : order_by COMMA $$111 orderings_then_by", +//t "orderings_then_by : then_by", +//t "$$112 :", +//t "orderings_then_by : orderings_then_by COMMA $$112 then_by", //t "order_by : expression", //t "order_by : expression ASCENDING", //t "order_by : expression DESCENDING", @@ -1126,12 +1119,12 @@ namespace Mono.CSharp //t "then_by : expression ASCENDING", //t "then_by : expression DESCENDING", //t "opt_query_continuation :", -//t "$$112 :", -//t "opt_query_continuation : INTO IDENTIFIER $$112 query_body", +//t "$$113 :", +//t "opt_query_continuation : INTO IDENTIFIER $$113 query_body", //t "interactive_parsing : EVAL_STATEMENT_PARSER EOF", //t "interactive_parsing : EVAL_USING_DECLARATIONS_UNIT_PARSER using_directives opt_COMPLETE_COMPLETION", -//t "$$113 :", -//t "interactive_parsing : EVAL_STATEMENT_PARSER $$113 interactive_statement_list opt_COMPLETE_COMPLETION", +//t "$$114 :", +//t "interactive_parsing : EVAL_STATEMENT_PARSER $$114 interactive_statement_list opt_COMPLETE_COMPLETION", //t "interactive_parsing : EVAL_COMPILATION_UNIT_PARSER interactive_compilation_unit", //t "interactive_compilation_unit : opt_extern_alias_directives opt_using_directives", //t "interactive_compilation_unit : opt_extern_alias_directives opt_using_directives namespace_or_type_declarations", @@ -1144,16 +1137,16 @@ namespace Mono.CSharp //t "doc_cref : builtin_types opt_doc_method_sig", //t "doc_cref : builtin_types DOT IDENTIFIER opt_doc_method_sig", //t "doc_cref : doc_type_declaration_name DOT THIS", -//t "$$114 :", -//t "doc_cref : doc_type_declaration_name DOT THIS OPEN_BRACKET $$114 opt_doc_parameters CLOSE_BRACKET", +//t "$$115 :", +//t "doc_cref : doc_type_declaration_name DOT THIS OPEN_BRACKET $$115 opt_doc_parameters CLOSE_BRACKET", //t "doc_cref : EXPLICIT OPERATOR type opt_doc_method_sig", //t "doc_cref : IMPLICIT OPERATOR type opt_doc_method_sig", //t "doc_cref : OPERATOR overloadable_operator opt_doc_method_sig", //t "doc_type_declaration_name : type_declaration_name", //t "doc_type_declaration_name : doc_type_declaration_name DOT type_declaration_name", //t "opt_doc_method_sig :", -//t "$$115 :", -//t "opt_doc_method_sig : OPEN_PARENS $$115 opt_doc_parameters CLOSE_PARENS", +//t "$$116 :", +//t "opt_doc_method_sig : OPEN_PARENS $$116 opt_doc_parameters CLOSE_PARENS", //t "opt_doc_parameters :", //t "opt_doc_parameters : doc_parameters", //t "doc_parameters : doc_parameter", @@ -1398,20 +1391,20 @@ namespace Mono.CSharp yyVal = yyV > yyTop ? null : yyVals[yyV]; // yyVal = yyDefault(yyV > yyTop ? null : yyVals[yyV]); switch (yyN) { case 1: -#line 395 "cs-parser.jay" +#line 400 "cs-parser.jay" { Lexer.check_incorrect_doc_comment (); } break; case 2: -#line 396 "cs-parser.jay" +#line 401 "cs-parser.jay" { Lexer.CompleteOnEOF = false; } break; case 6: case_6(); break; case 7: -#line 413 "cs-parser.jay" +#line 418 "cs-parser.jay" { module.AddAttributes ((Attributes) yyVals[0+yyTop], current_namespace); } @@ -1423,7 +1416,7 @@ case 13: case_13(); break; case 14: -#line 451 "cs-parser.jay" +#line 456 "cs-parser.jay" { syntax_error (GetLocation (yyVals[-1+yyTop]), "`alias' expected"); /* TODO: better*/ } @@ -1468,7 +1461,7 @@ case 41: case_41(); break; case 42: -#line 640 "cs-parser.jay" +#line 645 "cs-parser.jay" { current_namespace.DeclarationFound = true; } @@ -1498,18 +1491,18 @@ case 57: case_57(); break; case 58: -#line 733 "cs-parser.jay" - { yyVal = "event"; } +#line 754 "cs-parser.jay" + { yyVal = "event"; savedCloseLocation = GetLocation (yyVals[0+yyTop]); } break; case 59: -#line 734 "cs-parser.jay" - { yyVal = "return"; } +#line 755 "cs-parser.jay" + { yyVal = "return"; savedCloseLocation = GetLocation (yyVals[0+yyTop]); } break; case 60: case_60(); break; case 61: -#line 751 "cs-parser.jay" +#line 772 "cs-parser.jay" { yyVal = new List (4) { (Attribute) yyVals[0+yyTop] }; } @@ -1518,7 +1511,7 @@ case 62: case_62(); break; case 63: -#line 765 "cs-parser.jay" +#line 787 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1527,14 +1520,14 @@ case 64: case_64(); break; case 66: -#line 789 "cs-parser.jay" +#line 814 "cs-parser.jay" { yyVal = null; } break; case 67: case_67(); break; case 68: -#line 800 "cs-parser.jay" +#line 825 "cs-parser.jay" { yyVal = null; } break; case 69: @@ -1550,13 +1543,13 @@ case 72: case_72(); break; case 73: -#line 844 "cs-parser.jay" +#line 869 "cs-parser.jay" { yyVal = new Argument ((Expression) yyVals[0+yyTop]); } break; case 75: -#line 852 "cs-parser.jay" +#line 877 "cs-parser.jay" { ++lexer.parsing_block; } @@ -1568,26 +1561,38 @@ case 77: case_77(); break; case 78: -#line 877 "cs-parser.jay" +#line 903 "cs-parser.jay" { yyVal = null; } break; case 79: -#line 881 "cs-parser.jay" +#line 907 "cs-parser.jay" { yyVal = Argument.AType.Ref; } break; case 80: -#line 885 "cs-parser.jay" +#line 911 "cs-parser.jay" { yyVal = Argument.AType.Out; } break; +case 83: +#line 923 "cs-parser.jay" + { + lexer.parsing_modifiers = true; + } + break; +case 84: +#line 927 "cs-parser.jay" + { + lexer.parsing_modifiers = true; + } + break; case 95: case_95(); break; case 96: -#line 926 "cs-parser.jay" +#line 957 "cs-parser.jay" { lexer.ConstraintsParsing = true; } @@ -1605,127 +1610,174 @@ case 100: case_100(); break; case 101: -#line 958 "cs-parser.jay" - { - Error_SyntaxError (yyToken); - } + case_101(); break; case 102: - case_102(); - break; -case 103: -#line 970 "cs-parser.jay" +#line 998 "cs-parser.jay" { - lbag.AppendToMember (current_class, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + Error_SyntaxError (yyToken); } break; -case 118: - case_118(); +case 103: + case_103(); break; -case 119: - case_119(); +case 104: + case_104(); break; -case 122: +case 107: #line 1039 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; -case 123: +case 108: #line 1043 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; -case 124: - case_124(); +case 109: + case_109(); break; -case 125: +case 110: #line 1059 "cs-parser.jay" { ++lexer.parsing_block; } break; -case 126: - case_126(); +case 111: + case_111(); break; -case 127: - case_127(); +case 112: + case_112(); break; -case 130: - case_130(); +case 115: + case_115(); break; -case 131: - case_131(); +case 116: + case_116(); break; -case 132: - case_132(); +case 117: + case_117(); break; -case 133: - case_133(); +case 118: + case_118(); break; -case 134: +case 119: #line 1138 "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"); } break; -case 136: - case_136(); +case 121: + case_121(); break; -case 137: - case_137(); +case 122: + case_122(); break; -case 140: +case 125: #line 1168 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; -case 141: +case 126: #line 1172 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; -case 142: - case_142(); +case 127: + case_127(); break; -case 143: +case 128: #line 1185 "cs-parser.jay" { ++lexer.parsing_block; } break; -case 144: - case_144(); +case 129: + case_129(); break; -case 147: +case 132: #line 1204 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; -case 148: +case 133: #line 1208 "cs-parser.jay" { current_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; -case 149: - case_149(); +case 134: + case_134(); break; -case 150: +case 135: #line 1224 "cs-parser.jay" { ++lexer.parsing_block; } break; -case 151: - case_151(); +case 136: + case_136(); + break; +case 137: + case_137(); + break; +case 140: + case_140(); + break; +case 141: + case_141(); + break; +case 142: + case_142(); + break; +case 143: +#line 1295 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.All; + } + break; +case 144: +#line 1299 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 145: + case_145(); + break; +case 146: +#line 1339 "cs-parser.jay" + { + lexer.parsing_generic_declaration = true; + } + break; +case 147: + case_147(); + break; +case 148: +#line 1349 "cs-parser.jay" + { + lexer.ConstraintsParsing = true; + } + break; +case 149: + case_149(); + break; +case 150: + case_150(); break; case 152: - case_152(); +#line 1423 "cs-parser.jay" + { savedLocation = GetLocation (yyVals[0+yyTop]); yyVal = null; } + break; +case 153: +#line 1427 "cs-parser.jay" + { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } break; case 155: case_155(); @@ -1737,33 +1789,27 @@ case 157: case_157(); break; case 158: -#line 1291 "cs-parser.jay" - { - valid_param_mod = ParameterModifierType.All; - } + case_158(); break; case 159: -#line 1295 "cs-parser.jay" - { - lexer.ConstraintsParsing = true; - } + case_159(); break; case 160: case_160(); break; case 161: -#line 1335 "cs-parser.jay" - { - lexer.parsing_generic_declaration = true; - } + case_161(); break; case 162: - case_162(); +#line 1499 "cs-parser.jay" + { + yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[0+yyTop] } ); + } break; case 163: -#line 1345 "cs-parser.jay" +#line 1503 "cs-parser.jay" { - lexer.ConstraintsParsing = true; + yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[0+yyTop])) }, true); } break; case 164: @@ -1772,28 +1818,36 @@ case 164: case 165: case_165(); break; +case 166: + case_166(); + break; case 167: -#line 1419 "cs-parser.jay" - { yyVal = null; } + case_167(); break; case 168: -#line 1423 "cs-parser.jay" - { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } + case_168(); + break; +case 169: + case_169(); break; case 170: - case_170(); +#line 1578 "cs-parser.jay" + { + ++lexer.parsing_block; + } break; case 171: case_171(); break; case 172: - case_172(); - break; -case 173: - case_173(); +#line 1619 "cs-parser.jay" + { yyVal = Parameter.Modifier.NONE; } break; case 174: - case_174(); +#line 1627 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } break; case 175: case_175(); @@ -1802,16 +1856,10 @@ case 176: case_176(); break; case 177: -#line 1482 "cs-parser.jay" - { - yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[0+yyTop] } ); - } + case_177(); break; case 178: -#line 1486 "cs-parser.jay" - { - yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[0+yyTop])) }, true); - } + case_178(); break; case 179: case_179(); @@ -1829,56 +1877,49 @@ case 183: case_183(); break; case 184: - case_184(); - break; -case 185: -#line 1561 "cs-parser.jay" +#line 1720 "cs-parser.jay" { - ++lexer.parsing_block; + Error_DuplicateParameterModifier (GetLocation (yyVals[-1+yyTop]), Parameter.Modifier.PARAMS); } break; +case 185: + case_185(); + break; case 186: case_186(); break; case 187: -#line 1602 "cs-parser.jay" - { yyVal = Parameter.Modifier.NONE; } + case_187(); + break; +case 188: + case_188(); break; case 189: case_189(); break; case 190: - case_190(); +#line 1774 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } break; case 191: case_191(); break; case 192: - case_192(); +#line 1803 "cs-parser.jay" + { + lexer.PropertyParsing = false; + } break; case 193: case_193(); break; -case 194: - case_194(); - break; -case 195: - case_195(); - break; -case 196: - case_196(); - break; -case 197: - case_197(); - break; case 198: case_198(); break; case 199: -#line 1700 "cs-parser.jay" - { - Error_DuplicateParameterModifier (GetLocation (yyVals[-1+yyTop]), Parameter.Modifier.PARAMS); - } + case_199(); break; case 200: case_200(); @@ -1889,232 +1930,248 @@ case 201: case 202: case_202(); break; -case 203: - case_203(); - break; case 204: case_204(); break; case 205: -#line 1754 "cs-parser.jay" - { - valid_param_mod = ParameterModifierType.Params | ParameterModifierType.DefaultValue; - } + case_205(); break; case 206: - case_206(); - break; -case 207: -#line 1783 "cs-parser.jay" +#line 1952 "cs-parser.jay" { - lexer.PropertyParsing = false; + lexer.ConstraintsParsing = true; } break; +case 207: + case_207(); + break; case 208: case_208(); break; -case 213: - case_213(); +case 209: + case_209(); + break; +case 210: + case_210(); + break; +case 211: +#line 1989 "cs-parser.jay" + { + Error_SyntaxError (yyToken); + } break; case 214: - case_214(); +#line 2001 "cs-parser.jay" + { + lexer.parsing_modifiers = true; + } break; case 215: - case_215(); +#line 2005 "cs-parser.jay" + { + lexer.parsing_modifiers = true; + } break; case 216: - case_216(); +#line 2012 "cs-parser.jay" + { + report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); + } break; case 217: - case_217(); - break; -case 219: - case_219(); - break; -case 220: - case_220(); - break; -case 221: -#line 1928 "cs-parser.jay" +#line 2016 "cs-parser.jay" { - lexer.ConstraintsParsing = true; + report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); } break; case 222: - case_222(); +#line 2024 "cs-parser.jay" + { + report.Error (567, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain operators"); + } break; case 223: - case_223(); +#line 2028 "cs-parser.jay" + { + report.Error (526, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain contructors"); + } break; case 224: - case_224(); +#line 2032 "cs-parser.jay" + { + report.Error (524, GetLocation (yyVals[0+yyTop]), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); + } break; case 225: - case_225(); +#line 2038 "cs-parser.jay" + { + } break; case 226: -#line 1961 "cs-parser.jay" - { - Error_SyntaxError (yyToken); - } + case_226(); + break; +case 228: +#line 2071 "cs-parser.jay" + { savedLocation = GetLocation (yyVals[0+yyTop]); yyVal = null; } + break; +case 230: + case_230(); break; case 231: -#line 1978 "cs-parser.jay" +#line 2087 "cs-parser.jay" { - report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); + valid_param_mod = ParameterModifierType.DefaultValue; } break; case 232: -#line 1982 "cs-parser.jay" - { - report.Error (525, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain fields or constants"); - } + case_232(); + break; +case 234: +#line 2133 "cs-parser.jay" + { yyVal = Operator.OpType.LogicalNot; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } + break; +case 235: +#line 2134 "cs-parser.jay" + { yyVal = Operator.OpType.OnesComplement; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } + break; +case 236: +#line 2135 "cs-parser.jay" + { yyVal = Operator.OpType.Increment; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 237: -#line 1990 "cs-parser.jay" - { - report.Error (567, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain operators"); - } +#line 2136 "cs-parser.jay" + { yyVal = Operator.OpType.Decrement; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 238: -#line 1994 "cs-parser.jay" - { - report.Error (526, GetLocation (yyVals[0+yyTop]), "Interfaces cannot contain contructors"); - } +#line 2137 "cs-parser.jay" + { yyVal = Operator.OpType.True; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 239: -#line 1998 "cs-parser.jay" - { - report.Error (524, GetLocation (yyVals[0+yyTop]), "Interfaces cannot declare classes, structs, interfaces, delegates, or enumerations"); - } +#line 2138 "cs-parser.jay" + { yyVal = Operator.OpType.False; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 240: -#line 2004 "cs-parser.jay" - { - } +#line 2140 "cs-parser.jay" + { yyVal = Operator.OpType.Addition; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 241: - case_241(); +#line 2141 "cs-parser.jay" + { yyVal = Operator.OpType.Subtraction; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } + break; +case 242: +#line 2143 "cs-parser.jay" + { yyVal = Operator.OpType.Multiply; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 243: -#line 2034 "cs-parser.jay" - { yyVal = null; } +#line 2144 "cs-parser.jay" + { yyVal = Operator.OpType.Division; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } + break; +case 244: +#line 2145 "cs-parser.jay" + { yyVal = Operator.OpType.Modulus; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 245: - case_245(); +#line 2146 "cs-parser.jay" + { yyVal = Operator.OpType.BitwiseAnd; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 246: -#line 2050 "cs-parser.jay" - { - valid_param_mod = ParameterModifierType.DefaultValue; - } +#line 2147 "cs-parser.jay" + { yyVal = Operator.OpType.BitwiseOr; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 247: - case_247(); +#line 2148 "cs-parser.jay" + { yyVal = Operator.OpType.ExclusiveOr; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } + break; +case 248: +#line 2149 "cs-parser.jay" + { yyVal = Operator.OpType.LeftShift; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 249: -#line 2096 "cs-parser.jay" - { yyVal = Operator.OpType.LogicalNot; } +#line 2150 "cs-parser.jay" + { yyVal = Operator.OpType.RightShift; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 250: -#line 2097 "cs-parser.jay" - { yyVal = Operator.OpType.OnesComplement; } +#line 2151 "cs-parser.jay" + { yyVal = Operator.OpType.Equality; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 251: -#line 2098 "cs-parser.jay" - { yyVal = Operator.OpType.Increment; } +#line 2152 "cs-parser.jay" + { yyVal = Operator.OpType.Inequality; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 252: -#line 2099 "cs-parser.jay" - { yyVal = Operator.OpType.Decrement; } +#line 2153 "cs-parser.jay" + { yyVal = Operator.OpType.GreaterThan; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 253: -#line 2100 "cs-parser.jay" - { yyVal = Operator.OpType.True; } +#line 2154 "cs-parser.jay" + { yyVal = Operator.OpType.LessThan; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 254: -#line 2101 "cs-parser.jay" - { yyVal = Operator.OpType.False; } +#line 2155 "cs-parser.jay" + { yyVal = Operator.OpType.GreaterThanOrEqual; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 255: -#line 2103 "cs-parser.jay" - { yyVal = Operator.OpType.Addition; } +#line 2156 "cs-parser.jay" + { yyVal = Operator.OpType.LessThanOrEqual; savedOperatorLocation = GetLocation (yyVals[0+yyTop]); } break; case 256: -#line 2104 "cs-parser.jay" - { yyVal = Operator.OpType.Subtraction; } +#line 2163 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } break; case 257: -#line 2106 "cs-parser.jay" - { yyVal = Operator.OpType.Multiply; } + case_257(); break; case 258: -#line 2107 "cs-parser.jay" - { yyVal = Operator.OpType.Division; } +#line 2182 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.DefaultValue; + } break; case 259: -#line 2108 "cs-parser.jay" - { yyVal = Operator.OpType.Modulus; } + case_259(); break; case 260: -#line 2109 "cs-parser.jay" - { yyVal = Operator.OpType.BitwiseAnd; } + case_260(); break; case 261: -#line 2110 "cs-parser.jay" - { yyVal = Operator.OpType.BitwiseOr; } + case_261(); break; case 262: -#line 2111 "cs-parser.jay" - { yyVal = Operator.OpType.ExclusiveOr; } + case_262(); break; case 263: -#line 2112 "cs-parser.jay" - { yyVal = Operator.OpType.LeftShift; } + case_263(); break; case 264: -#line 2113 "cs-parser.jay" - { yyVal = Operator.OpType.RightShift; } + case_264(); break; case 265: -#line 2114 "cs-parser.jay" - { yyVal = Operator.OpType.Equality; } - break; -case 266: -#line 2115 "cs-parser.jay" - { yyVal = Operator.OpType.Inequality; } + case_265(); break; case 267: -#line 2116 "cs-parser.jay" - { yyVal = Operator.OpType.GreaterThan; } - break; -case 268: -#line 2117 "cs-parser.jay" - { yyVal = Operator.OpType.LessThan; } - break; -case 269: -#line 2118 "cs-parser.jay" - { yyVal = Operator.OpType.GreaterThanOrEqual; } +#line 2285 "cs-parser.jay" + { current_block = null; yyVal = null; } break; case 270: -#line 2119 "cs-parser.jay" - { yyVal = Operator.OpType.LessThanOrEqual; } - break; -case 271: -#line 2126 "cs-parser.jay" +#line 2297 "cs-parser.jay" { - valid_param_mod = ParameterModifierType.DefaultValue; + ++lexer.parsing_block; } break; -case 272: - case_272(); +case 271: + case_271(); break; -case 273: -#line 2145 "cs-parser.jay" +case 272: +#line 2307 "cs-parser.jay" { - valid_param_mod = ParameterModifierType.DefaultValue; + ++lexer.parsing_block; } break; +case 273: + case_273(); + break; case 274: case_274(); break; @@ -2136,33 +2193,38 @@ case 279: case 280: case_280(); break; -case 282: -#line 2248 "cs-parser.jay" - { current_block = null; yyVal = null; } +case 281: + case_281(); break; -case 285: -#line 2260 "cs-parser.jay" +case 283: +#line 2416 "cs-parser.jay" { - ++lexer.parsing_block; + ++lexer.parsing_block; } break; -case 286: - case_286(); +case 284: + case_284(); break; case 287: -#line 2270 "cs-parser.jay" +#line 2433 "cs-parser.jay" { - ++lexer.parsing_block; + current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); } break; case 288: - case_288(); +#line 2437 "cs-parser.jay" + { + current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); + } break; case 289: case_289(); break; case 290: - case_290(); +#line 2450 "cs-parser.jay" + { + ++lexer.parsing_block; + } break; case 291: case_291(); @@ -2171,45 +2233,39 @@ case 292: case_292(); break; case 293: - case_293(); - break; -case 294: - case_294(); - break; -case 295: - case_295(); +#line 2475 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } break; case 296: case_296(); break; +case 297: + case_297(); + break; case 298: -#line 2379 "cs-parser.jay" - { - ++lexer.parsing_block; - } + case_298(); break; case 299: case_299(); break; +case 300: + case_300(); + break; +case 301: + case_301(); + break; case 302: -#line 2396 "cs-parser.jay" - { - current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); - } + case_302(); break; case 303: -#line 2400 "cs-parser.jay" - { - current_event_field.AddDeclarator ((FieldDeclarator) yyVals[0+yyTop]); - } - break; -case 304: - case_304(); + case_303(); break; case 305: -#line 2413 "cs-parser.jay" +#line 2569 "cs-parser.jay" { - ++lexer.parsing_block; + enumCommas.Add (GetLocation (yyVals[0+yyTop])); } break; case 306: @@ -2219,10 +2275,10 @@ case 307: case_307(); break; case 308: -#line 2438 "cs-parser.jay" - { - yyVal = yyVals[0+yyTop]; - } + case_308(); + break; +case 309: + case_309(); break; case 311: case_311(); @@ -2230,17 +2286,11 @@ case 311: case 312: case_312(); break; -case 313: - case_313(); - break; -case 314: - case_314(); - break; case 315: - case_315(); - break; -case 316: - case_316(); +#line 2637 "cs-parser.jay" + { + enumCommas.Add (GetLocation (yyVals[0+yyTop])); + } break; case 317: case_317(); @@ -2248,36 +2298,42 @@ case 317: case 318: case_318(); break; +case 319: + case_319(); + break; case 320: case_320(); break; case 321: - case_321(); +#line 2695 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; + } break; case 322: case_322(); break; case 323: - case_323(); +#line 2717 "cs-parser.jay" + { + lexer.ConstraintsParsing = false; + } break; -case 325: - case_325(); +case 324: + case_324(); break; case 326: case_326(); break; -case 329: -#line 2593 "cs-parser.jay" - { - lbag.AddLocation (yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); - } +case 328: + case_328(); + break; +case 330: + case_330(); break; case 331: case_331(); break; -case 332: - case_332(); - break; case 333: case_333(); break; @@ -2285,37 +2341,40 @@ case 334: case_334(); break; case 335: -#line 2651 "cs-parser.jay" - { - valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out | ParameterModifierType.Params | ParameterModifierType.DefaultValue; - } + case_335(); break; case 336: case_336(); break; case 337: -#line 2673 "cs-parser.jay" +#line 2822 "cs-parser.jay" { - lexer.ConstraintsParsing = false; + lexer.parsing_generic_declaration = true; } break; case 338: case_338(); break; -case 340: - case_340(); +case 339: + case_339(); + break; +case 341: + case_341(); break; case 342: case_342(); break; +case 343: + case_343(); + break; case 344: case_344(); break; case 345: case_345(); break; -case 347: - case_347(); +case 346: + case_346(); break; case 348: case_348(); @@ -2327,202 +2386,213 @@ case 350: case_350(); break; case 351: -#line 2777 "cs-parser.jay" - { - lexer.parsing_generic_declaration = true; - } + case_351(); break; case 352: case_352(); break; -case 353: - case_353(); - break; -case 355: - case_355(); - break; -case 356: - case_356(); - break; -case 357: - case_357(); - break; -case 358: - case_358(); - break; -case 359: - case_359(); - break; -case 360: - case_360(); - break; -case 362: - case_362(); - break; -case 363: - case_363(); - break; -case 364: - case_364(); - break; -case 365: - case_365(); - break; -case 366: - case_366(); - break; -case 368: -#line 2895 "cs-parser.jay" +case 354: +#line 2943 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[0+yyTop])); } break; -case 369: -#line 2902 "cs-parser.jay" +case 355: +#line 2950 "cs-parser.jay" { lexer.parsing_generic_declaration = true; } break; -case 371: - case_371(); +case 357: + case_357(); break; -case 373: - case_373(); +case 359: + case_359(); break; -case 375: - case_375(); +case 361: + case_361(); break; -case 377: -#line 2940 "cs-parser.jay" +case 363: +#line 2988 "cs-parser.jay" { yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; -case 378: - case_378(); +case 364: + case_364(); break; -case 379: -#line 2960 "cs-parser.jay" +case 365: +#line 3008 "cs-parser.jay" { yyVal = new ComposedCast (((MemberName) yyVals[-1+yyTop]).GetTypeExpression (), (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; -case 380: - case_380(); +case 366: + case_366(); break; -case 381: -#line 2969 "cs-parser.jay" +case 367: +#line 3017 "cs-parser.jay" { yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; -case 382: -#line 2973 "cs-parser.jay" +case 368: +#line 3021 "cs-parser.jay" { yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; -case 383: - case_383(); +case 369: + case_369(); break; -case 384: - case_384(); +case 370: + case_370(); break; -case 385: - case_385(); +case 371: + case_371(); break; -case 386: - case_386(); +case 372: + case_372(); break; -case 387: -#line 3011 "cs-parser.jay" +case 373: +#line 3060 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Object, GetLocation (yyVals[0+yyTop])); } break; -case 388: -#line 3012 "cs-parser.jay" +case 374: +#line 3061 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.String, GetLocation (yyVals[0+yyTop])); } break; -case 389: -#line 3013 "cs-parser.jay" +case 375: +#line 3062 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Bool, GetLocation (yyVals[0+yyTop])); } break; -case 390: -#line 3014 "cs-parser.jay" +case 376: +#line 3063 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Decimal, GetLocation (yyVals[0+yyTop])); } break; -case 391: -#line 3015 "cs-parser.jay" +case 377: +#line 3064 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Float, GetLocation (yyVals[0+yyTop])); } break; -case 392: -#line 3016 "cs-parser.jay" +case 378: +#line 3065 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Double, GetLocation (yyVals[0+yyTop])); } break; -case 394: -#line 3021 "cs-parser.jay" +case 380: +#line 3070 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.SByte, GetLocation (yyVals[0+yyTop])); } break; -case 395: -#line 3022 "cs-parser.jay" +case 381: +#line 3071 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Byte, GetLocation (yyVals[0+yyTop])); } break; -case 396: -#line 3023 "cs-parser.jay" +case 382: +#line 3072 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Short, GetLocation (yyVals[0+yyTop])); } break; -case 397: -#line 3024 "cs-parser.jay" +case 383: +#line 3073 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.UShort, GetLocation (yyVals[0+yyTop])); } break; -case 398: -#line 3025 "cs-parser.jay" +case 384: +#line 3074 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Int, GetLocation (yyVals[0+yyTop])); } break; -case 399: -#line 3026 "cs-parser.jay" +case 385: +#line 3075 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.UInt, GetLocation (yyVals[0+yyTop])); } break; -case 400: -#line 3027 "cs-parser.jay" +case 386: +#line 3076 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Long, GetLocation (yyVals[0+yyTop])); } break; -case 401: -#line 3028 "cs-parser.jay" +case 387: +#line 3077 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.ULong, GetLocation (yyVals[0+yyTop])); } break; -case 402: -#line 3029 "cs-parser.jay" +case 388: +#line 3078 "cs-parser.jay" { yyVal = new TypeExpression (compiler.BuiltinTypes.Char, GetLocation (yyVals[0+yyTop])); } break; +case 409: + case_409(); + break; +case 410: + case_410(); + break; +case 414: +#line 3125 "cs-parser.jay" + { yyVal = new NullLiteral (GetLocation (yyVals[0+yyTop])); } + break; +case 415: +#line 3129 "cs-parser.jay" + { yyVal = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation (yyVals[0+yyTop])); } + break; +case 416: +#line 3130 "cs-parser.jay" + { yyVal = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation (yyVals[0+yyTop])); } + break; +case 421: + case_421(); + break; +case 422: +#line 3163 "cs-parser.jay" + { + yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); + } + break; case 423: case_423(); break; case 424: case_424(); break; +case 425: + case_425(); + break; +case 426: + case_426(); + break; +case 427: +#line 3198 "cs-parser.jay" + { + yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null,GetLocation (yyVals[0+yyTop])); + } + break; case 428: -#line 3076 "cs-parser.jay" - { yyVal = new NullLiteral (GetLocation (yyVals[0+yyTop])); } + case_428(); break; case 429: -#line 3080 "cs-parser.jay" - { yyVal = new BoolLiteral (compiler.BuiltinTypes, true, GetLocation (yyVals[0+yyTop])); } +#line 3206 "cs-parser.jay" + { + yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null, lexer.Location); + } break; case 430: -#line 3081 "cs-parser.jay" - { yyVal = new BoolLiteral (compiler.BuiltinTypes, false, GetLocation (yyVals[0+yyTop])); } + case_430(); + break; +case 431: + case_431(); + break; +case 432: +#line 3222 "cs-parser.jay" + { yyVal = null; } + break; +case 434: + case_434(); break; case 435: case_435(); break; case 436: -#line 3114 "cs-parser.jay" - { - yyVal = new ParenthesizedExpression ((Expression) yyVals[-1+yyTop]); - } +#line 3245 "cs-parser.jay" + { yyVal = null; } break; case 437: - case_437(); +#line 3249 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } break; case 438: case_438(); @@ -2534,45 +2604,32 @@ case 440: case_440(); break; case 441: -#line 3146 "cs-parser.jay" - { - yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null,GetLocation (yyVals[0+yyTop])); - } + case_441(); break; case 442: - case_442(); - break; -case 443: -#line 3154 "cs-parser.jay" +#line 3282 "cs-parser.jay" { - yyVal = new CompletionMemberAccess ((Expression) yyVals[-2+yyTop], null, lexer.Location); + yyVal = new CompletionElementInitializer (null, GetLocation (yyVals[0+yyTop])); } break; +case 443: + case_443(); + break; case 444: case_444(); break; case 445: case_445(); break; -case 446: -#line 3170 "cs-parser.jay" - { yyVal = null; } - break; case 448: - case_448(); - break; -case 449: - case_449(); +#line 3310 "cs-parser.jay" + { yyVal = null; } break; case 450: -#line 3193 "cs-parser.jay" - { yyVal = null; } + case_450(); break; case 451: -#line 3197 "cs-parser.jay" - { - yyVal = yyVals[0+yyTop]; - } + case_451(); break; case 452: case_452(); @@ -2584,26 +2641,22 @@ case 454: case_454(); break; case 455: - case_455(); - break; -case 456: -#line 3229 "cs-parser.jay" +#line 3362 "cs-parser.jay" { - yyVal = new CompletionElementInitializer (null, GetLocation (yyVals[0+yyTop])); + yyVal = new Argument ((Expression) yyVals[0+yyTop]); } break; -case 457: - case_457(); - break; -case 458: - case_458(); - break; case 459: case_459(); break; +case 460: + case_460(); + break; +case 461: + case_461(); + break; case 462: -#line 3257 "cs-parser.jay" - { yyVal = null; } + case_462(); break; case 464: case_464(); @@ -2621,9 +2674,18 @@ case 468: case_468(); break; case 469: -#line 3309 "cs-parser.jay" + case_469(); + break; +case 470: +#line 3449 "cs-parser.jay" { - yyVal = new Argument ((Expression) yyVals[0+yyTop]); + yyVal = new Argument ((Expression) yyVals[0+yyTop]); + } + break; +case 472: +#line 3457 "cs-parser.jay" + { + yyVal = new This (GetLocation (yyVals[0+yyTop])); } break; case 473: @@ -2633,10 +2695,19 @@ case 474: case_474(); break; case 475: - case_475(); +#line 3477 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PostIncrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } break; case 476: - case_476(); +#line 3484 "cs-parser.jay" + { + yyVal = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); + } + break; +case 477: + case_477(); break; case 478: case_478(); @@ -2657,34 +2728,20 @@ case 483: case_483(); break; case 484: -#line 3396 "cs-parser.jay" - { - yyVal = new Argument ((Expression) yyVals[0+yyTop]); - } - break; -case 486: -#line 3404 "cs-parser.jay" +#line 3550 "cs-parser.jay" { - yyVal = new This (GetLocation (yyVals[0+yyTop])); + ++lexer.parsing_type; } break; -case 487: - case_487(); +case 485: + case_485(); break; -case 488: - case_488(); +case 486: + case_486(); break; case 489: -#line 3424 "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" - { - yyVal = new UnaryMutator (UnaryMutator.Mode.PostDecrement, (Expression) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); - } +#line 3577 "cs-parser.jay" + { yyVal = null; } break; case 491: case_491(); @@ -2704,30 +2761,38 @@ case 495: case 496: case_496(); break; -case 497: - case_497(); - break; -case 498: -#line 3497 "cs-parser.jay" - { - ++lexer.parsing_type; - } - break; -case 499: - case_499(); - break; case 500: case_500(); break; +case 501: + case_501(); + break; +case 502: + case_502(); + break; case 503: -#line 3524 "cs-parser.jay" - { yyVal = null; } +#line 3655 "cs-parser.jay" + { + yyVal = 2; + } + break; +case 504: +#line 3659 "cs-parser.jay" + { + yyVal = ((int) yyVals[-1+yyTop]) + 1; + } break; case 505: - case_505(); +#line 3666 "cs-parser.jay" + { + yyVal = null; + } break; case 506: - case_506(); +#line 3670 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } break; case 507: case_507(); @@ -2741,8 +2806,14 @@ case 509: case 510: case_510(); break; -case 514: - case_514(); +case 511: +#line 3714 "cs-parser.jay" + { + lexer.TypeOfParsing = true; + } + break; +case 512: + case_512(); break; case 515: case_515(); @@ -2751,28 +2822,16 @@ case 516: case_516(); break; case 517: -#line 3600 "cs-parser.jay" - { - yyVal = 2; - } + case_517(); break; case 518: -#line 3604 "cs-parser.jay" - { - yyVal = ((int) yyVals[-1+yyTop]) + 1; - } + case_518(); break; case 519: -#line 3611 "cs-parser.jay" - { - yyVal = null; - } + case_519(); break; case 520: -#line 3615 "cs-parser.jay" - { - yyVal = yyVals[0+yyTop]; - } + case_520(); break; case 521: case_521(); @@ -2787,28 +2846,43 @@ case 524: case_524(); break; case 525: -#line 3659 "cs-parser.jay" - { - lexer.TypeOfParsing = true; - } + case_525(); break; case 526: case_526(); break; +case 527: +#line 3834 "cs-parser.jay" + { + start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], false, GetLocation (yyVals[-1+yyTop])); + } + break; +case 528: + case_528(); + break; case 529: - case_529(); +#line 3847 "cs-parser.jay" + { + start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], true, GetLocation (yyVals[-2+yyTop])); + } break; case 530: - case_530(); +#line 3851 "cs-parser.jay" + { + yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); + } break; case 531: - case_531(); - break; -case 532: - case_532(); +#line 3858 "cs-parser.jay" + { + yyVal = ParametersCompiled.Undefined; + } break; case 533: - case_533(); +#line 3866 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } break; case 534: case_534(); @@ -2816,113 +2890,101 @@ case 534: case 535: case_535(); break; -case 536: - case_536(); - break; case 537: - case_537(); +#line 3892 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.LogicalNot, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } break; case 538: - case_538(); - break; -case 539: - case_539(); - break; -case 540: - case_540(); - break; -case 541: -#line 3773 "cs-parser.jay" +#line 3896 "cs-parser.jay" { - start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], false, GetLocation (yyVals[-1+yyTop])); + yyVal = new Unary (Unary.Operator.OnesComplement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; +case 541: + case_541(); + break; case 542: case_542(); break; -case 543: -#line 3786 "cs-parser.jay" - { - start_anonymous (false, (ParametersCompiled) yyVals[0+yyTop], true, GetLocation (yyVals[-2+yyTop])); - } - break; case 544: -#line 3790 "cs-parser.jay" - { - yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); +#line 3926 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.UnaryPlus, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 545: -#line 3797 "cs-parser.jay" +#line 3930 "cs-parser.jay" + { + yyVal = new Unary (Unary.Operator.UnaryNegation, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 546: +#line 3934 "cs-parser.jay" { - yyVal = ParametersCompiled.Undefined; + yyVal = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 547: -#line 3805 "cs-parser.jay" +#line 3938 "cs-parser.jay" { - valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + yyVal = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 548: - case_548(); +#line 3942 "cs-parser.jay" + { + yyVal = new Indirection ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } break; case 549: - case_549(); - break; -case 551: -#line 3831 "cs-parser.jay" +#line 3946 "cs-parser.jay" { - yyVal = new Unary (Unary.Operator.LogicalNot, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + yyVal = new Unary (Unary.Operator.AddressOf, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; +case 551: + case_551(); + break; case 552: -#line 3835 "cs-parser.jay" - { - yyVal = new Unary (Unary.Operator.OnesComplement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } + case_552(); + break; +case 553: + case_553(); break; case 555: case_555(); break; case 556: - case_556(); +#line 3978 "cs-parser.jay" + { + yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; +case 557: + case_557(); break; case 558: -#line 3865 "cs-parser.jay" - { - yyVal = new Unary (Unary.Operator.UnaryPlus, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); +#line 3987 "cs-parser.jay" + { + yyVal = new As ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 559: -#line 3869 "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 3991 "cs-parser.jay" { - yyVal = new UnaryMutator (UnaryMutator.Mode.PreIncrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + yyVal = new Is ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 561: -#line 3877 "cs-parser.jay" - { - yyVal = new UnaryMutator (UnaryMutator.Mode.PreDecrement, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } + case_561(); break; case 562: -#line 3881 "cs-parser.jay" - { - yyVal = new Indirection ((Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } + case_562(); break; -case 563: -#line 3885 "cs-parser.jay" - { - yyVal = new Unary (Unary.Operator.AddressOf, (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } +case 564: + case_564(); break; case 565: case_565(); @@ -2937,28 +2999,13 @@ case 569: case_569(); break; case 570: -#line 3917 "cs-parser.jay" - { - yyVal = new Binary (Binary.Operator.Subtraction, (Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } - break; -case 571: - case_571(); + case_570(); break; case 572: -#line 3926 "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" - { - yyVal = new Is ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } + case_572(); break; -case 575: - case_575(); +case 574: + case_574(); break; case 576: case_576(); @@ -2966,72 +3013,82 @@ case 576: case 578: case_578(); break; -case 579: - case_579(); - break; case 580: case_580(); break; -case 581: - case_581(); - break; -case 583: - case_583(); +case 582: + case_582(); break; case 584: case_584(); break; +case 585: +#line 4115 "cs-parser.jay" + { + yyVal = new SimpleAssign ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } + break; case 586: case_586(); break; +case 587: + case_587(); + break; case 588: case_588(); break; +case 589: + case_589(); + break; case 590: case_590(); break; +case 591: + case_591(); + break; case 592: case_592(); break; +case 593: + case_593(); + break; case 594: case_594(); break; +case 595: + case_595(); + break; case 596: case_596(); break; +case 597: + case_597(); + break; case 598: case_598(); break; case 599: -#line 4054 "cs-parser.jay" - { - yyVal = new SimpleAssign ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } + case_599(); break; case 600: case_600(); break; case 601: - case_601(); +#line 4212 "cs-parser.jay" + { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } break; case 602: case_602(); break; -case 603: - case_603(); - break; -case 604: - case_604(); - break; case 605: - case_605(); +#line 4228 "cs-parser.jay" + { + start_block (lexer.Location); + } break; case 606: case_606(); break; -case 607: - case_607(); - break; case 608: case_608(); break; @@ -3048,35 +3105,34 @@ case 612: case_612(); break; case 613: - case_613(); +#line 4273 "cs-parser.jay" + { + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + } break; case 614: case_614(); break; case 615: -#line 4149 "cs-parser.jay" - { yyVal = ParametersCompiled.EmptyReadOnlyParameters; } + case_615(); break; case 616: - case_616(); - break; -case 619: -#line 4164 "cs-parser.jay" +#line 4287 "cs-parser.jay" { - start_block (lexer.Location); + valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } break; -case 620: - case_620(); +case 617: + case_617(); break; -case 622: - case_622(); - break; -case 623: - case_623(); +case 618: + case_618(); break; case 624: - case_624(); +#line 4312 "cs-parser.jay" + { + yyVal = new ArglistAccess (GetLocation (yyVals[0+yyTop])); + } break; case 625: case_625(); @@ -3085,21 +3141,18 @@ case 626: case_626(); break; case 627: -#line 4209 "cs-parser.jay" - { - valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; - } - break; -case 628: - case_628(); + case_627(); break; case 629: - case_629(); +#line 4341 "cs-parser.jay" + { + yyVal = new BooleanExpression ((Expression) yyVals[0+yyTop]); + } break; case 630: -#line 4223 "cs-parser.jay" +#line 4354 "cs-parser.jay" { - valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; + lexer.ConstraintsParsing = true; } break; case 631: @@ -3108,32 +3161,43 @@ case 631: case 632: case_632(); break; +case 633: + case_633(); + break; +case 634: + case_634(); + break; +case 635: +#line 4397 "cs-parser.jay" + { yyVal = null; } + break; +case 636: +#line 4399 "cs-parser.jay" + { yyVal = yyVals[0+yyTop]; StoreModifierLocation (Modifiers.PARTIAL, GetLocation (yyVals[0+yyTop])); } + break; +case 637: + case_637(); + break; case 638: -#line 4248 "cs-parser.jay" +#line 4412 "cs-parser.jay" { - yyVal = new ArglistAccess (GetLocation (yyVals[0+yyTop])); + lexer.parsing_modifiers = false; } break; -case 639: - case_639(); - break; case 640: case_640(); break; case 641: case_641(); break; +case 642: + case_642(); + break; case 643: -#line 4277 "cs-parser.jay" - { - yyVal = new BooleanExpression ((Expression) yyVals[0+yyTop]); - } + case_643(); break; case 644: -#line 4290 "cs-parser.jay" - { - lexer.ConstraintsParsing = true; - } + case_644(); break; case 645: case_645(); @@ -3148,33 +3212,34 @@ case 648: case_648(); break; case 649: -#line 4329 "cs-parser.jay" - { yyVal = null; } + case_649(); break; case 650: -#line 4331 "cs-parser.jay" - { yyVal = yyVals[0+yyTop]; StoreModifierLocation (Modifiers.PARTIAL, GetLocation (yyVals[0+yyTop])); } + case_650(); break; case 651: case_651(); break; +case 652: + case_652(); + break; +case 653: + case_653(); + break; case 654: case_654(); break; case 655: case_655(); break; -case 656: - case_656(); - break; case 657: case_657(); break; -case 658: - case_658(); - break; case 659: - case_659(); +#line 4532 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } break; case 660: case_660(); @@ -3201,28 +3266,40 @@ case 667: case_667(); break; case 668: - case_668(); +#line 4623 "cs-parser.jay" + { + yyVal = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation (yyVals[0+yyTop])); + } break; case 669: - case_669(); +#line 4627 "cs-parser.jay" + { + yyVal = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation (yyVals[0+yyTop])); + } break; -case 671: -#line 4451 "cs-parser.jay" +case 670: +#line 4634 "cs-parser.jay" { - current_container.AddBasesForPart (current_class, (List) yyVals[0+yyTop]); - } + yyVal = Variance.None; + } + break; +case 671: + case_671(); + break; +case 672: + case_672(); break; case 673: -#line 4459 "cs-parser.jay" - { - yyVal = yyVals[0+yyTop]; - } + case_673(); break; case 674: case_674(); break; case 675: - case_675(); +#line 4679 "cs-parser.jay" + { + yyVal = yyVals[0+yyTop]; + } break; case 676: case_676(); @@ -3236,101 +3313,83 @@ case 678: case 679: case_679(); break; -case 680: - case_680(); - break; -case 681: - case_681(); - break; -case 682: -#line 4548 "cs-parser.jay" - { - yyVal = new SpecialContraintExpr (SpecialConstraint.Class, GetLocation (yyVals[0+yyTop])); - } - break; -case 683: -#line 4552 "cs-parser.jay" - { - yyVal = new SpecialContraintExpr (SpecialConstraint.Struct, GetLocation (yyVals[0+yyTop])); - } - break; case 684: -#line 4559 "cs-parser.jay" +#line 4723 "cs-parser.jay" { - yyVal = Variance.None; + current_block.AddStatement ((Statement) yyVals[0+yyTop]); } break; case 685: - case_685(); - break; -case 686: -#line 4573 "cs-parser.jay" +#line 4727 "cs-parser.jay" { - yyVal = Variance.Covariant; + current_block.AddStatement ((Statement) yyVals[0+yyTop]); } break; case 687: -#line 4577 "cs-parser.jay" + case_687(); + break; +case 690: +#line 4751 "cs-parser.jay" { - yyVal = Variance.Contravariant; + current_block.AddStatement ((Statement) yyVals[0+yyTop]); } break; -case 688: - case_688(); - break; -case 689: -#line 4602 "cs-parser.jay" +case 691: +#line 4755 "cs-parser.jay" { - yyVal = yyVals[0+yyTop]; + current_block.AddStatement ((Statement) yyVals[0+yyTop]); } break; -case 690: - case_690(); +case 720: + case_720(); break; -case 691: - case_691(); +case 721: + case_721(); break; -case 692: - case_692(); +case 722: + case_722(); break; -case 693: - case_693(); +case 723: + case_723(); break; -case 698: -#line 4646 "cs-parser.jay" - { - current_block.AddStatement ((Statement) yyVals[0+yyTop]); - } +case 724: + case_724(); break; -case 699: -#line 4650 "cs-parser.jay" - { - current_block.AddStatement ((Statement) yyVals[0+yyTop]); - } +case 727: + case_727(); + break; +case 728: + case_728(); break; -case 701: - case_701(); +case 729: + case_729(); break; -case 704: -#line 4674 "cs-parser.jay" +case 730: + case_730(); + break; +case 731: +#line 4899 "cs-parser.jay" { - current_block.AddStatement ((Statement) yyVals[0+yyTop]); + yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; -case 705: -#line 4678 "cs-parser.jay" +case 732: +#line 4903 "cs-parser.jay" { - current_block.AddStatement ((Statement) yyVals[0+yyTop]); + yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); } break; -case 734: - case_734(); +case 733: + case_733(); break; case 735: case_735(); break; case 736: - case_736(); +#line 4924 "cs-parser.jay" + { + yyVal = ComposedTypeSpecifier.CreatePointer (GetLocation (yyVals[0+yyTop])); + } break; case 737: case_737(); @@ -3338,8 +3397,11 @@ case 737: case 738: case_738(); break; -case 741: - case_741(); +case 739: + case_739(); + break; +case 740: + case_740(); break; case 742: case_742(); @@ -3347,89 +3409,77 @@ case 742: case 743: case_743(); break; -case 744: - case_744(); - break; -case 745: -#line 4822 "cs-parser.jay" - { - yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); - } - break; -case 746: -#line 4826 "cs-parser.jay" - { - yyVal = new ComposedCast (new TypeExpression (compiler.BuiltinTypes.Void, GetLocation (yyVals[-1+yyTop])), (ComposedTypeSpecifier) yyVals[0+yyTop]); - } - break; case 747: case_747(); break; -case 749: - case_749(); - break; case 750: -#line 4847 "cs-parser.jay" - { - yyVal = ComposedTypeSpecifier.CreatePointer (GetLocation (yyVals[0+yyTop])); - } + case_750(); break; case 751: case_751(); break; case 752: - case_752(); +#line 5024 "cs-parser.jay" + { + report.Error (145, lexer.Location, "A const field requires a value to be provided"); + } break; case 753: case_753(); break; -case 754: - case_754(); +case 758: + case_758(); break; -case 756: - case_756(); +case 760: + case_760(); break; -case 757: - case_757(); +case 761: + case_761(); break; case 762: case_762(); break; case 763: - case_763(); +#line 5074 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } break; case 764: -#line 4936 "cs-parser.jay" - { - report.Error (145, lexer.Location, "A const field requires a value to be provided"); - } +#line 5078 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } break; case 765: - case_765(); +#line 5079 "cs-parser.jay" + { yyVal = yyVals[-1+yyTop]; } + break; +case 766: + case_766(); + break; +case 767: + case_767(); + break; +case 768: + case_768(); break; -case 770: - case_770(); +case 771: + case_771(); break; case 772: case_772(); break; case 773: - case_773(); +#line 5147 "cs-parser.jay" + { + start_block (GetLocation (yyVals[0+yyTop])); + } break; case 774: case_774(); break; case 775: -#line 4986 "cs-parser.jay" - { yyVal = yyVals[-1+yyTop]; } - break; -case 776: -#line 4990 "cs-parser.jay" - { yyVal = yyVals[-1+yyTop]; } + case_775(); break; case 777: -#line 4991 "cs-parser.jay" - { yyVal = yyVals[-1+yyTop]; } + case_777(); break; case 778: case_778(); @@ -3438,7 +3488,19 @@ case 779: case_779(); break; case 780: - case_780(); +#line 5191 "cs-parser.jay" + { + current_block = current_block.CreateSwitchBlock (lexer.Location); + } + break; +case 781: +#line 5195 "cs-parser.jay" + { + yyVal = new SwitchSection ((List) yyVals[-2+yyTop], current_block); + } + break; +case 782: + case_782(); break; case 783: case_783(); @@ -3447,20 +3509,11 @@ case 784: case_784(); break; case 785: -#line 5059 "cs-parser.jay" +#line 5224 "cs-parser.jay" { - start_block (GetLocation (yyVals[0+yyTop])); + yyVal = new SwitchLabel (null, GetLocation (yyVals[0+yyTop])); } break; -case 786: - case_786(); - break; -case 787: - case_787(); - break; -case 789: - case_789(); - break; case 790: case_790(); break; @@ -3468,15 +3521,12 @@ case 791: case_791(); break; case 792: -#line 5103 "cs-parser.jay" - { - current_block = current_block.CreateSwitchBlock (lexer.Location); - } + case_792(); break; case 793: -#line 5107 "cs-parser.jay" +#line 5263 "cs-parser.jay" { - yyVal = new SwitchSection ((List) yyVals[-2+yyTop], current_block); + yyVal = yyVals[0+yyTop]; } break; case 794: @@ -3486,52 +3536,40 @@ case 795: case_795(); break; case 796: - case_796(); - break; -case 797: -#line 5136 "cs-parser.jay" - { - yyVal = new SwitchLabel (null, GetLocation (yyVals[0+yyTop])); - } - break; -case 802: - case_802(); +#line 5291 "cs-parser.jay" + { yyVal = new EmptyStatement (lexer.Location); } break; -case 803: - case_803(); +case 798: + case_798(); break; -case 804: - case_804(); +case 799: + case_799(); break; -case 805: -#line 5175 "cs-parser.jay" - { - yyVal = yyVals[0+yyTop]; - } +case 801: +#line 5312 "cs-parser.jay" + { yyVal = null; } break; -case 806: - case_806(); +case 803: +#line 5317 "cs-parser.jay" + { yyVal = new EmptyStatement (lexer.Location); } break; case 807: case_807(); break; case 808: -#line 5203 "cs-parser.jay" - { yyVal = new EmptyStatement (lexer.Location); } + case_808(); + break; +case 809: + case_809(); break; case 810: case_810(); break; -case 811: - case_811(); - break; -case 813: -#line 5224 "cs-parser.jay" - { yyVal = null; } +case 817: + case_817(); break; -case 815: -#line 5229 "cs-parser.jay" - { yyVal = new EmptyStatement (lexer.Location); } +case 818: + case_818(); break; case 819: case_819(); @@ -3545,6 +3583,21 @@ case 821: case 822: case_822(); break; +case 823: + case_823(); + break; +case 824: + case_824(); + break; +case 825: + case_825(); + break; +case 828: +#line 5472 "cs-parser.jay" + { + yyVal = new TryCatch ((Block) yyVals[-1+yyTop], (List) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop]), false); + } + break; case 829: case_829(); break; @@ -3560,32 +3613,44 @@ case 832: case 833: case_833(); break; -case 834: - case_834(); - break; -case 835: - case_835(); - break; case 836: - case_836(); +#line 5525 "cs-parser.jay" + { + yyVal = new Catch ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } break; case 837: case_837(); break; +case 838: +#line 5544 "cs-parser.jay" + { + yyVal = yyVals[-1+yyTop]; + } + break; +case 839: + case_839(); + break; case 840: -#line 5384 "cs-parser.jay" +#line 5562 "cs-parser.jay" { - yyVal = new TryCatch ((Block) yyVals[-1+yyTop], (List) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop]), false); + yyVal = new Checked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } break; case 841: - case_841(); +#line 5569 "cs-parser.jay" + { + yyVal = new Unchecked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + } break; case 842: case_842(); break; case 843: - case_843(); +#line 5579 "cs-parser.jay" + { + yyVal = new Unsafe ((Block) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); + } break; case 844: case_844(); @@ -3593,44 +3658,38 @@ case 844: case 845: case_845(); break; +case 846: + case_846(); + break; +case 847: + case_847(); + break; case 848: -#line 5437 "cs-parser.jay" - { - yyVal = new Catch ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } + case_848(); break; case 849: case_849(); break; case 850: -#line 5456 "cs-parser.jay" - { - yyVal = yyVals[-1+yyTop]; - } + case_850(); break; case 851: case_851(); break; case 852: -#line 5474 "cs-parser.jay" +#line 5662 "cs-parser.jay" { - yyVal = new Checked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); + Error_MissingInitializer (lexer.Location); } break; case 853: -#line 5481 "cs-parser.jay" - { - yyVal = new Unchecked ((Block) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); - } + case_853(); break; case 854: case_854(); break; case 855: -#line 5491 "cs-parser.jay" - { - yyVal = new Unsafe ((Block) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); - } + case_855(); break; case 856: case_856(); @@ -3651,15 +3710,18 @@ case 861: case_861(); break; case 862: - case_862(); +#line 5763 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } break; case 863: case_863(); break; case 864: -#line 5574 "cs-parser.jay" +#line 5778 "cs-parser.jay" { - report.Error (210, lexer.Location, "You must provide an initializer in a fixed or using statement declaration"); + current_block = new Linq.QueryBlock (current_block, lexer.Location); } break; case 865: @@ -3668,14 +3730,14 @@ case 865: case 866: case_866(); break; -case 867: - case_867(); - break; case 868: case_868(); break; case 869: - case_869(); +#line 5823 "cs-parser.jay" + { + current_block = new Linq.QueryBlock (current_block, lexer.Location); + } break; case 870: case_870(); @@ -3689,81 +3751,72 @@ case 872: case 873: case_873(); break; -case 874: -#line 5674 "cs-parser.jay" +case 877: + case_877(); + break; +case 883: +#line 5882 "cs-parser.jay" { - current_block = new Linq.QueryBlock (current_block, lexer.Location); + current_block = new Linq.QueryBlock (current_block, lexer.Location); } break; -case 875: - case_875(); +case 884: + case_884(); break; -case 876: -#line 5689 "cs-parser.jay" +case 885: +#line 5901 "cs-parser.jay" { - current_block = new Linq.QueryBlock (current_block, lexer.Location); + current_block = new Linq.QueryBlock (current_block, lexer.Location); } break; -case 877: - case_877(); +case 886: + case_886(); break; -case 878: - case_878(); +case 887: + case_887(); break; -case 880: - case_880(); +case 888: + case_888(); break; -case 881: -#line 5734 "cs-parser.jay" - { - current_block = new Linq.QueryBlock (current_block, lexer.Location); - } +case 889: + case_889(); break; -case 882: - case_882(); +case 890: + case_890(); break; -case 883: - case_883(); +case 891: + case_891(); break; -case 884: - case_884(); +case 892: + case_892(); break; -case 885: - case_885(); +case 893: + case_893(); break; -case 889: - case_889(); +case 894: + case_894(); break; -case 895: -#line 5793 "cs-parser.jay" +case 896: +#line 6045 "cs-parser.jay" { - current_block = new Linq.QueryBlock (current_block, lexer.Location); + yyVal = yyVals[0+yyTop]; } break; -case 896: - case_896(); - break; case 897: -#line 5812 "cs-parser.jay" +#line 6052 "cs-parser.jay" { - current_block = new Linq.QueryBlock (current_block, lexer.Location); + current_block = new Linq.QueryBlock (current_block, lexer.Location); } break; case 898: case_898(); break; -case 899: - case_899(); - break; case 900: case_900(); break; case 901: case_901(); break; -case 902: - case_902(); - break; case 903: case_903(); break; @@ -3771,22 +3824,25 @@ case 904: case_904(); break; case 905: - case_905(); +#line 6098 "cs-parser.jay" + { + yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); + } break; case 906: case_906(); break; +case 907: + case_907(); + break; case 908: -#line 5956 "cs-parser.jay" +#line 6115 "cs-parser.jay" { - yyVal = yyVals[0+yyTop]; + yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); } break; case 909: -#line 5963 "cs-parser.jay" - { - current_block = new Linq.QueryBlock (current_block, lexer.Location); - } + case_909(); break; case 910: case_910(); @@ -3797,122 +3853,86 @@ case 912: case 913: case_913(); break; -case 915: - case_915(); - break; case 916: case_916(); break; case 917: -#line 6009 "cs-parser.jay" - { - yyVal = new Linq.OrderByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); - } - break; -case 918: - case_918(); - break; -case 919: - case_919(); - break; -case 920: -#line 6026 "cs-parser.jay" - { - yyVal = new Linq.ThenByAscending ((Linq.QueryBlock) current_block, (Expression)yyVals[0+yyTop]); - } - break; -case 921: - case_921(); - break; -case 922: - case_922(); - break; -case 924: - case_924(); + case_917(); break; case 925: - case_925(); - break; -case 928: - case_928(); - break; -case 929: - case_929(); - break; -case 937: -#line 6150 "cs-parser.jay" +#line 6239 "cs-parser.jay" { module.DocumentationBuilder.ParsedName = (MemberName) yyVals[0+yyTop]; } break; -case 938: -#line 6157 "cs-parser.jay" +case 926: +#line 6246 "cs-parser.jay" { module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; } break; -case 939: - case_939(); +case 927: + case_927(); break; -case 940: - case_940(); +case 928: + case_928(); break; -case 941: -#line 6174 "cs-parser.jay" +case 929: +#line 6263 "cs-parser.jay" { yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], new MemberName (MemberCache.IndexerNameAlias)); } break; -case 942: -#line 6178 "cs-parser.jay" +case 930: +#line 6267 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } break; -case 943: - case_943(); +case 931: + case_931(); break; -case 944: - case_944(); +case 932: + case_932(); break; -case 945: - case_945(); +case 933: + case_933(); break; -case 946: - case_946(); +case 934: + case_934(); break; -case 948: -#line 6214 "cs-parser.jay" +case 936: +#line 6303 "cs-parser.jay" { yyVal = new MemberName (((MemberName) yyVals[-2+yyTop]), (MemberName) yyVals[0+yyTop]); } break; -case 950: -#line 6222 "cs-parser.jay" +case 938: +#line 6311 "cs-parser.jay" { valid_param_mod = ParameterModifierType.Ref | ParameterModifierType.Out; } break; -case 951: -#line 6226 "cs-parser.jay" +case 939: +#line 6315 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; } break; -case 952: -#line 6233 "cs-parser.jay" +case 940: +#line 6322 "cs-parser.jay" { yyVal = new List (0); } break; -case 954: - case_954(); +case 942: + case_942(); break; -case 955: - case_955(); +case 943: + case_943(); break; -case 956: - case_956(); +case 944: + case_944(); break; #line default } @@ -3950,7 +3970,7 @@ case 956: All more than 3 lines long rules are wrapped into a method */ void case_6() -#line 403 "cs-parser.jay" +#line 408 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { Attributes attrs = (Attributes) yyVals[0+yyTop]; @@ -3960,7 +3980,7 @@ void case_6() } void case_8() -#line 415 "cs-parser.jay" +#line 420 "cs-parser.jay" { if (yyToken == Token.EXTERN_ALIAS) report.Error (439, lexer.Location, "An extern alias declaration must precede all other elements"); @@ -3969,7 +3989,7 @@ void case_8() } void case_13() -#line 435 "cs-parser.jay" +#line 440 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; string s = lt.Value; @@ -3985,21 +4005,21 @@ void case_13() } void case_17() -#line 461 "cs-parser.jay" +#line 466 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } void case_18() -#line 466 "cs-parser.jay" +#line 471 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } void case_19() -#line 474 "cs-parser.jay" +#line 479 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; if (lang_version != LanguageVersion.ISO_1 && lt.Value == "global") { @@ -4012,21 +4032,21 @@ void case_19() } void case_20() -#line 485 "cs-parser.jay" +#line 490 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } void case_21() -#line 493 "cs-parser.jay" +#line 498 "cs-parser.jay" { current_namespace.AddUsing ((MemberName) yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); ubag.AddUsing (GetLocation (yyVals[-2+yyTop]), (MemberName) yyVals[-1+yyTop], GetLocation (yyVals[0+yyTop])); } void case_22() -#line 506 "cs-parser.jay" +#line 511 "cs-parser.jay" { Attributes attrs = (Attributes) yyVals[-2+yyTop]; MemberName name = (MemberName) yyVals[0+yyTop]; @@ -4059,7 +4079,7 @@ void case_22() } void case_23() -#line 537 "cs-parser.jay" +#line 542 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; @@ -4067,43 +4087,43 @@ void case_23() } void case_24() -#line 543 "cs-parser.jay" +#line 548 "cs-parser.jay" { - if (yyVals[0+yyTop] != null) - lbag.AddLocation (current_namespace, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); - else - lbag.AddLocation (current_namespace, GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-1+yyTop])); - current_namespace = current_namespace.Parent; current_class = current_namespace.SlaveDeclSpace; current_container = current_class.PartialContainer; ubag.CloseNamespace (GetLocation (yyVals[-1+yyTop])); - ubag.EndNamespace (GetLocation (yyVals[-1+yyTop])); + if (yyVals[0+yyTop] != null) + ubag.EndNamespace (GetLocation (yyVals[0+yyTop])); + else + ubag.EndNamespace (); } void case_25() -#line 559 "cs-parser.jay" +#line 562 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new MemberName (lt.Value, lt.Location); } void case_26() -#line 564 "cs-parser.jay" +#line 567 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; - yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], lt.Value, lt.Location); + yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], lt.Value, lt.Location) { + DotLocation = GetLocation (yyVals[-1+yyTop]) + }; } void case_27() -#line 569 "cs-parser.jay" +#line 574 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new MemberName ("", lexer.Location); } void case_32() -#line 587 "cs-parser.jay" +#line 592 "cs-parser.jay" { MemberName name = (MemberName) yyVals[0+yyTop]; @@ -4114,7 +4134,7 @@ void case_32() } void case_41() -#line 619 "cs-parser.jay" +#line 624 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { TypeContainer ds = (TypeContainer)yyVals[0+yyTop]; @@ -4135,42 +4155,49 @@ void case_41() } void case_50() -#line 669 "cs-parser.jay" +#line 674 "cs-parser.jay" { var sect = (List) yyVals[0+yyTop]; yyVal = new Attributes (sect); - lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + if (locationListStack.Count > 0) + lbag.AddLocation (sect, locationListStack.Pop ()); + if (attributeCommas.Count > 0) { + lbag.AppendTo (sect, attributeCommas); + attributeCommas.Clear (); + } } void case_51() -#line 675 "cs-parser.jay" +#line 685 "cs-parser.jay" { Attributes attrs = yyVals[-1+yyTop] as Attributes; var sect = (List) yyVals[0+yyTop]; + + if (locationListStack.Count > 0) + lbag.AddLocation (sect, locationListStack.Pop ()); if (attrs == null) attrs = new Attributes (sect); else attrs.AddAttributes (sect); - lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); yyVal = attrs; } void case_52() -#line 689 "cs-parser.jay" +#line 701 "cs-parser.jay" { lexer.parsing_attribute_section = true; savedOpenLocation = GetLocation (yyVals[0+yyTop]); } void case_53() -#line 694 "cs-parser.jay" +#line 706 "cs-parser.jay" { lexer.parsing_attribute_section = false; yyVal = yyVals[0+yyTop]; } void case_54() -#line 702 "cs-parser.jay" +#line 714 "cs-parser.jay" { current_attr_target = (string) yyVals[-1+yyTop]; if (current_attr_target == "assembly" || current_attr_target == "module") { @@ -4179,7 +4206,7 @@ void case_54() } void case_55() -#line 709 "cs-parser.jay" +#line 721 "cs-parser.jay" { /* when attribute target is invalid*/ if (current_attr_target == string.Empty) @@ -4189,25 +4216,34 @@ void case_55() current_attr_target = null; lexer.parsing_attribute_section = false; - savedCloseLocation = GetLocation (yyVals[0+yyTop]); + if (yyVals[-1+yyTop] != null) { + locationListStack.Push (new List(new [] { savedOpenLocation, savedCloseLocation, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop]) })); + } else { + locationListStack.Push (new List(new [] { savedOpenLocation, savedCloseLocation, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[0+yyTop]) })); + } } void case_56() -#line 721 "cs-parser.jay" +#line 737 "cs-parser.jay" { yyVal = yyVals[-2+yyTop]; - savedCloseLocation = GetLocation (yyVals[0+yyTop]); + if (yyVals[-1+yyTop] != null) { + locationListStack.Push (new List(new [] { savedOpenLocation, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop]) })); + } else { + locationListStack.Push (new List(new [] { savedOpenLocation, GetLocation (yyVals[0+yyTop]) })); + } } void case_57() -#line 729 "cs-parser.jay" +#line 749 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = CheckAttributeTarget (lt.Value, lt.Location); + savedCloseLocation = GetLocation (yyVals[0+yyTop]); } void case_60() -#line 736 "cs-parser.jay" +#line 757 "cs-parser.jay" { if (yyToken == Token.IDENTIFIER) { Error_SyntaxError (yyToken); @@ -4219,16 +4255,17 @@ void case_60() } void case_62() -#line 753 "cs-parser.jay" +#line 774 "cs-parser.jay" { var attrs = (List) yyVals[-2+yyTop]; attrs.Add ((Attribute) yyVals[0+yyTop]); + attributeCommas.Add (GetLocation (yyVals[-1+yyTop])); yyVal = attrs; } void case_64() -#line 767 "cs-parser.jay" +#line 789 "cs-parser.jay" { --lexer.parsing_block; MemberName mname = (MemberName) yyVals[-2+yyTop]; @@ -4241,12 +4278,15 @@ void case_64() ATypeNameExpression expr = mname.GetTypeExpression (); yyVal = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname)); if (arguments != null) { - lbag.AddLocation (yyVal, savedAttrParenOpenLocation, savedAttrParenCloseLocation); + attributeArgumentCommas.Insert (0, savedAttrParenOpenLocation); + attributeArgumentCommas.Add (savedAttrParenCloseLocation); + lbag.AddLocation (yyVal, attributeArgumentCommas); + attributeArgumentCommas.Clear (); } } void case_67() -#line 791 "cs-parser.jay" +#line 816 "cs-parser.jay" { savedAttrParenOpenLocation = GetLocation (yyVals[-2+yyTop]); savedAttrParenCloseLocation = GetLocation (yyVals[0+yyTop]); @@ -4254,7 +4294,7 @@ void case_67() } void case_69() -#line 802 "cs-parser.jay" +#line 827 "cs-parser.jay" { Arguments a = new Arguments (4); a.Add ((Argument) yyVals[0+yyTop]); @@ -4262,7 +4302,7 @@ void case_69() } void case_70() -#line 808 "cs-parser.jay" +#line 833 "cs-parser.jay" { Arguments a = new Arguments (4); a.Add ((Argument) yyVals[0+yyTop]); @@ -4270,7 +4310,7 @@ void case_70() } void case_71() -#line 814 "cs-parser.jay" +#line 839 "cs-parser.jay" { Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; if (o [1] != null) { @@ -4283,11 +4323,11 @@ void case_71() Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) yyVals[0+yyTop]); - lbag.AppendTo (args, GetLocation (yyVals[-1+yyTop])); + attributeArgumentCommas.Add (GetLocation (yyVals[-1+yyTop])); } void case_72() -#line 829 "cs-parser.jay" +#line 854 "cs-parser.jay" { Arguments[] o = (Arguments[]) yyVals[-2+yyTop]; if (o [1] == null) { @@ -4295,11 +4335,11 @@ void case_72() } ((Arguments) o [1]).Add ((Argument) yyVals[0+yyTop]); - lbag.AppendTo (o[1], GetLocation (yyVals[-1+yyTop])); + attributeArgumentCommas.Add (GetLocation (yyVals[-1+yyTop])); } void case_76() -#line 854 "cs-parser.jay" +#line 879 "cs-parser.jay" { --lexer.parsing_block; var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; @@ -4308,7 +4348,7 @@ void case_76() } void case_77() -#line 864 "cs-parser.jay" +#line 889 "cs-parser.jay" { if (lang_version <= LanguageVersion.V_3) FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "named argument"); @@ -4318,10 +4358,11 @@ void case_77() var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; yyVal = new NamedArgument (lt.Value, lt.Location, (Expression) yyVals[0+yyTop], arg_mod); + lbag.AddLocation (yyVal, GetLocation(yyVals[-2+yyTop])); } void case_95() -#line 911 "cs-parser.jay" +#line 942 "cs-parser.jay" { report.Error (1519, lexer.Location, "Unexpected symbol `{0}' in class, struct, or interface member declaration", GetSymbolName (yyToken)); @@ -4330,14 +4371,15 @@ void case_95() } void case_97() -#line 928 "cs-parser.jay" +#line 959 "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]); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-2+yyTop])); } void case_98() -#line 934 "cs-parser.jay" +#line 966 "cs-parser.jay" { lexer.ConstraintsParsing = false; @@ -4346,32 +4388,35 @@ void case_98() if (doc_support) current_container.DocComment = Lexer.consume_doc_comment (); - lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-5+yyTop])); + + lexer.parsing_modifiers = true; } void case_99() -#line 945 "cs-parser.jay" +#line 978 "cs-parser.jay" { - --lexer.parsing_declaration; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } void case_100() -#line 951 "cs-parser.jay" +#line 983 "cs-parser.jay" { - lbag.AppendToMember (current_class, GetLocation (yyVals[0+yyTop])); - yyVal = pop_current_class (); + lbag.AppendToMember (current_class, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); + --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; } -void case_102() -#line 963 "cs-parser.jay" +void case_101() +#line 990 "cs-parser.jay" { - if (doc_support) - Lexer.doc_state = XmlCommentState.Allowed; + if (yyVals[-1+yyTop] != null) + current_class.OptionalSemicolon = GetLocation (yyVals[-1+yyTop]); + yyVal = pop_current_class (); } -void case_118() +void case_103() #line 1005 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; @@ -4386,7 +4431,7 @@ void case_118() yyVal = current_field; } -void case_119() +void case_104() #line 1018 "cs-parser.jay" { if (doc_support) { @@ -4399,7 +4444,7 @@ void case_119() current_field = null; } -void case_124() +void case_109() #line 1048 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -4407,7 +4452,7 @@ void case_124() lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); } -void case_126() +void case_111() #line 1061 "cs-parser.jay" { --lexer.parsing_block; @@ -4415,14 +4460,14 @@ void case_126() lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); } -void case_127() +void case_112() #line 1067 "cs-parser.jay" { report.Error (145, lexer.Location, "A const field requires a value to be provided"); yyVal = null; } -void case_130() +void case_115() #line 1082 "cs-parser.jay" { lexer.parsing_generic_declaration = false; @@ -4437,7 +4482,7 @@ void case_130() yyVal = current_field; } -void case_131() +void case_116() #line 1097 "cs-parser.jay" { if (doc_support) { @@ -4450,7 +4495,7 @@ void case_131() current_field = null; } -void case_132() +void case_117() #line 1110 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) @@ -4463,7 +4508,7 @@ void case_132() current_container.AddField (current_field); } -void case_133() +void case_118() #line 1121 "cs-parser.jay" { if (doc_support) { @@ -4477,7 +4522,7 @@ void case_133() current_field = null; } -void case_136() +void case_121() #line 1144 "cs-parser.jay" { ++lexer.parsing_block; @@ -4485,7 +4530,7 @@ void case_136() start_block (GetLocation (yyVals[0+yyTop])); } -void case_137() +void case_122() #line 1150 "cs-parser.jay" { --lexer.parsing_block; @@ -4495,7 +4540,7 @@ void case_137() current_local_parameters = null; } -void case_142() +void case_127() #line 1177 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; @@ -4503,7 +4548,7 @@ void case_142() lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } -void case_144() +void case_129() #line 1187 "cs-parser.jay" { --lexer.parsing_block; @@ -4512,7 +4557,7 @@ void case_144() lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); } -void case_149() +void case_134() #line 1213 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -4520,7 +4565,7 @@ void case_149() lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); } -void case_151() +void case_136() #line 1226 "cs-parser.jay" { --lexer.parsing_block; @@ -4528,14 +4573,14 @@ void case_151() lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_152() +void case_137() #line 1232 "cs-parser.jay" { report.Error (443, lexer.Location, "Value or constant expected"); yyVal = null; } -void case_155() +void case_140() #line 1242 "cs-parser.jay" { /* It has to be here for the parent to safely restore artificial block*/ @@ -4543,23 +4588,27 @@ void case_155() yyVal = null; } -void case_156() +void case_141() #line 1251 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.NotAllowed; - /* Add it early in the case of body being eof for full aot*/ - current_container.AddMethod ((Method) yyVals[0+yyTop]); + /* Add it early in the case of body being eof for full ast*/ + Method m = (Method) yyVals[0+yyTop]; + lexer.async_block = (m.ModFlags & Modifiers.ASYNC) != 0; + current_container.AddMethod (m); } -void case_157() -#line 1259 "cs-parser.jay" +void case_142() +#line 1261 "cs-parser.jay" { Method method = (Method) yyVals[-2+yyTop]; method.Block = (ToplevelBlock) yyVals[0+yyTop]; + lexer.async_block = false; if (method.Block == null) { + lbag.AppendToMember (method, savedLocation); /* semicolon*/ method.ParameterInfo.CheckParameters (method); if ((method.ModFlags & Modifiers.ASYNC) != 0) { @@ -4579,8 +4628,8 @@ void case_157() Lexer.doc_state = XmlCommentState.Allowed; } -void case_160() -#line 1297 "cs-parser.jay" +void case_145() +#line 1301 "cs-parser.jay" { lexer.ConstraintsParsing = false; valid_param_mod = 0; @@ -4614,15 +4663,15 @@ void case_160() yyVal = method; } -void case_162() -#line 1338 "cs-parser.jay" +void case_147() +#line 1342 "cs-parser.jay" { lexer.parsing_generic_declaration = false; valid_param_mod = ParameterModifierType.All; } -void case_164() -#line 1347 "cs-parser.jay" +void case_149() +#line 1351 "cs-parser.jay" { lexer.ConstraintsParsing = false; valid_param_mod = 0; @@ -4673,8 +4722,8 @@ void case_164() yyVal = method; } -void case_165() -#line 1400 "cs-parser.jay" +void case_150() +#line 1404 "cs-parser.jay" { MemberName name = (MemberName) yyVals[-3+yyTop]; report.Error (1585, name.Location, @@ -4691,91 +4740,104 @@ void case_165() yyVal = method; } -void case_170() -#line 1429 "cs-parser.jay" +void case_155() +#line 1433 "cs-parser.jay" { var pars_list = (List) yyVals[0+yyTop]; yyVal = new ParametersCompiled (pars_list.ToArray ()); - lbag.AddLocation (yyVal, lbag.GetLocations (pars_list)); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_171() -#line 1435 "cs-parser.jay" +void case_156() +#line 1439 "cs-parser.jay" { var pars_list = (List) yyVals[-2+yyTop]; pars_list.Add ((Parameter) yyVals[0+yyTop]); - + parameterListCommas.Add (GetLocation (yyVals[-1+yyTop])); + yyVal = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_172() -#line 1442 "cs-parser.jay" +void case_157() +#line 1448 "cs-parser.jay" { var pars_list = (List) yyVals[-2+yyTop]; pars_list.Add (new ArglistParameter (GetLocation (yyVals[0+yyTop]))); + parameterListCommas.Add (GetLocation (yyVals[-1+yyTop])); + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_173() -#line 1448 "cs-parser.jay" +void case_158() +#line 1457 "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"); yyVal = new ParametersCompiled (new Parameter[] { (Parameter) yyVals[-2+yyTop] } ); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_174() -#line 1455 "cs-parser.jay" +void case_159() +#line 1465 "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"); var pars_list = (List) yyVals[-4+yyTop]; pars_list.Add (new ArglistParameter (GetLocation (yyVals[-2+yyTop]))); - + parameterListCommas.Add (GetLocation (yyVals[-3+yyTop])); + parameterListCommas.Add (GetLocation (yyVals[-1+yyTop])); + yyVal = new ParametersCompiled (pars_list.ToArray (), true); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_175() -#line 1465 "cs-parser.jay" +void case_160() +#line 1478 "cs-parser.jay" { report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); yyVal = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation (yyVals[-2+yyTop])) }, true); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_176() -#line 1471 "cs-parser.jay" +void case_161() +#line 1485 "cs-parser.jay" { report.Error (257, GetLocation (yyVals[-2+yyTop]), "An __arglist parameter must be the last parameter in a formal parameter list"); var pars_list = (List) yyVals[-4+yyTop]; pars_list.Add (new ArglistParameter (GetLocation (yyVals[-2+yyTop]))); + parameterListCommas.Add (GetLocation (yyVals[-3+yyTop])); + parameterListCommas.Add (GetLocation (yyVals[-1+yyTop])); yyVal = new ParametersCompiled (pars_list.ToArray (), true); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_179() -#line 1488 "cs-parser.jay" +void case_164() +#line 1505 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = ParametersCompiled.EmptyReadOnlyParameters; } -void case_180() -#line 1496 "cs-parser.jay" +void case_165() +#line 1513 "cs-parser.jay" { parameters_bucket.Clear (); Parameter p = (Parameter) yyVals[0+yyTop]; parameters_bucket.Add (p); - + parameterListCommas.Clear (); default_parameter_used = p.HasDefaultValue; yyVal = parameters_bucket; } -void case_181() -#line 1505 "cs-parser.jay" +void case_166() +#line 1522 "cs-parser.jay" { var pars = (List) yyVals[-2+yyTop]; Parameter p = (Parameter) yyVals[0+yyTop]; @@ -4788,22 +4850,22 @@ void case_181() default_parameter_used |= p.HasDefaultValue; pars.Add (p); - lbag.AppendTo (pars, GetLocation (yyVals[-1+yyTop])); + parameterListCommas.Add (GetLocation (yyVals[-1+yyTop])); } yyVal = yyVals[-2+yyTop]; } -void case_182() -#line 1529 "cs-parser.jay" +void case_167() +#line 1546 "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); lbag.AddLocation (yyVal, parameterModifierLocation); } -void case_183() -#line 1538 "cs-parser.jay" +void case_168() +#line 1555 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; report.Error (1552, lt.Location, "Array type specifier, [], must appear before parameter name"); @@ -4811,8 +4873,8 @@ void case_183() lbag.AddLocation (yyVal, parameterModifierLocation); } -void case_184() -#line 1548 "cs-parser.jay" +void case_169() +#line 1565 "cs-parser.jay" { Error_SyntaxError (yyToken); Location l = GetLocation (yyVals[0+yyTop]); @@ -4820,8 +4882,8 @@ void case_184() lbag.AddLocation (yyVal, parameterModifierLocation); } -void case_186() -#line 1563 "cs-parser.jay" +void case_171() +#line 1580 "cs-parser.jay" { --lexer.parsing_block; if (lang_version <= LanguageVersion.V_3) { @@ -4859,15 +4921,8 @@ void case_186() ((Parameter) yyVal).DefaultValue = new DefaultParameterValueExpression ((Expression) yyVals[0+yyTop]); } -void case_189() -#line 1608 "cs-parser.jay" -{ - yyVal = yyVals[0+yyTop]; - parameterModifierLocation = GetLocation (yyVals[0+yyTop]); - } - -void case_190() -#line 1613 "cs-parser.jay" +void case_175() +#line 1629 "cs-parser.jay" { Parameter.Modifier p2 = (Parameter.Modifier)yyVals[0+yyTop]; Parameter.Modifier mod = (Parameter.Modifier)yyVals[-1+yyTop] | p2; @@ -4889,68 +4944,71 @@ void case_190() yyVal = mod; } -void case_191() -#line 1637 "cs-parser.jay" +void case_176() +#line 1653 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.Ref) == 0) Error_ParameterModifierNotValid ("ref", GetLocation (yyVals[0+yyTop])); - + parameterModifierLocation = GetLocation (yyVals[0+yyTop]); yyVal = Parameter.Modifier.REF; } -void case_192() -#line 1644 "cs-parser.jay" +void case_177() +#line 1660 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.Out) == 0) Error_ParameterModifierNotValid ("out", GetLocation (yyVals[0+yyTop])); - + parameterModifierLocation = GetLocation (yyVals[0+yyTop]); yyVal = Parameter.Modifier.OUT; } -void case_193() -#line 1651 "cs-parser.jay" +void case_178() +#line 1667 "cs-parser.jay" { if ((valid_param_mod & ParameterModifierType.This) == 0) Error_ParameterModifierNotValid ("this", GetLocation (yyVals[0+yyTop])); if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "extension methods"); - + parameterModifierLocation = GetLocation (yyVals[0+yyTop]); yyVal = Parameter.Modifier.This; } -void case_194() -#line 1664 "cs-parser.jay" +void case_179() +#line 1680 "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); + lbag.AddLocation (yyVal, savedLocation); } -void case_195() -#line 1669 "cs-parser.jay" +void case_180() +#line 1686 "cs-parser.jay" { report.Error (1751, GetLocation (yyVals[-4+yyTop]), "Cannot specify a default value for a parameter array"); var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new ParamsParameter ((FullNamedExpression) yyVals[-3+yyTop], lt.Value, (Attributes) yyVals[-5+yyTop], lt.Location); + lbag.AddLocation (yyVal, savedLocation); } -void case_196() -#line 1676 "cs-parser.jay" +void case_181() +#line 1694 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } -void case_197() -#line 1684 "cs-parser.jay" +void case_182() +#line 1702 "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"); + savedLocation = GetLocation (yyVals[0+yyTop]); } -void case_198() -#line 1689 "cs-parser.jay" +void case_183() +#line 1708 "cs-parser.jay" { Parameter.Modifier mod = (Parameter.Modifier)yyVals[0+yyTop]; if ((mod & Parameter.Modifier.This) != 0) { @@ -4958,24 +5016,25 @@ void case_198() } else { report.Error (1611, GetLocation (yyVals[-1+yyTop]), "The params parameter cannot be declared as ref or out"); } + savedLocation = GetLocation (yyVals[-1+yyTop]); } -void case_200() -#line 1705 "cs-parser.jay" +void case_185() +#line 1725 "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" +void case_186() +#line 1736 "cs-parser.jay" { if (doc_support) tmpComment = Lexer.consume_doc_comment (); } -void case_202() -#line 1721 "cs-parser.jay" +void case_187() +#line 1741 "cs-parser.jay" { var type = (FullNamedExpression) yyVals[-3+yyTop]; current_property = new Property (current_class, type, (Modifiers) yyVals[-4+yyTop], @@ -4990,8 +5049,8 @@ void case_202() lexer.PropertyParsing = true; } -void case_203() -#line 1735 "cs-parser.jay" +void case_188() +#line 1755 "cs-parser.jay" { lexer.PropertyParsing = false; @@ -4999,15 +5058,15 @@ void case_203() current_property.DocComment = ConsumeStoredComment (); } -void case_204() -#line 1742 "cs-parser.jay" +void case_189() +#line 1762 "cs-parser.jay" { lbag.AppendToMember (current_property, GetLocation (yyVals[0+yyTop])); current_property = null; } -void case_206() -#line 1756 "cs-parser.jay" +void case_191() +#line 1776 "cs-parser.jay" { valid_param_mod = 0; var type = (FullNamedExpression) yyVals[-6+yyTop]; @@ -5033,8 +5092,8 @@ void case_206() lexer.PropertyParsing = true; } -void case_208() -#line 1785 "cs-parser.jay" +void case_193() +#line 1805 "cs-parser.jay" { if (current_property.AccessorFirst != null && current_property.AccessorFirst.Block == null) ((Indexer) current_property).ParameterInfo.CheckParameters (current_property); @@ -5046,8 +5105,8 @@ void case_208() current_property = null; } -void case_213() -#line 1804 "cs-parser.jay" +void case_198() +#line 1824 "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 ()); @@ -5059,8 +5118,8 @@ void case_213() } } -void case_214() -#line 1818 "cs-parser.jay" +void case_199() +#line 1838 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); @@ -5079,12 +5138,11 @@ void case_214() } current_local_parameters = current_property.Get.ParameterInfo; - lbag.AddMember (current_property.Get, GetModifierLocations ()); lexer.PropertyParsing = false; } -void case_215() -#line 1840 "cs-parser.jay" +void case_200() +#line 1859 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { current_property.Get.Block = (ToplevelBlock) yyVals[0+yyTop]; @@ -5092,7 +5150,10 @@ void case_215() if (current_container.Kind == MemberKind.Interface) { report.Error (531, current_property.Get.Block.StartLocation, "`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); - } + } + lbag.AddMember (current_property.Get, GetModifierLocations ()); + } else { + lbag.AddMember (current_property.Get, GetModifierLocations (), savedLocation); } current_local_parameters = null; @@ -5103,8 +5164,8 @@ void case_215() Lexer.doc_state = XmlCommentState.NotAllowed; } -void case_216() -#line 1861 "cs-parser.jay" +void case_201() +#line 1883 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "access modifiers on properties"); @@ -5128,12 +5189,11 @@ void case_216() } current_local_parameters = current_property.Set.ParameterInfo; - lbag.AddMember (current_property.Set, GetModifierLocations ()); lexer.PropertyParsing = false; } -void case_217() -#line 1888 "cs-parser.jay" +void case_202() +#line 1909 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { current_property.Set.Block = (ToplevelBlock) yyVals[0+yyTop]; @@ -5142,6 +5202,9 @@ void case_217() report.Error (531, current_property.Set.Block.StartLocation, "`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); } + lbag.AddMember (current_property.Set, GetModifierLocations ()); + } else { + lbag.AddMember (current_property.Set, GetModifierLocations (), savedLocation); } current_local_parameters = null; @@ -5152,30 +5215,30 @@ void case_217() Lexer.doc_state = XmlCommentState.NotAllowed; } -void case_219() -#line 1910 "cs-parser.jay" +void case_204() +#line 1934 "cs-parser.jay" { - lbag.AppendToMember (lbag.LastMember, GetLocation (yyVals[0+yyTop])); + savedLocation = GetLocation (yyVals[0+yyTop]); yyVal = null; } -void case_220() -#line 1915 "cs-parser.jay" +void case_205() +#line 1939 "cs-parser.jay" { Error_SyntaxError (1043, yyToken, "Invalid accessor body"); yyVal = null; } -void case_222() -#line 1930 "cs-parser.jay" +void case_207() +#line 1954 "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]); lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-2+yyTop])); } -void case_223() -#line 1937 "cs-parser.jay" +void case_208() +#line 1961 "cs-parser.jay" { lexer.ConstraintsParsing = false; @@ -5185,25 +5248,29 @@ void case_223() current_container.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } + + lexer.parsing_modifiers = true; } -void case_224() -#line 1948 "cs-parser.jay" +void case_209() +#line 1974 "cs-parser.jay" { --lexer.parsing_declaration; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } -void case_225() -#line 1954 "cs-parser.jay" +void case_210() +#line 1980 "cs-parser.jay" { - lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + if (yyVals[0+yyTop] != null) + current_class.OptionalSemicolon = GetLocation (yyVals[0+yyTop]); + lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); yyVal = pop_current_class (); } -void case_241() -#line 2006 "cs-parser.jay" +void case_226() +#line 2040 "cs-parser.jay" { OperatorDeclaration decl = (OperatorDeclaration) yyVals[-2+yyTop]; if (decl != null) { @@ -5224,20 +5291,23 @@ void case_241() current_container.AddOperator (op); lbag.AddMember (op, GetModifierLocations (), lbag.GetLocations (decl)); + if (yyVals[0+yyTop] == null) { /* Semicolon*/ + lbag.AppendTo (op, savedLocation); + } } current_local_parameters = null; } -void case_245() -#line 2040 "cs-parser.jay" +void case_230() +#line 2077 "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" +void case_232() +#line 2089 "cs-parser.jay" { valid_param_mod = 0; @@ -5275,11 +5345,11 @@ void case_247() } yyVal = new OperatorDeclaration (op, (FullNamedExpression) yyVals[-6+yyTop], loc); - lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), savedOperatorLocation, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_272() -#line 2128 "cs-parser.jay" +void case_257() +#line 2165 "cs-parser.jay" { valid_param_mod = 0; @@ -5295,8 +5365,8 @@ void case_272() lbag.AddLocation (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_274() -#line 2147 "cs-parser.jay" +void case_259() +#line 2184 "cs-parser.jay" { valid_param_mod = 0; @@ -5312,24 +5382,24 @@ void case_274() lbag.AddLocation (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_275() -#line 2162 "cs-parser.jay" +void case_260() +#line 2199 "cs-parser.jay" { Error_SyntaxError (yyToken); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; yyVal = new OperatorDeclaration (Operator.OpType.Implicit, null, GetLocation (yyVals[-1+yyTop])); } -void case_276() -#line 2168 "cs-parser.jay" +void case_261() +#line 2205 "cs-parser.jay" { Error_SyntaxError (yyToken); current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; yyVal = new OperatorDeclaration (Operator.OpType.Explicit, null, GetLocation (yyVals[-1+yyTop])); } -void case_277() -#line 2178 "cs-parser.jay" +void case_262() +#line 2215 "cs-parser.jay" { Constructor c = (Constructor) yyVals[-1+yyTop]; c.Block = (ToplevelBlock) yyVals[0+yyTop]; @@ -5344,8 +5414,8 @@ void case_277() Lexer.doc_state = XmlCommentState.Allowed; } -void case_278() -#line 2197 "cs-parser.jay" +void case_263() +#line 2234 "cs-parser.jay" { if (doc_support) { tmpComment = Lexer.consume_doc_comment (); @@ -5355,8 +5425,8 @@ void case_278() valid_param_mod = ParameterModifierType.All; } -void case_279() -#line 2206 "cs-parser.jay" +void case_264() +#line 2243 "cs-parser.jay" { valid_param_mod = 0; current_local_parameters = (ParametersCompiled) yyVals[-1+yyTop]; @@ -5368,8 +5438,8 @@ void case_279() start_block (lexer.Location); } -void case_280() -#line 2217 "cs-parser.jay" +void case_265() +#line 2254 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-6+yyTop]; var mods = (Modifiers) yyVals[-7+yyTop]; @@ -5398,31 +5468,31 @@ void case_280() yyVal = c; } -void case_286() -#line 2262 "cs-parser.jay" +void case_271() +#line 2299 "cs-parser.jay" { --lexer.parsing_block; yyVal = new ConstructorBaseInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_288() -#line 2272 "cs-parser.jay" +void case_273() +#line 2309 "cs-parser.jay" { --lexer.parsing_block; yyVal = new ConstructorThisInitializer ((Arguments) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_289() -#line 2278 "cs-parser.jay" +void case_274() +#line 2315 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } -void case_290() -#line 2286 "cs-parser.jay" +void case_275() +#line 2323 "cs-parser.jay" { if (doc_support) { tmpComment = Lexer.consume_doc_comment (); @@ -5432,8 +5502,8 @@ void case_290() current_local_parameters = ParametersCompiled.EmptyReadOnlyParameters; } -void case_291() -#line 2295 "cs-parser.jay" +void case_276() +#line 2332 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; if (lt.Value != current_container.MemberName.Name){ @@ -5454,8 +5524,8 @@ void case_291() current_local_parameters = null; } -void case_292() -#line 2320 "cs-parser.jay" +void case_277() +#line 2357 "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); @@ -5468,8 +5538,8 @@ void case_292() yyVal = current_event_field; } -void case_293() -#line 2334 "cs-parser.jay" +void case_278() +#line 2371 "cs-parser.jay" { if (doc_support) { current_event_field.DocComment = Lexer.consume_doc_comment (); @@ -5480,8 +5550,8 @@ void case_293() current_event_field = null; } -void case_294() -#line 2347 "cs-parser.jay" +void case_279() +#line 2384 "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); @@ -5490,8 +5560,8 @@ void case_294() lexer.EventParsing = true; } -void case_295() -#line 2355 "cs-parser.jay" +void case_280() +#line 2392 "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"); @@ -5499,8 +5569,8 @@ void case_295() lexer.EventParsing = false; } -void case_296() -#line 2362 "cs-parser.jay" +void case_281() +#line 2399 "cs-parser.jay" { if (doc_support) { current_event.DocComment = Lexer.consume_doc_comment (); @@ -5512,23 +5582,23 @@ void case_296() current_local_parameters = null; } -void case_299() -#line 2381 "cs-parser.jay" +void case_284() +#line 2418 "cs-parser.jay" { --lexer.parsing_block; current_event_field.Initializer = (Expression) yyVals[0+yyTop]; } -void case_304() -#line 2405 "cs-parser.jay" +void case_289() +#line 2442 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new FieldDeclarator (new SimpleMemberName (lt.Value, lt.Location), null); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } -void case_306() -#line 2415 "cs-parser.jay" +void case_291() +#line 2452 "cs-parser.jay" { --lexer.parsing_block; var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; @@ -5536,8 +5606,8 @@ void case_306() lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); } -void case_307() -#line 2424 "cs-parser.jay" +void case_292() +#line 2461 "cs-parser.jay" { if (current_container.Kind == MemberKind.Interface) { report.Error (68, lexer.Location, "`{0}': event in interface cannot have an initializer", @@ -5550,29 +5620,29 @@ void case_307() } } -void case_311() -#line 2445 "cs-parser.jay" +void case_296() +#line 2482 "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" +void case_297() +#line 2487 "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" +void case_298() +#line 2492 "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" +void case_299() +#line 2500 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone) { report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); @@ -5585,8 +5655,8 @@ void case_314() lexer.EventParsing = false; } -void case_315() -#line 2475 "cs-parser.jay" +void case_300() +#line 2512 "cs-parser.jay" { lexer.EventParsing = true; @@ -5600,8 +5670,8 @@ void case_315() current_local_parameters = null; } -void case_316() -#line 2491 "cs-parser.jay" +void case_301() +#line 2528 "cs-parser.jay" { if (yyVals[-1+yyTop] != ModifierNone) { report.Error (1609, GetLocation (yyVals[-1+yyTop]), "Modifiers cannot be placed on event accessor declarations"); @@ -5614,8 +5684,8 @@ void case_316() lexer.EventParsing = false; } -void case_317() -#line 2503 "cs-parser.jay" +void case_302() +#line 2540 "cs-parser.jay" { lexer.EventParsing = true; @@ -5629,85 +5699,88 @@ void case_317() current_local_parameters = null; } -void case_318() -#line 2519 "cs-parser.jay" +void case_303() +#line 2556 "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" +void case_306() +#line 2572 "cs-parser.jay" { if (doc_support) enumTypeComment = Lexer.consume_doc_comment (); } -void case_321() -#line 2536 "cs-parser.jay" +void case_307() +#line 2577 "cs-parser.jay" { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; + enumCommas.Add (GetLocation (yyVals[0+yyTop])); MemberName name = (MemberName) yyVals[-3+yyTop]; if (name.IsGeneric) { report.Error (1675, name.Location, "Enums cannot have type parameters"); } - push_current_class (new Enum (current_namespace, current_class, (TypeExpression) yyVals[-2+yyTop], (Modifiers) yyVals[-5+yyTop], MakeName (name), (Attributes) yyVals[-6+yyTop]), null); + push_current_class (new Enum (current_namespace, current_class, (TypeExpression) yyVals[-2+yyTop], (Modifiers) yyVals[-6+yyTop], MakeName (name), (Attributes) yyVals[-7+yyTop]), null); } -void case_322() -#line 2548 "cs-parser.jay" +void case_308() +#line 2590 "cs-parser.jay" { /* here will be evaluated after CLOSE_BLACE is consumed.*/ if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } -void case_323() -#line 2554 "cs-parser.jay" +void case_309() +#line 2596 "cs-parser.jay" { + enumCommas.Add (GetLocation (yyVals[-1+yyTop])); + if (yyVals[0+yyTop] != null) + current_class.OptionalSemicolon = GetLocation (yyVals[0+yyTop]); if (doc_support) current_class.DocComment = enumTypeComment; --lexer.parsing_declaration; -/* if (doc_support)*/ -/* em.DocComment = ev.DocComment;*/ - - lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-9+yyTop]), GetLocation (yyVals[-5+yyTop]), GetLocation (yyVals[-1+yyTop])); + lbag.AddMember (current_class, GetModifierLocations (), enumCommas); + enumCommas.Clear (); yyVal = pop_current_class (); } -void case_325() -#line 2571 "cs-parser.jay" +void case_311() +#line 2614 "cs-parser.jay" { var te = yyVals[0+yyTop] as TypeExpression; if (te == null || !EnumSpec.IsValidUnderlyingType (te.Type)) { Enum.Error_1008 (GetLocation (yyVals[0+yyTop]), report); yyVal = null; } else { + enumCommas.Add (GetLocation (yyVals[-1+yyTop])); yyVal = yyVals[0+yyTop]; } } -void case_326() -#line 2581 "cs-parser.jay" +void case_312() +#line 2625 "cs-parser.jay" { Error_TypeExpected (GetLocation (yyVals[-1+yyTop])); yyVal = null; } -void case_331() -#line 2599 "cs-parser.jay" +void case_317() +#line 2643 "cs-parser.jay" { - lbag.AddLocation (yyVals[-2+yyTop], GetLocation (yyVals[-1+yyTop])); + enumCommas.Add (GetLocation (yyVals[-1+yyTop])); yyVal = yyVals[0+yyTop]; } -void case_332() -#line 2607 "cs-parser.jay" +void case_318() +#line 2651 "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]); @@ -5721,8 +5794,8 @@ void case_332() yyVal = em; } -void case_333() -#line 2620 "cs-parser.jay" +void case_319() +#line 2664 "cs-parser.jay" { ++lexer.parsing_block; if (doc_support) { @@ -5731,8 +5804,8 @@ void case_333() } } -void case_334() -#line 2628 "cs-parser.jay" +void case_320() +#line 2672 "cs-parser.jay" { --lexer.parsing_block; @@ -5747,8 +5820,8 @@ void case_334() yyVal = em; } -void case_336() -#line 2653 "cs-parser.jay" +void case_322() +#line 2697 "cs-parser.jay" { valid_param_mod = 0; @@ -5767,8 +5840,8 @@ void case_336() lexer.ConstraintsParsing = true; } -void case_338() -#line 2675 "cs-parser.jay" +void case_324() +#line 2719 "cs-parser.jay" { if (doc_support) { current_delegate.DocComment = Lexer.consume_doc_comment (); @@ -5783,8 +5856,8 @@ void case_338() current_delegate = null; } -void case_340() -#line 2693 "cs-parser.jay" +void case_326() +#line 2737 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "nullable types"); @@ -5792,8 +5865,8 @@ void case_340() yyVal = ComposedTypeSpecifier.CreateNullable (GetLocation (yyVals[0+yyTop])); } -void case_342() -#line 2704 "cs-parser.jay" +void case_328() +#line 2748 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -5801,23 +5874,24 @@ void case_342() yyVal = new MemberName (lt1.Value, lt2.Value, (TypeArguments) yyVals[0+yyTop], lt1.Location); } -void case_344() -#line 2715 "cs-parser.jay" +void case_330() +#line 2759 "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); - lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + yyVal = new MemberName ((MemberName) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location) { + DotLocation = GetLocation (yyVals[-2+yyTop]) + }; } -void case_345() -#line 2724 "cs-parser.jay" +void case_331() +#line 2769 "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" +void case_333() +#line 2781 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); @@ -5829,15 +5903,15 @@ void case_347() yyVal = yyVals[-1+yyTop];; } -void case_348() -#line 2747 "cs-parser.jay" +void case_334() +#line 2792 "cs-parser.jay" { Error_TypeExpected (lexer.Location); yyVal = new TypeArguments (); } -void case_349() -#line 2755 "cs-parser.jay" +void case_335() +#line 2800 "cs-parser.jay" { TypeArguments type_args = new TypeArguments (); type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); @@ -5845,8 +5919,8 @@ void case_349() locationListStack.Push (new List ()); } -void case_350() -#line 2762 "cs-parser.jay" +void case_336() +#line 2807 "cs-parser.jay" { TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; type_args.Add ((FullNamedExpression) yyVals[0+yyTop]); @@ -5854,16 +5928,16 @@ void case_350() locationListStack.Peek ().Add (GetLocation (yyVals[-1+yyTop])); } -void case_352() -#line 2779 "cs-parser.jay" +void case_338() +#line 2824 "cs-parser.jay" { lexer.parsing_generic_declaration = false; var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new MemberName (lt.Value, (TypeArguments)yyVals[0+yyTop], lt.Location); } -void case_353() -#line 2788 "cs-parser.jay" +void case_339() +#line 2833 "cs-parser.jay" { MemberName mn = (MemberName)yyVals[0+yyTop]; if (mn.TypeArguments != null) @@ -5871,38 +5945,38 @@ void case_353() mn.GetSignatureForError ())); } -void case_355() -#line 2799 "cs-parser.jay" +void case_341() +#line 2844 "cs-parser.jay" { lexer.parsing_generic_declaration = false; var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new MemberName ((MemberName) yyVals[-2+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location); } -void case_356() -#line 2808 "cs-parser.jay" +void case_342() +#line 2853 "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" +void case_343() +#line 2858 "cs-parser.jay" { lexer.parsing_generic_declaration = false; - yyVal = new MemberName ((MemberName) yyVals[-1+yyTop], TypeContainer.DefaultIndexerName, null, GetLocation (yyVals[-1+yyTop])); + yyVal = new MemberName ((MemberName) yyVals[-1+yyTop], TypeContainer.DefaultIndexerName, null, GetLocation (yyVals[0+yyTop])); } -void case_358() -#line 2821 "cs-parser.jay" +void case_344() +#line 2866 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new MemberName (lt.Value, (TypeArguments) yyVals[-1+yyTop], lt.Location); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_359() -#line 2827 "cs-parser.jay" +void case_345() +#line 2872 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; @@ -5911,50 +5985,53 @@ void case_359() lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_360() -#line 2835 "cs-parser.jay" +void case_346() +#line 2880 "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); lbag.AddLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_362() -#line 2845 "cs-parser.jay" +void case_348() +#line 2890 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "generics"); yyVal = yyVals[-1+yyTop]; - lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + lbag.AppendTo (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_363() -#line 2856 "cs-parser.jay" +void case_349() +#line 2901 "cs-parser.jay" { TypeArguments type_args = new TypeArguments (); type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); yyVal = type_args; } -void case_364() -#line 2862 "cs-parser.jay" +void case_350() +#line 2907 "cs-parser.jay" { TypeArguments type_args = (TypeArguments) yyVals[-2+yyTop]; type_args.Add ((FullNamedExpression)yyVals[0+yyTop]); yyVal = type_args; - lbag.AddLocation (yyVals[0+yyTop], GetLocation (yyVals[0+yyTop])); + lbag.AppendTo (type_args, GetLocation (yyVals[-1+yyTop])); } -void case_365() -#line 2872 "cs-parser.jay" +void case_351() +#line 2917 "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); + var variance = (Variance) yyVals[-1+yyTop]; + yyVal = new TypeParameterName (lt.Value, (Attributes)yyVals[-2+yyTop], variance, lt.Location); + if (variance != Variance.None) + lbag.AddLocation (yyVal, savedLocation); } -void case_366() -#line 2877 "cs-parser.jay" +void case_352() +#line 2925 "cs-parser.jay" { if (GetTokenName (yyToken) == "type") report.Error (81, GetLocation (yyVals[0+yyTop]), "Type parameter declaration must be an identifier not a type"); @@ -5964,29 +6041,29 @@ void case_366() yyVal = new TypeParameterName ("", null, lexer.Location); } -void case_371() -#line 2911 "cs-parser.jay" +void case_357() +#line 2959 "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" +void case_359() +#line 2968 "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" +void case_361() +#line 2977 "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" +void case_364() +#line 2993 "cs-parser.jay" { MemberName name = (MemberName) yyVals[-1+yyTop]; @@ -6000,31 +6077,32 @@ void case_378() } } -void case_380() -#line 2962 "cs-parser.jay" +void case_366() +#line 3010 "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" +void case_369() +#line 3026 "cs-parser.jay" { var types = new List (2); types.Add ((FullNamedExpression) yyVals[0+yyTop]); yyVal = types; } -void case_384() -#line 2984 "cs-parser.jay" +void case_370() +#line 3032 "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" +void case_371() +#line 3042 "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 ()); @@ -6032,60 +6110,63 @@ void case_385() yyVal = yyVals[0+yyTop]; } -void case_386() -#line 3000 "cs-parser.jay" +void case_372() +#line 3049 "cs-parser.jay" { Error_TypeExpected (lexer.Location); yyVal = null; } -void case_423() -#line 3062 "cs-parser.jay" +void case_409() +#line 3111 "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" +void case_410() +#line 3115 "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" +void case_421() +#line 3156 "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" +void case_423() +#line 3168 "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); - lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location) { + DotLocation = GetLocation (yyVals[-2+yyTop]) + }; } -void case_438() -#line 3125 "cs-parser.jay" +void case_424() +#line 3175 "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); - lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location) { + DotLocation = GetLocation (yyVals[-2+yyTop]) + }; } -void case_439() -#line 3131 "cs-parser.jay" +void case_425() +#line 3182 "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); - lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop])); + yyVal = new MemberAccess (new BaseThis (GetLocation (yyVals[-3+yyTop])), lt.Value, (TypeArguments) yyVals[0+yyTop], lt.Location) { + DotLocation = GetLocation (yyVals[-2+yyTop]) + }; } -void case_440() -#line 3137 "cs-parser.jay" +void case_426() +#line 3189 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -6094,79 +6175,80 @@ void case_440() lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } -void case_442() -#line 3147 "cs-parser.jay" +void case_428() +#line 3199 "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" +void case_430() +#line 3207 "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" +void case_431() +#line 3215 "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" +void case_434() +#line 3228 "cs-parser.jay" { if (yyVals[-1+yyTop] == null) { yyVal = CollectionOrObjectInitializers.Empty; /* 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])); } } -void case_449() -#line 3186 "cs-parser.jay" +void case_435() +#line 3238 "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() -#line 3202 "cs-parser.jay" +void case_438() +#line 3254 "cs-parser.jay" { var a = new List (); a.Add ((Expression) yyVals[0+yyTop]); yyVal = a; } -void case_453() -#line 3208 "cs-parser.jay" +void case_439() +#line 3260 "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" +void case_440() +#line 3266 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = yyVals[-1+yyTop]; } -void case_455() -#line 3221 "cs-parser.jay" +void case_441() +#line 3274 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; yyVal = new ElementInitializer (lt.Value, (Expression)yyVals[0+yyTop], lt.Location); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } -void case_457() -#line 3230 "cs-parser.jay" +void case_443() +#line 3283 "cs-parser.jay" { CompletionSimpleName csn = yyVals[-1+yyTop] as CompletionSimpleName; if (csn == null) @@ -6175,8 +6257,8 @@ void case_457() yyVal = new CompletionElementInitializer (csn.Prefix, csn.Location); } -void case_458() -#line 3238 "cs-parser.jay" +void case_444() +#line 3291 "cs-parser.jay" { if (yyVals[-1+yyTop] == null) yyVal = null; @@ -6184,23 +6266,23 @@ void case_458() yyVal = new CollectionElementInitializer ((List)yyVals[-1+yyTop], GetLocation (yyVals[-2+yyTop])); } -void case_459() -#line 3245 "cs-parser.jay" +void case_445() +#line 3298 "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" +void case_450() +#line 3316 "cs-parser.jay" { Arguments list = new Arguments (4); list.Add ((Argument) yyVals[0+yyTop]); yyVal = list; } -void case_465() -#line 3269 "cs-parser.jay" +void case_451() +#line 3322 "cs-parser.jay" { Arguments list = (Arguments) yyVals[-2+yyTop]; if (list [list.Count - 1] is NamedArgument) @@ -6211,8 +6293,8 @@ void case_465() yyVal = list; } -void case_466() -#line 3279 "cs-parser.jay" +void case_452() +#line 3332 "cs-parser.jay" { Arguments list = (Arguments) yyVals[-2+yyTop]; NamedArgument a = (NamedArgument) yyVals[0+yyTop]; @@ -6228,65 +6310,65 @@ void case_466() yyVal = list; } -void case_467() -#line 3294 "cs-parser.jay" +void case_453() +#line 3347 "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" +void case_454() +#line 3352 "cs-parser.jay" { report.Error (839, GetLocation (yyVals[-1+yyTop]), "An argument is missing"); yyVal = null; } -void case_473() -#line 3320 "cs-parser.jay" +void case_459() +#line 3373 "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" +void case_460() +#line 3378 "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" +void case_461() +#line 3383 "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" +void case_462() +#line 3388 "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" +void case_464() +#line 3400 "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" +void case_465() +#line 3408 "cs-parser.jay" { var list = new List (4); list.Add ((Expression) yyVals[0+yyTop]); yyVal = list; } -void case_480() -#line 3361 "cs-parser.jay" +void case_466() +#line 3414 "cs-parser.jay" { var list = (List) yyVals[-2+yyTop]; list.Add ((Expression) yyVals[0+yyTop]); @@ -6294,23 +6376,23 @@ void case_480() yyVal = list; } -void case_481() -#line 3367 "cs-parser.jay" +void case_467() +#line 3420 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = yyVals[-1+yyTop]; } -void case_482() -#line 3375 "cs-parser.jay" +void case_468() +#line 3428 "cs-parser.jay" { Arguments args = new Arguments (4); args.Add ((Argument) yyVals[0+yyTop]); yyVal = args; } -void case_483() -#line 3381 "cs-parser.jay" +void case_469() +#line 3434 "cs-parser.jay" { Arguments args = (Arguments) yyVals[-2+yyTop]; if (args [args.Count - 1] is NamedArgument && !(yyVals[0+yyTop] is NamedArgument)) @@ -6321,22 +6403,22 @@ void case_483() yyVal = args; } -void case_487() -#line 3409 "cs-parser.jay" +void case_473() +#line 3462 "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" +void case_474() +#line 3467 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new ElementAccess (null, null, GetLocation (yyVals[-1+yyTop])); } -void case_491() -#line 3436 "cs-parser.jay" +void case_477() +#line 3489 "cs-parser.jay" { if (yyVals[0+yyTop] != null) { if (lang_version <= LanguageVersion.ISO_2) @@ -6350,8 +6432,8 @@ void case_491() lbag.AddLocation (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); } -void case_492() -#line 3449 "cs-parser.jay" +void case_478() +#line 3502 "cs-parser.jay" { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "collection initializers"); @@ -6359,8 +6441,8 @@ void case_492() yyVal = new NewInitialize ((FullNamedExpression) yyVals[-1+yyTop], null, (CollectionOrObjectInitializers) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); } -void case_493() -#line 3461 "cs-parser.jay" +void case_479() +#line 3514 "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])) { @@ -6369,8 +6451,8 @@ void case_493() lbag.AddLocation (yyVal, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); } -void case_494() -#line 3469 "cs-parser.jay" +void case_480() +#line 3522 "cs-parser.jay" { if (yyVals[0+yyTop] == null) report.Error (1586, GetLocation (yyVals[-3+yyTop]), "Array creation must have array size or array initializer"); @@ -6378,8 +6460,8 @@ void case_494() yyVal = new ArrayCreation ((FullNamedExpression) yyVals[-2+yyTop], (ComposedTypeSpecifier) yyVals[-1+yyTop], (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-3+yyTop])); } -void case_495() -#line 3476 "cs-parser.jay" +void case_481() +#line 3529 "cs-parser.jay" { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-2+yyTop]), "implicitly typed arrays"); @@ -6387,29 +6469,29 @@ void case_495() yyVal = new ImplicitlyTypedArrayCreation ((ComposedTypeSpecifier) yyVals[-1+yyTop], (ArrayInitializer) yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); } -void case_496() -#line 3483 "cs-parser.jay" +void case_482() +#line 3536 "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" +void case_483() +#line 3541 "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" +void case_485() +#line 3552 "cs-parser.jay" { --lexer.parsing_type; yyVal = yyVals[0+yyTop]; } -void case_500() -#line 3507 "cs-parser.jay" +void case_486() +#line 3560 "cs-parser.jay" { if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "anonymous types"); @@ -6420,76 +6502,78 @@ void case_500() lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_505() -#line 3530 "cs-parser.jay" +void case_491() +#line 3583 "cs-parser.jay" { var a = new List (4); a.Add ((AnonymousTypeParameter) yyVals[0+yyTop]); yyVal = a; } -void case_506() -#line 3536 "cs-parser.jay" +void case_492() +#line 3589 "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" +void case_493() +#line 3600 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken)yyVals[-2+yyTop]; yyVal = new AnonymousTypeParameter ((Expression)yyVals[0+yyTop], lt.Value, lt.Location); lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } -void case_508() -#line 3551 "cs-parser.jay" +void case_494() +#line 3606 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken)yyVals[0+yyTop]; yyVal = new AnonymousTypeParameter (new SimpleName (lt.Value, lt.Location), lt.Value, lt.Location); } -void case_509() -#line 3557 "cs-parser.jay" +void case_495() +#line 3612 "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" +void case_496() +#line 3617 "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"); yyVal = null; } -void case_514() -#line 3577 "cs-parser.jay" +void case_500() +#line 3632 "cs-parser.jay" { ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; yyVal = yyVals[-1+yyTop]; } -void case_515() -#line 3585 "cs-parser.jay" +void case_501() +#line 3640 "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" +void case_502() +#line 3645 "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" +void case_507() +#line 3675 "cs-parser.jay" { var ai = new ArrayInitializer (0, GetLocation (yyVals[-1+yyTop])); ai.VariableDeclaration = current_variable; @@ -6497,8 +6581,8 @@ void case_521() yyVal = ai; } -void case_522() -#line 3627 "cs-parser.jay" +void case_508() +#line 3682 "cs-parser.jay" { var ai = new ArrayInitializer ((List) yyVals[-2+yyTop], GetLocation (yyVals[-3+yyTop])); ai.VariableDeclaration = current_variable; @@ -6510,16 +6594,16 @@ void case_522() yyVal = ai; } -void case_523() -#line 3641 "cs-parser.jay" +void case_509() +#line 3696 "cs-parser.jay" { var list = new List (4); list.Add ((Expression) yyVals[0+yyTop]); yyVal = list; } -void case_524() -#line 3647 "cs-parser.jay" +void case_510() +#line 3702 "cs-parser.jay" { var list = (List) yyVals[-2+yyTop]; list.Add ((Expression) yyVals[0+yyTop]); @@ -6527,31 +6611,31 @@ void case_524() yyVal = list; } -void case_526() -#line 3661 "cs-parser.jay" +void case_512() +#line 3716 "cs-parser.jay" { lexer.TypeOfParsing = false; yyVal = new TypeOf ((FullNamedExpression) yyVals[-1+yyTop], GetLocation (yyVals[-4+yyTop])); lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_529() -#line 3672 "cs-parser.jay" +void case_515() +#line 3727 "cs-parser.jay" { Error_TypeExpected (lexer.Location); yyVal = null; } -void case_530() -#line 3680 "cs-parser.jay" +void case_516() +#line 3735 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new SimpleName (lt.Value, (int) yyVals[0+yyTop], lt.Location); } -void case_531() -#line 3686 "cs-parser.jay" +void case_517() +#line 3741 "cs-parser.jay" { var lt1 = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var lt2 = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; @@ -6560,35 +6644,41 @@ void case_531() lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } -void case_532() -#line 3694 "cs-parser.jay" +void case_518() +#line 3749 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; - yyVal = new MemberAccess ((Expression) yyVals[-2+yyTop], lt.Value, lt.Location); + yyVal = new MemberAccess ((Expression) yyVals[-2+yyTop], lt.Value, lt.Location) { + DotLocation = GetLocation (yyVals[-1+yyTop]) + }; } -void case_533() -#line 3700 "cs-parser.jay" +void case_519() +#line 3757 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; - yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (int) yyVals[0+yyTop], lt.Location); + yyVal = new MemberAccess ((Expression) yyVals[-3+yyTop], lt.Value, (int) yyVals[0+yyTop], lt.Location) { + DotLocation = GetLocation (yyVals[-2+yyTop]) + }; } -void case_534() -#line 3706 "cs-parser.jay" +void case_520() +#line 3765 "cs-parser.jay" { var te = ((MemberName) yyVals[-3+yyTop]).GetTypeExpression (); if (te.HasTypeArguments) Error_TypeExpected (GetLocation (yyVals[0+yyTop])); var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; - yyVal = new MemberAccess (te, lt.Value, (int) yyVals[0+yyTop], lt.Location); + yyVal = new MemberAccess (te, lt.Value, (int) yyVals[0+yyTop], lt.Location) { + DotLocation = GetLocation (yyVals[-2+yyTop]) + }; } -void case_535() -#line 3718 "cs-parser.jay" +void case_521() +#line 3779 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[0+yyTop]), "generics"); @@ -6596,8 +6686,8 @@ void case_535() yyVal = yyVals[0+yyTop]; } -void case_536() -#line 3728 "cs-parser.jay" +void case_522() +#line 3789 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; if (lang_version == LanguageVersion.ISO_1) @@ -6606,36 +6696,36 @@ void case_536() yyVal = lt; } -void case_537() -#line 3739 "cs-parser.jay" +void case_523() +#line 3800 "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" +void case_524() +#line 3808 "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" +void case_525() +#line 3816 "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" +void case_526() +#line 3824 "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" +void case_528() +#line 3836 "cs-parser.jay" { yyVal = end_anonymous ((ParametersBlock) yyVals[0+yyTop]); if ((ParametersCompiled) yyVals[-2+yyTop] != ParametersCompiled.Undefined) { @@ -6645,8 +6735,8 @@ void case_542() } } -void case_548() -#line 3807 "cs-parser.jay" +void case_534() +#line 3868 "cs-parser.jay" { valid_param_mod = 0; yyVal = yyVals[-1+yyTop]; @@ -6654,8 +6744,8 @@ void case_548() savedCloseLocation = GetLocation (yyVals[-2+yyTop]); } -void case_549() -#line 3817 "cs-parser.jay" +void case_535() +#line 3878 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-3+yyTop]), "default value expression"); @@ -6664,148 +6754,148 @@ void case_549() lbag.AddLocation (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_555() -#line 3842 "cs-parser.jay" +void case_541() +#line 3903 "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" +void case_542() +#line 3911 "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" +void case_551() +#line 3952 "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" +void case_552() +#line 3957 "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" +void case_553() +#line 3962 "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" +void case_555() +#line 3971 "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" +void case_557() +#line 3980 "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" +void case_561() +#line 3997 "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" +void case_562() +#line 4002 "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" +void case_564() +#line 4011 "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" +void case_565() +#line 4016 "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" +void case_566() +#line 4021 "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" +void case_567() +#line 4026 "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" +void case_569() +#line 4035 "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" +void case_570() +#line 4040 "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" +void case_572() +#line 4049 "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" +void case_574() +#line 4058 "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" +void case_576() +#line 4067 "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" +void case_578() +#line 4076 "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" +void case_580() +#line 4085 "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" +void case_582() +#line 4094 "cs-parser.jay" { if (lang_version < LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation (yyVals[-1+yyTop]), "null coalescing operator"); @@ -6813,94 +6903,94 @@ void case_596() yyVal = new Nullable.NullCoalescingOperator ((Expression) yyVals[-2+yyTop], (Expression) yyVals[0+yyTop], GetLocation (yyVals[-1+yyTop])); } -void case_598() -#line 4044 "cs-parser.jay" +void case_584() +#line 4105 "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" +void case_586() +#line 4117 "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" +void case_587() +#line 4122 "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" +void case_588() +#line 4127 "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" +void case_589() +#line 4132 "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" +void case_590() +#line 4137 "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" +void case_591() +#line 4142 "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" +void case_592() +#line 4147 "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" +void case_593() +#line 4152 "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" +void case_594() +#line 4157 "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" +void case_595() +#line 4162 "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" +void case_596() +#line 4170 "cs-parser.jay" { var pars = new List (4); pars.Add ((Parameter) yyVals[0+yyTop]); - + parameterListCommas.Clear (); yyVal = pars; } -void case_611() -#line 4116 "cs-parser.jay" +void case_597() +#line 4177 "cs-parser.jay" { var pars = (List) yyVals[-2+yyTop]; Parameter p = (Parameter)yyVals[0+yyTop]; @@ -6909,41 +6999,44 @@ void case_611() } pars.Add (p); + parameterListCommas.Add (GetLocation (yyVals[-1+yyTop])); + yyVal = pars; } -void case_612() -#line 4130 "cs-parser.jay" +void case_598() +#line 4193 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, (Parameter.Modifier) yyVals[-2+yyTop], null, lt.Location); } -void case_613() -#line 4136 "cs-parser.jay" +void case_599() +#line 4199 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; yyVal = new Parameter ((FullNamedExpression) yyVals[-1+yyTop], lt.Value, Parameter.Modifier.NONE, null, lt.Location); } -void case_614() -#line 4142 "cs-parser.jay" +void case_600() +#line 4205 "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" +void case_602() +#line 4213 "cs-parser.jay" { var pars_list = (List) yyVals[0+yyTop]; yyVal = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation (yyVal, parameterListCommas); } -void case_620() -#line 4166 "cs-parser.jay" +void case_606() +#line 4230 "cs-parser.jay" { Block b = end_block (lexer.Location); b.IsCompilerGenerated = true; @@ -6951,142 +7044,147 @@ void case_620() yyVal = b; } -void case_622() -#line 4177 "cs-parser.jay" +void case_608() +#line 4241 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = EmptyExpression.Null; } -void case_623() -#line 4185 "cs-parser.jay" +void case_609() +#line 4249 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); start_anonymous (true, new ParametersCompiled (p), false, lt.Location); } -void case_624() -#line 4191 "cs-parser.jay" +void case_610() +#line 4255 "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" +void case_611() +#line 4260 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; Parameter p = new ImplicitLambdaParameter (lt.Value, lt.Location); start_anonymous (true, new ParametersCompiled (p), true, lt.Location); } -void case_626() -#line 4202 "cs-parser.jay" +void case_612() +#line 4266 "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" +void case_614() +#line 4275 "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" +void case_615() +#line 4280 "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" +void case_617() +#line 4289 "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" +void case_618() +#line 4294 "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" +void case_625() +#line 4317 "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" +void case_626() +#line 4322 "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" +void case_627() +#line 4327 "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" +void case_631() +#line 4356 "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]); if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (c.Location, "static classes"); } - + push_current_class (c, yyVals[-3+yyTop]); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-2+yyTop])); } -void case_646() -#line 4303 "cs-parser.jay" +void case_632() +#line 4368 "cs-parser.jay" { lexer.ConstraintsParsing = false; current_class.SetParameterInfo ((List) yyVals[0+yyTop]); - lbag.AddMember (current_class, GetModifierLocations (), GetLocation (yyVals[-5+yyTop])); if (doc_support) { current_container.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } + + lexer.parsing_modifiers = true; } -void case_647() -#line 4315 "cs-parser.jay" +void case_633() +#line 4381 "cs-parser.jay" { --lexer.parsing_declaration; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } -void case_648() -#line 4321 "cs-parser.jay" +void case_634() +#line 4387 "cs-parser.jay" { - lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); + lbag.AppendToMember (current_class, GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-2+yyTop])); + if (yyVals[0+yyTop] != null) + current_class.OptionalSemicolon = GetLocation (yyVals[0+yyTop]); yyVal = pop_current_class (); } -void case_651() -#line 4336 "cs-parser.jay" +void case_637() +#line 4404 "cs-parser.jay" { mod_locations = null; yyVal = ModifierNone; + lexer.parsing_modifiers = false; } -void case_654() -#line 4346 "cs-parser.jay" +void case_640() +#line 4418 "cs-parser.jay" { var m1 = (Modifiers) yyVals[-1+yyTop]; var m2 = (Modifiers) yyVals[0+yyTop]; @@ -7103,8 +7201,8 @@ void case_654() yyVal = m1 | m2; } -void case_655() -#line 4365 "cs-parser.jay" +void case_641() +#line 4437 "cs-parser.jay" { yyVal = Modifiers.NEW; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); @@ -7113,92 +7211,92 @@ void case_655() report.Error (1530, GetLocation (yyVals[0+yyTop]), "Keyword `new' is not allowed on namespace elements"); } -void case_656() -#line 4373 "cs-parser.jay" +void case_642() +#line 4445 "cs-parser.jay" { yyVal = Modifiers.PUBLIC; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_657() -#line 4378 "cs-parser.jay" +void case_643() +#line 4450 "cs-parser.jay" { yyVal = Modifiers.PROTECTED; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_658() -#line 4383 "cs-parser.jay" +void case_644() +#line 4455 "cs-parser.jay" { yyVal = Modifiers.INTERNAL; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_659() -#line 4388 "cs-parser.jay" +void case_645() +#line 4460 "cs-parser.jay" { yyVal = Modifiers.PRIVATE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_660() -#line 4393 "cs-parser.jay" +void case_646() +#line 4465 "cs-parser.jay" { yyVal = Modifiers.ABSTRACT; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_661() -#line 4398 "cs-parser.jay" +void case_647() +#line 4470 "cs-parser.jay" { yyVal = Modifiers.SEALED; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_662() -#line 4403 "cs-parser.jay" +void case_648() +#line 4475 "cs-parser.jay" { yyVal = Modifiers.STATIC; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_663() -#line 4408 "cs-parser.jay" +void case_649() +#line 4480 "cs-parser.jay" { yyVal = Modifiers.READONLY; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_664() -#line 4413 "cs-parser.jay" +void case_650() +#line 4485 "cs-parser.jay" { yyVal = Modifiers.VIRTUAL; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_665() -#line 4418 "cs-parser.jay" +void case_651() +#line 4490 "cs-parser.jay" { yyVal = Modifiers.OVERRIDE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_666() -#line 4423 "cs-parser.jay" +void case_652() +#line 4495 "cs-parser.jay" { yyVal = Modifiers.EXTERN; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_667() -#line 4428 "cs-parser.jay" +void case_653() +#line 4500 "cs-parser.jay" { yyVal = Modifiers.VOLATILE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_668() -#line 4433 "cs-parser.jay" +void case_654() +#line 4505 "cs-parser.jay" { yyVal = Modifiers.UNSAFE; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); @@ -7206,30 +7304,37 @@ void case_668() Error_UnsafeCodeNotAllowed (GetLocation (yyVals[0+yyTop])); } -void case_669() -#line 4440 "cs-parser.jay" +void case_655() +#line 4512 "cs-parser.jay" { yyVal = Modifiers.ASYNC; StoreModifierLocation (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_674() -#line 4461 "cs-parser.jay" +void case_657() +#line 4521 "cs-parser.jay" +{ + lbag.AppendToMember (current_class, GetLocation (yyVals[-1+yyTop])); + current_container.AddBasesForPart (current_class, (List) yyVals[0+yyTop]); + } + +void case_660() +#line 4534 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } -void case_675() -#line 4469 "cs-parser.jay" +void case_661() +#line 4542 "cs-parser.jay" { var constraints = new List (1); constraints.Add ((Constraints) yyVals[0+yyTop]); yyVal = constraints; } -void case_676() -#line 4475 "cs-parser.jay" +void case_662() +#line 4548 "cs-parser.jay" { var constraints = (List) yyVals[-1+yyTop]; Constraints new_constraint = (Constraints)yyVals[0+yyTop]; @@ -7246,23 +7351,24 @@ void case_676() yyVal = constraints; } -void case_677() -#line 4494 "cs-parser.jay" +void case_663() +#line 4567 "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])); + lbag.AddLocation (yyVal, GetLocation (yyVals[-1+yyTop])); } -void case_678() -#line 4502 "cs-parser.jay" +void case_664() +#line 4576 "cs-parser.jay" { var constraints = new List (1); constraints.Add ((FullNamedExpression) yyVals[0+yyTop]); yyVal = constraints; } -void case_679() -#line 4508 "cs-parser.jay" +void case_665() +#line 4582 "cs-parser.jay" { var constraints = (List) yyVals[-2+yyTop]; var prev = constraints [constraints.Count - 1] as SpecialContraintExpr; @@ -7283,11 +7389,12 @@ void case_679() } constraints.Add ((FullNamedExpression) yyVals[0+yyTop]); + lbag.AppendTo (constraints, GetLocation (yyVals[-1+yyTop])); yyVal = constraints; } -void case_680() -#line 4534 "cs-parser.jay" +void case_666() +#line 4609 "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 ()); @@ -7295,15 +7402,15 @@ void case_680() yyVal = yyVals[0+yyTop]; } -void case_681() -#line 4541 "cs-parser.jay" +void case_667() +#line 4616 "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" +void case_671() +#line 4636 "cs-parser.jay" { if (lang_version <= LanguageVersion.V_3) FeatureIsNotAvailable (lexer.Location, "generic type variance"); @@ -7311,88 +7418,102 @@ void case_685() yyVal = yyVals[0+yyTop]; } -void case_688() -#line 4595 "cs-parser.jay" +void case_672() +#line 4646 "cs-parser.jay" +{ + yyVal = Variance.Covariant; + savedLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_673() +#line 4651 "cs-parser.jay" +{ + yyVal = Variance.Contravariant; + savedLocation = GetLocation (yyVals[0+yyTop]); + } + +void case_674() +#line 4672 "cs-parser.jay" { ++lexer.parsing_block; start_block (GetLocation (yyVals[0+yyTop])); } -void case_690() -#line 4607 "cs-parser.jay" +void case_676() +#line 4684 "cs-parser.jay" { --lexer.parsing_block; yyVal = end_block (GetLocation (yyVals[0+yyTop])); } -void case_691() -#line 4612 "cs-parser.jay" +void case_677() +#line 4689 "cs-parser.jay" { --lexer.parsing_block; yyVal = end_block (lexer.Location); } -void case_692() -#line 4621 "cs-parser.jay" +void case_678() +#line 4698 "cs-parser.jay" { ++lexer.parsing_block; current_block.StartLocation = GetLocation (yyVals[0+yyTop]); } -void case_693() -#line 4626 "cs-parser.jay" +void case_679() +#line 4703 "cs-parser.jay" { --lexer.parsing_block; yyVal = end_block (GetLocation (yyVals[0+yyTop])); } -void case_701() -#line 4653 "cs-parser.jay" +void case_687() +#line 4730 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } -void case_734() -#line 4717 "cs-parser.jay" +void case_720() +#line 4794 "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" +void case_721() +#line 4799 "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" +void case_722() +#line 4804 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); } -void case_737() -#line 4735 "cs-parser.jay" +void case_723() +#line 4812 "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" +void case_724() +#line 4820 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); - + lbag.AddLocation (labeled, GetLocation (yyVals[0+yyTop])); current_block.AddLabel (labeled); current_block.AddStatement (labeled); } -void case_741() -#line 4756 "cs-parser.jay" +void case_727() +#line 4833 "cs-parser.jay" { if (yyVals[-1+yyTop] is VarExpr) yyVals[-1+yyTop] = new SimpleName ("var", ((VarExpr) yyVals[-1+yyTop]).Location); @@ -7400,8 +7521,8 @@ void case_741() yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } -void case_742() -#line 4772 "cs-parser.jay" +void case_728() +#line 4849 "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*/ @@ -7432,8 +7553,8 @@ void case_742() } } -void case_743() -#line 4802 "cs-parser.jay" +void case_729() +#line 4879 "cs-parser.jay" { ATypeNameExpression expr = yyVals[-1+yyTop] as ATypeNameExpression; @@ -7445,8 +7566,8 @@ void case_743() } } -void case_744() -#line 4813 "cs-parser.jay" +void case_730() +#line 4890 "cs-parser.jay" { if (yyVals[0+yyTop] == null) yyVal = yyVals[-1+yyTop]; @@ -7454,22 +7575,22 @@ void case_744() yyVal = new ComposedCast ((FullNamedExpression) yyVals[-1+yyTop], (ComposedTypeSpecifier) yyVals[0+yyTop]); } -void case_747() -#line 4828 "cs-parser.jay" +void case_733() +#line 4905 "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" +void case_735() +#line 4914 "cs-parser.jay" { ((ComposedTypeSpecifier) yyVals[-1+yyTop]).Next = (ComposedTypeSpecifier) yyVals[0+yyTop]; yyVal = yyVals[-1+yyTop]; } -void case_751() -#line 4852 "cs-parser.jay" +void case_737() +#line 4929 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_block, lt.Value, lt.Location); @@ -7477,16 +7598,16 @@ void case_751() current_variable = new BlockVariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); } -void case_752() -#line 4859 "cs-parser.jay" +void case_738() +#line 4936 "cs-parser.jay" { yyVal = current_variable; current_variable = null; lbag.AppendTo (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_753() -#line 4865 "cs-parser.jay" +void case_739() +#line 4942 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); @@ -7494,8 +7615,8 @@ void case_753() current_variable = new BlockConstantDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); } -void case_754() -#line 4872 "cs-parser.jay" +void case_740() +#line 4949 "cs-parser.jay" { if (current_variable.Initializer != null) { lbag.AddLocation (current_variable, GetLocation (yyVals[-6+yyTop]), savedLocation, GetLocation (yyVals[0+yyTop])); @@ -7506,15 +7627,15 @@ void case_754() current_variable = null; } -void case_756() -#line 4886 "cs-parser.jay" +void case_742() +#line 4963 "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" +void case_743() +#line 4968 "cs-parser.jay" { if (yyToken == Token.OPEN_BRACKET_EXPR) { report.Error (650, lexer.Location, @@ -7524,8 +7645,17 @@ void case_757() } } -void case_762() -#line 4913 "cs-parser.jay" +void case_747() +#line 4986 "cs-parser.jay" +{ + foreach (var d in current_variable.Declarators) { + if (d.Initializer == null) + Error_MissingInitializer (d.Variable.Location); + } + } + +void case_750() +#line 5001 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); @@ -7535,8 +7665,8 @@ void case_762() lbag.AddLocation (d, GetLocation (yyVals[-1+yyTop])); } -void case_763() -#line 4922 "cs-parser.jay" +void case_751() +#line 5010 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var li = new LocalVariable (current_variable.Variable, lt.Value, lt.Location); @@ -7546,15 +7676,15 @@ void case_763() lbag.AddLocation (d, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); } -void case_765() -#line 4938 "cs-parser.jay" +void case_753() +#line 5026 "cs-parser.jay" { savedLocation = GetLocation (yyVals[-1+yyTop]); current_variable.Initializer = (Expression) yyVals[0+yyTop]; } -void case_770() -#line 4956 "cs-parser.jay" +void case_758() +#line 5044 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; var li = new LocalVariable (current_block, lt.Value, LocalVariable.Flags.Constant, lt.Location); @@ -7564,29 +7694,29 @@ void case_770() lbag.AddLocation (d, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); } -void case_772() -#line 4969 "cs-parser.jay" +void case_760() +#line 5057 "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" +void case_761() +#line 5062 "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" +void case_762() +#line 5070 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; lbag.AddStatement (yyVal, GetLocation (yyVals[0+yyTop])); } -void case_778() -#line 5000 "cs-parser.jay" +void case_766() +#line 5088 "cs-parser.jay" { ExpressionStatement s = yyVals[0+yyTop] as ExpressionStatement; if (s == null) { @@ -7597,8 +7727,8 @@ void case_778() } } -void case_779() -#line 5013 "cs-parser.jay" +void case_767() +#line 5101 "cs-parser.jay" { Expression expr = (Expression) yyVals[0+yyTop]; ExpressionStatement s; @@ -7607,15 +7737,15 @@ void case_779() yyVal = new StatementExpression (s); } -void case_780() -#line 5021 "cs-parser.jay" +void case_768() +#line 5109 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new EmptyStatement (GetLocation (yyVals[0+yyTop])); } -void case_783() -#line 5035 "cs-parser.jay" +void case_771() +#line 5123 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7624,8 +7754,8 @@ void case_783() lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); } -void case_784() -#line 5044 "cs-parser.jay" +void case_772() +#line 5132 "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])); @@ -7636,23 +7766,23 @@ void case_784() Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); } -void case_786() -#line 5061 "cs-parser.jay" +void case_774() +#line 5149 "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])); lbag.AddStatement (yyVal, GetLocation (yyVals[-6+yyTop]), GetLocation (yyVals[-4+yyTop]), GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_787() -#line 5070 "cs-parser.jay" +void case_775() +#line 5158 "cs-parser.jay" { report.Warning (1522, 1, current_block.StartLocation, "Empty switch block"); yyVal = new List (); } -void case_789() -#line 5079 "cs-parser.jay" +void case_777() +#line 5167 "cs-parser.jay" { var sections = new List (4); @@ -7660,8 +7790,8 @@ void case_789() yyVal = sections; } -void case_790() -#line 5086 "cs-parser.jay" +void case_778() +#line 5174 "cs-parser.jay" { var sections = (List) yyVals[-1+yyTop]; @@ -7669,15 +7799,15 @@ void case_790() yyVal = sections; } -void case_791() -#line 5093 "cs-parser.jay" +void case_779() +#line 5181 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = new List (); } -void case_794() -#line 5112 "cs-parser.jay" +void case_782() +#line 5200 "cs-parser.jay" { var labels = new List (2); @@ -7685,8 +7815,8 @@ void case_794() yyVal = labels; } -void case_795() -#line 5119 "cs-parser.jay" +void case_783() +#line 5207 "cs-parser.jay" { var labels = (List) (yyVals[-1+yyTop]); labels.Add ((SwitchLabel) yyVals[0+yyTop]); @@ -7694,15 +7824,15 @@ void case_795() yyVal = labels; } -void case_796() -#line 5129 "cs-parser.jay" +void case_784() +#line 5217 "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" +void case_790() +#line 5236 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7711,22 +7841,22 @@ void case_802() lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); } -void case_803() -#line 5160 "cs-parser.jay" +void case_791() +#line 5248 "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" +void case_792() +#line 5256 "cs-parser.jay" { start_block (GetLocation (yyVals[0+yyTop])); current_block.IsCompilerGenerated = true; } -void case_806() -#line 5184 "cs-parser.jay" +void case_794() +#line 5272 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7739,15 +7869,15 @@ void case_806() yyVal = end_block (GetLocation (yyVals[-5+yyTop])); } -void case_807() -#line 5196 "cs-parser.jay" +void case_795() +#line 5284 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = end_block (current_block.StartLocation); } -void case_810() -#line 5209 "cs-parser.jay" +void case_798() +#line 5297 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[0+yyTop]; var li = new LocalVariable (current_block, lt.Value, lt.Location); @@ -7755,15 +7885,15 @@ void case_810() current_variable = new BlockVariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); } -void case_811() -#line 5216 "cs-parser.jay" +void case_799() +#line 5304 "cs-parser.jay" { yyVal = current_variable; current_variable = null; } -void case_819() -#line 5240 "cs-parser.jay" +void case_807() +#line 5328 "cs-parser.jay" { var sl = yyVals[-2+yyTop] as StatementList; if (sl == null) { @@ -7777,15 +7907,15 @@ void case_819() yyVal = sl; } -void case_820() -#line 5256 "cs-parser.jay" +void case_808() +#line 5344 "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" +void case_809() +#line 5349 "cs-parser.jay" { start_block (GetLocation (yyVals[-5+yyTop])); current_block.IsCompilerGenerated = true; @@ -7795,8 +7925,8 @@ void case_821() yyVal = li; } -void case_822() -#line 5270 "cs-parser.jay" +void case_810() +#line 5358 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7808,58 +7938,58 @@ void case_822() yyVal = end_block (GetLocation (yyVals[-2+yyTop])); } -void case_829() -#line 5293 "cs-parser.jay" +void case_817() +#line 5381 "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" +void case_818() +#line 5389 "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" +void case_819() +#line 5397 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-1+yyTop]; yyVal = new Goto (lt.Value, GetLocation (yyVals[-2+yyTop])); lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_832() -#line 5315 "cs-parser.jay" +void case_820() +#line 5403 "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" +void case_821() +#line 5408 "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" +void case_822() +#line 5416 "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" +void case_823() +#line 5424 "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" +void case_824() +#line 5432 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; string s = lt.Value; @@ -7876,8 +8006,8 @@ void case_836() lbag.AddStatement (yyVal, GetLocation (yyVals[-2+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_837() -#line 5360 "cs-parser.jay" +void case_825() +#line 5448 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; string s = lt.Value; @@ -7892,29 +8022,29 @@ void case_837() lbag.AddStatement (yyVal, GetLocation (yyVals[-1+yyTop]), GetLocation (yyVals[0+yyTop])); } -void case_841() -#line 5386 "cs-parser.jay" +void case_829() +#line 5474 "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" +void case_830() +#line 5479 "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" +void case_831() +#line 5484 "cs-parser.jay" { report.Error (1524, GetLocation (yyVals[-2+yyTop]), "Expected catch or finally"); yyVal = null; } -void case_844() -#line 5404 "cs-parser.jay" +void case_832() +#line 5492 "cs-parser.jay" { var l = new List (2); @@ -7922,8 +8052,8 @@ void case_844() yyVal = l; } -void case_845() -#line 5411 "cs-parser.jay" +void case_833() +#line 5499 "cs-parser.jay" { var l = (List) yyVals[-1+yyTop]; @@ -7940,8 +8070,8 @@ void case_845() yyVal = l; } -void case_849() -#line 5439 "cs-parser.jay" +void case_837() +#line 5527 "cs-parser.jay" { start_block (GetLocation (yyVals[-3+yyTop])); var c = new Catch (current_block, GetLocation (yyVals[-4+yyTop])); @@ -7957,8 +8087,8 @@ void case_849() yyVal = c; } -void case_851() -#line 5458 "cs-parser.jay" +void case_839() +#line 5546 "cs-parser.jay" { if (yyToken == Token.CLOSE_PARENS) { report.Error (1015, lexer.Location, @@ -7970,15 +8100,15 @@ void case_851() yyVal = new Catch (null, GetLocation (yyVals[-2+yyTop])); } -void case_854() -#line 5486 "cs-parser.jay" +void case_842() +#line 5574 "cs-parser.jay" { if (!settings.Unsafe) Error_UnsafeCodeNotAllowed (GetLocation (yyVals[0+yyTop])); } -void case_856() -#line 5496 "cs-parser.jay" +void case_844() +#line 5584 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -7987,8 +8117,8 @@ void case_856() lbag.AddStatement (yyVal, GetLocation (yyVals[-3+yyTop]), GetLocation (yyVals[-1+yyTop])); } -void case_857() -#line 5507 "cs-parser.jay" +void case_845() +#line 5595 "cs-parser.jay" { start_block (GetLocation (yyVals[-2+yyTop])); @@ -7999,15 +8129,15 @@ void case_857() current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); } -void case_858() -#line 5517 "cs-parser.jay" +void case_846() +#line 5605 "cs-parser.jay" { yyVal = current_variable; current_variable = null; } -void case_859() -#line 5522 "cs-parser.jay" +void case_847() +#line 5610 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -8018,8 +8148,8 @@ void case_859() yyVal = end_block (GetLocation (yyVals[-2+yyTop])); } -void case_860() -#line 5535 "cs-parser.jay" +void case_848() +#line 5623 "cs-parser.jay" { start_block (GetLocation (yyVals[-2+yyTop])); @@ -8030,15 +8160,15 @@ void case_860() current_variable = new Using.VariableDeclaration ((FullNamedExpression) yyVals[-1+yyTop], li); } -void case_861() -#line 5545 "cs-parser.jay" +void case_849() +#line 5633 "cs-parser.jay" { yyVal = current_variable; current_variable = null; } -void case_862() -#line 5550 "cs-parser.jay" +void case_850() +#line 5638 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -8049,8 +8179,8 @@ void case_862() yyVal = end_block (GetLocation (yyVals[-2+yyTop])); } -void case_863() -#line 5560 "cs-parser.jay" +void case_851() +#line 5648 "cs-parser.jay" { if (yyVals[0+yyTop] is EmptyStatement && lexer.peek_token () == Token.OPEN_BRACE) Warning_EmptyStatement (GetLocation (yyVals[0+yyTop])); @@ -8060,15 +8190,16 @@ void case_863() yyVal = u; } -void case_865() -#line 5576 "cs-parser.jay" +void case_853() +#line 5664 "cs-parser.jay" { current_variable.Initializer = (Expression) yyVals[0+yyTop]; + lbag.AppendTo (current_variable, GetLocation (yyVals[-1+yyTop])); yyVal = current_variable; } -void case_866() -#line 5587 "cs-parser.jay" +void case_854() +#line 5676 "cs-parser.jay" { lexer.query_parsing = false; @@ -8081,8 +8212,8 @@ void case_866() current_block = current_block.Parent; } -void case_867() -#line 5599 "cs-parser.jay" +void case_855() +#line 5688 "cs-parser.jay" { Linq.AQueryClause from = yyVals[-1+yyTop] as Linq.AQueryClause; @@ -8093,8 +8224,8 @@ void case_867() current_block = current_block.Parent; } -void case_868() -#line 5610 "cs-parser.jay" +void case_856() +#line 5699 "cs-parser.jay" { lexer.query_parsing = false; yyVal = yyVals[-1+yyTop]; @@ -8103,16 +8234,16 @@ void case_868() current_block = current_block.Parent; } -void case_869() -#line 5617 "cs-parser.jay" +void case_857() +#line 5706 "cs-parser.jay" { yyVal = yyVals[-1+yyTop]; current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; } -void case_870() -#line 5626 "cs-parser.jay" +void case_858() +#line 5715 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8121,8 +8252,8 @@ void case_870() yyVal = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-3+yyTop]))); } -void case_871() -#line 5634 "cs-parser.jay" +void case_859() +#line 5723 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8135,8 +8266,8 @@ void case_871() ); } -void case_872() -#line 5649 "cs-parser.jay" +void case_860() +#line 5738 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8145,8 +8276,8 @@ void case_872() yyVal = new Linq.QueryExpression (new Linq.QueryStartClause ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], rv, GetLocation (yyVals[-3+yyTop]))); } -void case_873() -#line 5657 "cs-parser.jay" +void case_861() +#line 5746 "cs-parser.jay" { current_block = new Linq.QueryBlock (current_block, lexer.Location); @@ -8159,8 +8290,8 @@ void case_873() ); } -void case_875() -#line 5676 "cs-parser.jay" +void case_863() +#line 5765 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var sn = new Linq.RangeVariable (lt.Value, lt.Location); @@ -8172,8 +8303,8 @@ void case_875() ((Linq.QueryBlock)current_block).AddRangeVariable (sn); } -void case_877() -#line 5691 "cs-parser.jay" +void case_865() +#line 5780 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var sn = new Linq.RangeVariable (lt.Value, lt.Location); @@ -8188,8 +8319,8 @@ void case_877() ((Linq.QueryBlock)current_block).AddRangeVariable (sn); } -void case_878() -#line 5708 "cs-parser.jay" +void case_866() +#line 5797 "cs-parser.jay" { Linq.AQueryClause head = (Linq.AQueryClause)yyVals[-1+yyTop]; @@ -8205,15 +8336,15 @@ void case_878() yyVal = head; } -void case_880() -#line 5724 "cs-parser.jay" +void case_868() +#line 5813 "cs-parser.jay" { Error_SyntaxError (yyToken); yyVal = null; } -void case_882() -#line 5736 "cs-parser.jay" +void case_870() +#line 5825 "cs-parser.jay" { yyVal = new Linq.Select ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); @@ -8221,8 +8352,8 @@ void case_882() current_block = current_block.Parent; } -void case_883() -#line 5743 "cs-parser.jay" +void case_871() +#line 5832 "cs-parser.jay" { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); @@ -8231,8 +8362,8 @@ void case_883() linq_clause_blocks.Push ((Linq.QueryBlock)current_block); } -void case_884() -#line 5751 "cs-parser.jay" +void case_872() +#line 5840 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8240,8 +8371,8 @@ void case_884() current_block = new Linq.QueryBlock (current_block, lexer.Location); } -void case_885() -#line 5758 "cs-parser.jay" +void case_873() +#line 5847 "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])); @@ -8250,15 +8381,15 @@ void case_885() current_block = current_block.Parent; } -void case_889() -#line 5775 "cs-parser.jay" +void case_877() +#line 5864 "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" +void case_884() +#line 5884 "cs-parser.jay" { var lt = (Tokenizer.LocatedToken) yyVals[-3+yyTop]; var sn = new Linq.RangeVariable (lt.Value, lt.Location); @@ -8271,8 +8402,8 @@ void case_896() ((Linq.QueryBlock)current_block).AddRangeVariable (sn); } -void case_898() -#line 5814 "cs-parser.jay" +void case_886() +#line 5903 "cs-parser.jay" { yyVal = new Linq.Where ((Linq.QueryBlock)current_block, (Expression)yyVals[0+yyTop], GetLocation (yyVals[-2+yyTop])); @@ -8280,8 +8411,8 @@ void case_898() current_block = current_block.Parent; } -void case_899() -#line 5824 "cs-parser.jay" +void case_887() +#line 5913 "cs-parser.jay" { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); @@ -8290,8 +8421,8 @@ void case_899() linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } -void case_900() -#line 5832 "cs-parser.jay" +void case_888() +#line 5921 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8300,8 +8431,8 @@ void case_900() linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } -void case_901() -#line 5840 "cs-parser.jay" +void case_889() +#line 5929 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8310,8 +8441,8 @@ void case_901() current_block = new Linq.QueryBlock (current_block, lexer.Location); } -void case_902() -#line 5848 "cs-parser.jay" +void case_890() +#line 5937 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8350,8 +8481,8 @@ void case_902() ((Linq.QueryBlock)current_block).AddRangeVariable (into); } -void case_903() -#line 5886 "cs-parser.jay" +void case_891() +#line 5975 "cs-parser.jay" { if (linq_clause_blocks == null) linq_clause_blocks = new Stack (); @@ -8360,8 +8491,8 @@ void case_903() linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } -void case_904() -#line 5894 "cs-parser.jay" +void case_892() +#line 5983 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8370,8 +8501,8 @@ void case_904() linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } -void case_905() -#line 5902 "cs-parser.jay" +void case_893() +#line 5991 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8380,8 +8511,8 @@ void case_905() current_block = new Linq.QueryBlock (current_block, lexer.Location); } -void case_906() -#line 5910 "cs-parser.jay" +void case_894() +#line 5999 "cs-parser.jay" { current_block.AddStatement (new ContextualReturn ((Expression) yyVals[-1+yyTop])); current_block.SetEndLocation (lexer.Location); @@ -8422,8 +8553,8 @@ void case_906() ((Linq.QueryBlock)current_block).AddRangeVariable (into); } -void case_910() -#line 5965 "cs-parser.jay" +void case_898() +#line 6054 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8431,8 +8562,8 @@ void case_910() yyVal = yyVals[0+yyTop]; } -void case_912() -#line 5976 "cs-parser.jay" +void case_900() +#line 6065 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8440,15 +8571,15 @@ void case_912() current_block = new Linq.QueryBlock (current_block, lexer.Location); } -void case_913() -#line 5983 "cs-parser.jay" +void case_901() +#line 6072 "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" +void case_903() +#line 6081 "cs-parser.jay" { current_block.SetEndLocation (lexer.Location); current_block = current_block.Parent; @@ -8456,43 +8587,43 @@ void case_915() current_block = new Linq.QueryBlock ((Linq.QueryBlock) current_block, lexer.Location); } -void case_916() -#line 5999 "cs-parser.jay" +void case_904() +#line 6088 "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" +void case_906() +#line 6100 "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" +void case_907() +#line 6105 "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" +void case_909() +#line 6117 "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" +void case_910() +#line 6122 "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" +void case_912() +#line 6132 "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*/ @@ -8509,8 +8640,8 @@ void case_924() linq_clause_blocks.Push ((Linq.QueryBlock) current_block); } -void case_925() -#line 6059 "cs-parser.jay" +void case_913() +#line 6148 "cs-parser.jay" { var current_block = linq_clause_blocks.Pop (); var lt = (Tokenizer.LocatedToken) yyVals[-2+yyTop]; @@ -8520,8 +8651,8 @@ void case_925() }; } -void case_928() -#line 6086 "cs-parser.jay" +void case_916() +#line 6175 "cs-parser.jay" { current_container = new Class (current_namespace, current_class, new MemberName (""), Modifiers.PUBLIC, null); current_class = current_container; @@ -8552,8 +8683,8 @@ void case_928() start_block (lexer.Location); } -void case_929() -#line 6116 "cs-parser.jay" +void case_917() +#line 6205 "cs-parser.jay" { --lexer.parsing_block; Method method = (Method) oob_stack.Pop (); @@ -8564,16 +8695,16 @@ void case_929() current_local_parameters = null; } -void case_939() -#line 6159 "cs-parser.jay" +void case_927() +#line 6248 "cs-parser.jay" { module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-1+yyTop]; module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; yyVal = null; } -void case_940() -#line 6165 "cs-parser.jay" +void case_928() +#line 6254 "cs-parser.jay" { module.DocumentationBuilder.ParsedBuiltinType = (TypeExpression)yyVals[-3+yyTop]; module.DocumentationBuilder.ParsedParameters = (List)yyVals[0+yyTop]; @@ -8581,15 +8712,15 @@ void case_940() yyVal = new MemberName (lt.Value); } -void case_943() -#line 6180 "cs-parser.jay" +void case_931() +#line 6269 "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" +void case_932() +#line 6274 "cs-parser.jay" { var p = (List)yyVals[0+yyTop] ?? new List (1); p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); @@ -8598,8 +8729,8 @@ void case_944() yyVal = null; } -void case_945() -#line 6193 "cs-parser.jay" +void case_933() +#line 6282 "cs-parser.jay" { var p = (List)yyVals[0+yyTop] ?? new List (1); p.Add (new DocumentationParameter ((FullNamedExpression) yyVals[-1+yyTop])); @@ -8608,8 +8739,8 @@ void case_945() yyVal = null; } -void case_946() -#line 6201 "cs-parser.jay" +void case_934() +#line 6290 "cs-parser.jay" { var p = (List)yyVals[0+yyTop] ?? new List (1); module.DocumentationBuilder.ParsedParameters = p; @@ -8617,24 +8748,24 @@ void case_946() yyVal = null; } -void case_954() -#line 6239 "cs-parser.jay" +void case_942() +#line 6328 "cs-parser.jay" { var parameters = new List (); parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); yyVal = parameters; } -void case_955() -#line 6245 "cs-parser.jay" +void case_943() +#line 6334 "cs-parser.jay" { var parameters = yyVals[-2+yyTop] as List; parameters.Add ((DocumentationParameter) yyVals[0+yyTop]); yyVal = parameters; } -void case_956() -#line 6254 "cs-parser.jay" +void case_944() +#line 6343 "cs-parser.jay" { if (yyVals[-1+yyTop] != null) yyVal = new DocumentationParameter ((Parameter.Modifier) yyVals[-1+yyTop], (FullNamedExpression) yyVals[0+yyTop]); @@ -8653,93 +8784,92 @@ void case_956() 37, 37, 42, 39, 40, 41, 41, 43, 43, 43, 43, 43, 44, 44, 48, 45, 47, 49, 49, 49, 50, 50, 51, 51, 52, 52, 52, 52, 52, 52, - 52, 52, 52, 52, 52, 65, 67, 70, 71, 29, - 29, 73, 69, 72, 72, 74, 74, 75, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 78, 53, 79, - 79, 80, 80, 81, 83, 77, 77, 82, 82, 88, - 54, 92, 54, 54, 87, 95, 87, 89, 89, 96, - 96, 97, 98, 97, 93, 93, 99, 99, 100, 101, - 91, 91, 94, 94, 94, 104, 55, 107, 108, 102, - 109, 110, 111, 102, 102, 103, 103, 106, 106, 114, - 114, 114, 114, 114, 114, 114, 114, 114, 114, 115, - 115, 118, 118, 118, 121, 118, 119, 119, 122, 122, - 123, 123, 123, 116, 116, 116, 124, 124, 124, 117, - 126, 128, 129, 56, 131, 132, 133, 58, 127, 127, - 127, 127, 127, 137, 134, 138, 135, 136, 136, 136, - 139, 140, 141, 143, 30, 30, 142, 142, 144, 144, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 148, - 59, 147, 147, 149, 149, 152, 146, 146, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 154, 153, 155, 153, 153, 153, 60, 158, 160, 156, - 157, 157, 159, 159, 164, 162, 165, 162, 162, 166, - 61, 168, 57, 171, 172, 57, 167, 174, 167, 169, - 169, 175, 175, 176, 177, 176, 178, 173, 170, 170, - 170, 170, 170, 182, 179, 183, 180, 181, 181, 185, - 187, 188, 31, 184, 184, 184, 186, 186, 186, 189, - 189, 190, 191, 190, 192, 193, 194, 32, 195, 195, - 17, 17, 196, 196, 199, 198, 198, 198, 200, 200, - 202, 64, 125, 105, 105, 130, 130, 203, 203, 203, - 201, 201, 204, 204, 205, 205, 207, 207, 86, 76, - 76, 90, 90, 120, 120, 150, 150, 208, 208, 208, - 208, 208, 212, 212, 213, 213, 211, 211, 211, 211, - 211, 211, 211, 214, 214, 214, 214, 214, 214, 214, - 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, - 215, 215, 216, 216, 216, 217, 217, 217, 237, 237, - 238, 238, 239, 239, 219, 219, 236, 236, 236, 236, - 236, 236, 236, 236, 221, 240, 240, 241, 241, 242, - 242, 244, 244, 244, 245, 245, 245, 245, 245, 246, - 246, 163, 163, 250, 250, 250, 250, 250, 252, 252, - 251, 251, 253, 253, 253, 253, 254, 222, 249, 249, - 249, 255, 255, 256, 256, 223, 224, 224, 225, 226, - 227, 227, 218, 218, 218, 218, 218, 261, 257, 228, - 262, 262, 263, 263, 264, 264, 265, 265, 265, 265, - 258, 258, 209, 209, 260, 260, 266, 266, 259, 259, - 85, 85, 267, 267, 268, 229, 269, 269, 269, 270, - 270, 270, 270, 270, 271, 197, 230, 231, 232, 233, - 273, 234, 274, 234, 272, 272, 276, 275, 220, 277, - 277, 277, 277, 277, 279, 280, 278, 278, 278, 278, - 278, 278, 278, 281, 281, 281, 281, 282, 282, 282, - 282, 282, 282, 283, 283, 283, 284, 284, 284, 284, - 284, 285, 285, 285, 286, 286, 287, 287, 288, 288, - 289, 289, 290, 290, 291, 291, 292, 292, 293, 293, - 293, 293, 293, 293, 293, 293, 293, 293, 293, 294, - 294, 295, 295, 295, 296, 296, 297, 297, 300, 298, - 299, 299, 302, 301, 303, 301, 304, 305, 301, 306, - 307, 301, 46, 46, 247, 247, 247, 247, 235, 235, - 235, 84, 309, 310, 311, 312, 313, 28, 63, 63, - 62, 62, 112, 112, 314, 314, 314, 314, 314, 314, - 314, 314, 314, 314, 314, 314, 314, 314, 314, 66, - 66, 68, 68, 68, 315, 315, 316, 317, 317, 318, - 318, 318, 318, 206, 206, 319, 319, 321, 113, 322, - 322, 323, 161, 320, 320, 324, 324, 325, 325, 325, - 325, 329, 329, 330, 330, 330, 327, 327, 327, 327, - 327, 327, 327, 327, 327, 327, 327, 327, 327, 331, - 331, 331, 331, 331, 331, 331, 331, 331, 331, 331, - 331, 331, 345, 345, 345, 345, 332, 346, 328, 347, - 347, 348, 348, 348, 348, 348, 348, 210, 210, 349, - 351, 326, 354, 326, 350, 350, 350, 352, 352, 357, - 357, 358, 358, 353, 353, 355, 355, 359, 359, 360, - 356, 356, 356, 333, 333, 344, 344, 361, 362, 362, - 334, 334, 363, 363, 366, 364, 365, 365, 367, 367, - 367, 370, 368, 369, 369, 371, 371, 335, 335, 335, - 335, 372, 373, 377, 374, 376, 376, 378, 378, 382, - 381, 381, 379, 379, 380, 380, 384, 383, 383, 375, - 385, 375, 336, 336, 336, 336, 336, 336, 386, 387, - 388, 388, 388, 389, 390, 391, 391, 392, 392, 337, - 337, 337, 337, 393, 393, 395, 395, 394, 396, 394, - 394, 338, 339, 397, 342, 340, 399, 400, 343, 401, - 402, 341, 341, 398, 398, 308, 308, 308, 308, 403, - 403, 405, 405, 407, 406, 408, 406, 404, 404, 404, - 412, 410, 413, 414, 410, 409, 409, 415, 415, 416, - 416, 416, 416, 416, 421, 417, 422, 418, 423, 424, - 425, 419, 427, 428, 429, 419, 426, 426, 431, 420, - 430, 434, 430, 433, 436, 433, 432, 432, 432, 435, - 435, 435, 411, 437, 411, 3, 3, 438, 3, 3, - 439, 439, 248, 248, 243, 243, 5, 440, 440, 440, - 440, 444, 440, 440, 440, 440, 441, 441, 442, 445, - 442, 443, 443, 446, 446, 447, + 52, 52, 52, 52, 52, 65, 67, 69, 70, 71, + 29, 29, 74, 53, 75, 75, 76, 76, 77, 79, + 73, 73, 78, 78, 84, 54, 88, 54, 54, 83, + 91, 83, 85, 85, 92, 92, 93, 94, 93, 89, + 89, 95, 95, 96, 97, 87, 87, 90, 90, 90, + 100, 55, 103, 104, 98, 105, 106, 107, 98, 98, + 99, 99, 102, 102, 110, 110, 110, 110, 110, 110, + 110, 110, 110, 110, 111, 111, 114, 114, 114, 117, + 114, 115, 115, 118, 118, 119, 119, 119, 112, 112, + 112, 120, 120, 120, 113, 122, 124, 125, 56, 127, + 128, 129, 58, 123, 123, 123, 123, 123, 133, 130, + 134, 131, 132, 132, 132, 135, 136, 137, 139, 30, + 30, 138, 138, 140, 140, 141, 141, 141, 141, 141, + 141, 141, 141, 141, 144, 59, 143, 143, 145, 145, + 148, 142, 142, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 147, 147, 147, 147, 147, + 147, 147, 147, 147, 147, 150, 149, 151, 149, 149, + 149, 60, 154, 156, 152, 153, 153, 155, 155, 160, + 158, 161, 158, 158, 162, 61, 164, 57, 167, 168, + 57, 163, 170, 163, 165, 165, 171, 171, 172, 173, + 172, 174, 169, 166, 166, 166, 166, 166, 178, 175, + 179, 176, 177, 177, 180, 182, 184, 185, 31, 181, + 181, 181, 183, 183, 183, 186, 186, 187, 188, 187, + 189, 190, 191, 32, 192, 192, 17, 17, 193, 193, + 196, 195, 195, 195, 197, 197, 199, 64, 121, 101, + 101, 126, 126, 200, 200, 200, 198, 198, 201, 201, + 202, 202, 204, 204, 82, 72, 72, 86, 86, 116, + 116, 146, 146, 205, 205, 205, 205, 205, 209, 209, + 210, 210, 208, 208, 208, 208, 208, 208, 208, 211, + 211, 211, 211, 211, 211, 211, 211, 211, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 212, 212, + 212, 212, 212, 212, 212, 212, 212, 212, 213, 213, + 213, 214, 214, 214, 234, 234, 235, 235, 236, 236, + 216, 216, 233, 233, 233, 233, 233, 233, 233, 233, + 218, 237, 237, 238, 238, 239, 239, 241, 241, 241, + 242, 242, 242, 242, 242, 243, 243, 159, 159, 247, + 247, 247, 247, 247, 249, 249, 248, 248, 250, 250, + 250, 250, 251, 219, 246, 246, 246, 252, 252, 253, + 253, 220, 221, 221, 222, 223, 224, 224, 215, 215, + 215, 215, 215, 258, 254, 225, 259, 259, 260, 260, + 261, 261, 262, 262, 262, 262, 255, 255, 206, 206, + 257, 257, 263, 263, 256, 256, 81, 81, 264, 264, + 265, 226, 266, 266, 266, 267, 267, 267, 267, 267, + 268, 194, 227, 228, 229, 230, 270, 231, 271, 231, + 269, 269, 273, 272, 217, 274, 274, 274, 274, 274, + 276, 277, 275, 275, 275, 275, 275, 275, 275, 278, + 278, 278, 278, 279, 279, 279, 279, 279, 279, 280, + 280, 280, 281, 281, 281, 281, 281, 282, 282, 282, + 283, 283, 284, 284, 285, 285, 286, 286, 287, 287, + 288, 288, 289, 289, 290, 290, 290, 290, 290, 290, + 290, 290, 290, 290, 290, 291, 291, 292, 292, 292, + 293, 293, 294, 294, 297, 295, 296, 296, 299, 298, + 300, 298, 301, 302, 298, 303, 304, 298, 46, 46, + 244, 244, 244, 244, 232, 232, 232, 80, 306, 307, + 308, 309, 310, 28, 63, 63, 62, 62, 108, 108, + 311, 311, 311, 311, 311, 311, 311, 311, 311, 311, + 311, 311, 311, 311, 311, 66, 66, 68, 68, 68, + 312, 312, 313, 314, 314, 315, 315, 315, 315, 203, + 203, 316, 316, 318, 109, 319, 319, 320, 157, 317, + 317, 321, 321, 322, 322, 322, 322, 326, 326, 327, + 327, 327, 324, 324, 324, 324, 324, 324, 324, 324, + 324, 324, 324, 324, 324, 328, 328, 328, 328, 328, + 328, 328, 328, 328, 328, 328, 328, 328, 342, 342, + 342, 342, 329, 343, 325, 344, 344, 345, 345, 345, + 345, 345, 345, 207, 207, 346, 348, 323, 351, 323, + 347, 347, 347, 349, 349, 355, 355, 354, 354, 356, + 356, 350, 350, 352, 352, 357, 357, 358, 353, 353, + 353, 330, 330, 341, 341, 359, 360, 360, 331, 331, + 361, 361, 364, 362, 363, 363, 365, 365, 365, 368, + 366, 367, 367, 369, 369, 332, 332, 332, 332, 370, + 371, 375, 372, 374, 374, 376, 376, 380, 379, 379, + 377, 377, 378, 378, 382, 381, 381, 373, 383, 373, + 333, 333, 333, 333, 333, 333, 384, 385, 386, 386, + 386, 387, 388, 389, 389, 390, 390, 334, 334, 334, + 334, 391, 391, 393, 393, 392, 394, 392, 392, 335, + 336, 395, 339, 337, 397, 398, 340, 399, 400, 338, + 338, 396, 396, 305, 305, 305, 305, 401, 401, 403, + 403, 405, 404, 406, 404, 402, 402, 402, 410, 408, + 411, 412, 408, 407, 407, 413, 413, 414, 414, 414, + 414, 414, 419, 415, 420, 416, 421, 422, 423, 417, + 425, 426, 427, 417, 424, 424, 429, 418, 428, 432, + 428, 431, 434, 431, 430, 430, 430, 433, 433, 433, + 409, 435, 409, 3, 3, 436, 3, 3, 437, 437, + 245, 245, 240, 240, 5, 438, 438, 438, 438, 442, + 438, 438, 438, 438, 439, 439, 440, 443, 440, 441, + 441, 444, 444, 445, }; static readonly short [] yyLen = { 2, 2, 0, 3, 1, 2, 4, 3, 1, 0, 1, @@ -8751,932 +8881,939 @@ void case_956() 1, 3, 0, 3, 1, 0, 3, 0, 1, 1, 3, 3, 1, 1, 0, 4, 4, 0, 1, 1, 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 0, 0, 0, 0, 13, - 5, 0, 4, 0, 1, 1, 2, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 9, 0, - 1, 1, 2, 3, 0, 3, 1, 1, 1, 0, - 8, 0, 9, 6, 0, 0, 3, 0, 1, 1, - 2, 2, 0, 5, 0, 1, 1, 2, 3, 0, - 4, 2, 1, 1, 1, 0, 3, 0, 0, 10, - 0, 0, 0, 12, 8, 1, 1, 0, 1, 1, - 3, 3, 3, 5, 3, 5, 1, 1, 1, 1, - 3, 4, 6, 4, 0, 7, 0, 1, 1, 2, - 1, 1, 1, 4, 6, 4, 1, 2, 2, 1, - 0, 0, 0, 10, 0, 0, 0, 13, 1, 2, - 1, 2, 1, 0, 5, 0, 5, 1, 1, 1, - 0, 0, 0, 0, 15, 5, 0, 1, 1, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 5, 1, 1, 1, 1, 0, 7, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 16, 5, 0, 9, 0, 1, 1, 2, 3, 0, + 3, 1, 1, 1, 0, 8, 0, 9, 6, 0, + 0, 3, 0, 1, 1, 2, 2, 0, 5, 0, + 1, 1, 2, 3, 0, 4, 2, 1, 1, 1, + 0, 3, 0, 0, 10, 0, 0, 0, 12, 8, + 1, 1, 0, 1, 1, 3, 3, 3, 5, 3, + 5, 1, 1, 1, 1, 3, 4, 6, 4, 0, + 7, 0, 1, 1, 2, 1, 1, 1, 4, 6, + 4, 1, 2, 2, 1, 0, 0, 0, 10, 0, + 0, 0, 13, 1, 2, 1, 2, 1, 0, 5, + 0, 5, 1, 1, 1, 0, 0, 0, 0, 15, + 5, 0, 1, 1, 2, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 0, 5, 1, 1, 1, 1, + 0, 7, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 7, 0, 7, 2, + 2, 2, 0, 0, 9, 1, 1, 0, 1, 0, + 6, 0, 6, 1, 0, 8, 0, 9, 0, 0, + 10, 0, 0, 3, 0, 1, 1, 2, 2, 0, + 5, 0, 2, 2, 2, 1, 1, 1, 0, 5, + 0, 5, 1, 1, 0, 0, 0, 0, 13, 0, + 2, 2, 0, 1, 2, 1, 3, 2, 0, 5, + 0, 0, 0, 13, 0, 1, 1, 3, 1, 4, + 2, 0, 3, 2, 1, 3, 0, 3, 1, 1, + 3, 1, 2, 3, 4, 4, 0, 3, 1, 3, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 2, 2, 2, 2, 2, 2, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 0, 7, 0, 7, 2, 2, 2, 0, 0, 9, - 1, 1, 0, 1, 0, 6, 0, 6, 1, 0, - 8, 0, 9, 0, 0, 10, 0, 0, 3, 0, - 1, 1, 2, 2, 0, 5, 0, 2, 2, 2, - 1, 1, 1, 0, 5, 0, 5, 1, 1, 0, - 0, 0, 12, 0, 2, 2, 0, 1, 2, 1, - 3, 2, 0, 5, 0, 0, 0, 13, 0, 1, - 1, 3, 1, 4, 2, 0, 3, 2, 1, 3, - 0, 3, 1, 1, 3, 1, 2, 3, 4, 4, - 0, 3, 1, 3, 3, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, - 2, 2, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 3, 3, 4, 4, 4, 3, - 3, 4, 3, 4, 4, 0, 1, 3, 4, 0, - 1, 1, 3, 2, 3, 1, 2, 3, 2, 1, - 1, 0, 1, 1, 3, 3, 2, 2, 1, 1, - 1, 1, 2, 2, 4, 3, 1, 4, 1, 3, - 2, 1, 3, 1, 1, 1, 4, 3, 2, 2, - 6, 3, 7, 4, 3, 7, 3, 0, 2, 4, - 1, 2, 0, 1, 1, 3, 3, 1, 1, 1, - 0, 1, 1, 2, 2, 3, 1, 2, 0, 1, - 2, 4, 1, 3, 0, 5, 1, 1, 1, 2, - 3, 3, 4, 4, 1, 2, 4, 4, 4, 4, - 0, 4, 0, 5, 0, 1, 0, 4, 4, 1, - 2, 2, 1, 1, 4, 2, 1, 2, 2, 2, - 2, 2, 2, 1, 3, 3, 3, 1, 3, 3, - 3, 3, 3, 1, 3, 3, 1, 3, 3, 3, - 3, 1, 3, 3, 1, 3, 1, 3, 1, 3, - 1, 3, 1, 3, 1, 3, 1, 5, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, - 3, 3, 2, 1, 0, 1, 1, 1, 0, 2, - 1, 1, 0, 4, 0, 5, 0, 0, 7, 0, - 0, 8, 1, 1, 1, 1, 1, 1, 6, 4, - 4, 1, 1, 0, 0, 0, 0, 15, 0, 1, - 0, 1, 1, 2, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, - 2, 0, 1, 1, 1, 2, 4, 1, 3, 1, - 3, 1, 1, 0, 1, 1, 1, 0, 4, 1, - 1, 0, 4, 0, 1, 1, 2, 1, 1, 1, - 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, + 3, 3, 4, 4, 4, 3, 3, 4, 3, 4, + 4, 0, 1, 3, 4, 0, 1, 1, 3, 2, + 3, 1, 2, 3, 2, 1, 1, 0, 1, 1, + 3, 3, 2, 2, 1, 1, 1, 1, 2, 2, + 4, 3, 1, 4, 1, 3, 2, 1, 3, 1, + 1, 1, 4, 3, 2, 2, 6, 3, 7, 4, + 3, 7, 3, 0, 2, 4, 1, 2, 0, 1, + 1, 3, 3, 1, 1, 1, 0, 1, 1, 2, + 2, 3, 1, 2, 0, 1, 2, 4, 1, 3, + 0, 5, 1, 1, 1, 2, 3, 3, 4, 4, + 1, 2, 4, 4, 4, 4, 0, 4, 0, 5, + 0, 1, 0, 4, 4, 1, 2, 2, 1, 1, + 4, 2, 1, 2, 2, 2, 2, 2, 2, 1, + 3, 3, 3, 1, 3, 3, 3, 3, 3, 1, + 3, 3, 1, 3, 3, 3, 3, 1, 3, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 5, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 1, 3, 3, 2, 1, + 0, 1, 1, 1, 0, 2, 1, 1, 0, 4, + 0, 5, 0, 0, 7, 0, 0, 8, 1, 1, + 1, 1, 1, 1, 6, 4, 4, 1, 1, 0, + 0, 0, 0, 15, 0, 1, 0, 1, 1, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 0, 2, 0, 1, 1, + 1, 2, 4, 1, 3, 1, 3, 1, 1, 0, + 1, 1, 1, 0, 4, 1, 1, 0, 4, 0, + 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 4, 1, - 2, 2, 2, 2, 2, 2, 1, 1, 2, 1, - 0, 6, 0, 7, 0, 2, 1, 0, 1, 1, - 2, 2, 4, 0, 2, 0, 1, 1, 2, 4, - 1, 5, 2, 2, 2, 2, 2, 1, 1, 1, - 1, 1, 5, 7, 0, 8, 0, 1, 1, 2, - 1, 0, 3, 1, 2, 3, 1, 1, 1, 1, - 1, 5, 7, 0, 4, 7, 1, 0, 1, 0, - 5, 1, 0, 1, 0, 1, 1, 1, 3, 6, - 0, 9, 1, 1, 1, 1, 1, 1, 2, 2, - 3, 4, 3, 3, 3, 4, 3, 0, 1, 3, - 4, 5, 3, 1, 2, 0, 1, 2, 0, 7, - 3, 2, 2, 0, 3, 5, 0, 0, 10, 0, - 0, 10, 5, 0, 2, 2, 2, 2, 2, 4, - 5, 4, 5, 0, 5, 0, 6, 3, 2, 1, - 0, 3, 0, 0, 6, 0, 1, 1, 2, 1, - 1, 1, 1, 1, 0, 5, 0, 3, 0, 0, - 0, 12, 0, 0, 0, 13, 0, 2, 0, 3, - 1, 0, 4, 1, 0, 4, 1, 2, 2, 1, - 2, 2, 0, 0, 4, 2, 3, 0, 4, 2, - 2, 3, 0, 1, 1, 1, 2, 2, 2, 4, - 3, 0, 7, 4, 4, 3, 1, 3, 0, 0, - 4, 0, 1, 1, 3, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 0, 4, 1, 2, 2, 2, 2, + 2, 2, 1, 1, 2, 1, 0, 6, 0, 7, + 0, 2, 1, 0, 1, 0, 1, 1, 2, 2, + 4, 0, 2, 0, 1, 1, 2, 4, 1, 5, + 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, + 5, 7, 0, 8, 0, 1, 1, 2, 1, 0, + 3, 1, 2, 3, 1, 1, 1, 1, 1, 5, + 7, 0, 4, 7, 1, 0, 1, 0, 5, 1, + 0, 1, 0, 1, 1, 1, 3, 6, 0, 9, + 1, 1, 1, 1, 1, 1, 2, 2, 3, 4, + 3, 3, 3, 4, 3, 0, 1, 3, 4, 5, + 3, 1, 2, 0, 1, 2, 0, 7, 3, 2, + 2, 0, 3, 5, 0, 0, 10, 0, 0, 10, + 5, 0, 2, 2, 2, 2, 2, 4, 5, 4, + 5, 0, 5, 0, 6, 3, 2, 1, 0, 3, + 0, 0, 6, 0, 1, 1, 2, 1, 1, 1, + 1, 1, 0, 5, 0, 3, 0, 0, 0, 12, + 0, 0, 0, 13, 0, 2, 0, 3, 1, 0, + 4, 1, 0, 4, 1, 2, 2, 1, 2, 2, + 0, 0, 4, 2, 3, 0, 4, 2, 2, 3, + 0, 1, 1, 1, 2, 2, 2, 4, 3, 0, + 7, 4, 4, 3, 1, 3, 0, 0, 4, 0, + 1, 1, 3, 2, }; static readonly short [] yyDefRed = { 0, 8, 0, 0, 0, 0, 0, 0, 0, 2, 4, - 0, 0, 11, 14, 0, 926, 0, 0, 930, 0, - 0, 15, 17, 18, 389, 395, 402, 390, 392, 0, - 391, 0, 398, 400, 387, 0, 394, 396, 388, 399, - 401, 397, 351, 947, 0, 393, 937, 0, 10, 1, - 0, 0, 0, 12, 0, 780, 0, 0, 0, 0, - 0, 0, 0, 0, 430, 0, 0, 0, 0, 0, - 0, 0, 428, 0, 0, 0, 486, 0, 429, 0, - 525, 0, 854, 0, 0, 0, 638, 0, 0, 0, - 0, 0, 0, 0, 688, 0, 737, 0, 0, 0, - 0, 0, 0, 0, 0, 427, 0, 627, 0, 779, - 720, 0, 0, 0, 0, 404, 405, 0, 407, 408, - 409, 410, 411, 412, 413, 414, 415, 416, 417, 418, - 419, 420, 421, 422, 425, 426, 634, 557, 0, 553, - 554, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 635, 633, 636, 637, 704, 706, 0, 702, - 705, 721, 723, 724, 725, 726, 727, 728, 729, 730, - 731, 732, 722, 0, 0, 0, 781, 782, 798, 799, - 800, 801, 823, 824, 825, 826, 827, 828, 0, 0, - 0, 20, 0, 0, 0, 341, 0, 343, 934, 16, - 927, 0, 0, 254, 253, 250, 255, 256, 249, 268, - 267, 260, 261, 257, 259, 258, 262, 251, 252, 263, - 264, 270, 269, 265, 266, 0, 0, 950, 0, 939, - 0, 938, 3, 52, 0, 0, 0, 42, 39, 41, + 0, 0, 11, 14, 0, 914, 0, 0, 918, 0, + 0, 15, 17, 18, 375, 381, 388, 376, 378, 0, + 377, 0, 384, 386, 373, 0, 380, 382, 374, 385, + 387, 383, 337, 935, 0, 379, 925, 0, 10, 1, + 0, 0, 0, 12, 0, 768, 0, 0, 0, 0, + 0, 0, 0, 0, 416, 0, 0, 0, 0, 0, + 0, 0, 414, 0, 0, 0, 472, 0, 415, 0, + 511, 0, 842, 0, 0, 0, 624, 0, 0, 0, + 0, 0, 0, 0, 674, 0, 723, 0, 0, 0, + 0, 0, 0, 0, 0, 413, 0, 613, 0, 767, + 706, 0, 0, 0, 0, 390, 391, 0, 393, 394, + 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, + 405, 406, 407, 408, 411, 412, 620, 543, 0, 539, + 540, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 621, 619, 622, 623, 690, 692, 0, 688, + 691, 707, 709, 710, 711, 712, 713, 714, 715, 716, + 717, 718, 708, 0, 0, 0, 769, 770, 786, 787, + 788, 789, 811, 812, 813, 814, 815, 816, 0, 0, + 0, 20, 0, 0, 0, 327, 0, 329, 922, 16, + 915, 0, 0, 239, 238, 235, 240, 241, 234, 253, + 252, 245, 246, 242, 244, 243, 247, 236, 237, 248, + 249, 255, 254, 250, 251, 0, 0, 938, 0, 927, + 0, 926, 3, 52, 0, 0, 0, 42, 39, 41, 43, 44, 45, 46, 47, 50, 13, 0, 0, 0, - 829, 431, 432, 852, 0, 0, 0, 0, 0, 0, - 406, 0, 830, 0, 547, 541, 546, 736, 778, 707, - 734, 733, 735, 708, 709, 710, 711, 712, 713, 714, - 715, 716, 717, 718, 719, 0, 0, 0, 804, 0, + 817, 417, 418, 840, 0, 0, 0, 0, 0, 0, + 392, 0, 818, 0, 533, 527, 532, 722, 766, 693, + 720, 719, 721, 694, 695, 696, 697, 698, 699, 700, + 701, 702, 703, 704, 705, 0, 0, 0, 792, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 839, 0, 403, 0, 0, 0, 0, 0, 0, - 853, 0, 0, 0, 750, 746, 0, 0, 0, 0, - 0, 0, 370, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 630, 556, 0, 0, 552, 558, 559, 551, - 563, 562, 560, 561, 0, 0, 623, 738, 536, 0, - 424, 423, 0, 0, 0, 0, 340, 0, 744, 745, - 0, 489, 490, 0, 0, 0, 742, 743, 0, 0, + 0, 827, 0, 389, 0, 0, 0, 0, 0, 0, + 841, 0, 0, 0, 736, 732, 0, 0, 0, 0, + 0, 0, 356, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 616, 542, 0, 0, 538, 544, 545, 537, + 549, 548, 546, 547, 0, 0, 609, 724, 522, 0, + 410, 409, 0, 0, 0, 0, 326, 0, 730, 731, + 0, 475, 476, 0, 0, 0, 728, 729, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 929, 703, 751, 741, 0, 776, 777, 880, - 897, 0, 0, 0, 909, 868, 866, 890, 0, 0, - 888, 891, 892, 893, 894, 869, 867, 0, 0, 0, - 345, 0, 21, 0, 0, 0, 946, 0, 352, 0, - 0, 0, 948, 0, 0, 40, 660, 666, 658, 0, - 655, 665, 659, 657, 656, 663, 661, 662, 668, 664, - 667, 669, 0, 0, 653, 51, 488, 0, 0, 484, - 485, 0, 482, 0, 753, 0, 0, 0, 0, 774, - 775, 0, 0, 0, 642, 0, 833, 831, 643, 0, - 0, 510, 0, 0, 0, 501, 0, 505, 515, 517, - 0, 497, 0, 0, 0, 0, 0, 492, 0, 495, - 0, 499, 372, 834, 0, 0, 835, 843, 0, 0, - 0, 844, 0, 0, 855, 0, 0, 749, 0, 382, - 0, 378, 379, 0, 377, 380, 381, 0, 0, 0, - 564, 0, 0, 543, 625, 0, 701, 0, 0, 696, - 698, 699, 700, 435, 436, 837, 0, 0, 0, 348, - 349, 0, 192, 191, 193, 0, 0, 0, 0, 374, - 0, 610, 0, 0, 440, 0, 443, 0, 441, 0, - 0, 0, 0, 0, 0, 469, 472, 0, 0, 464, - 471, 470, 0, 599, 600, 601, 602, 603, 604, 605, - 606, 607, 609, 608, 565, 567, 566, 572, 573, 0, + 0, 0, 917, 689, 737, 727, 0, 764, 765, 868, + 885, 0, 0, 0, 897, 856, 854, 878, 0, 0, + 876, 879, 880, 881, 882, 857, 855, 0, 0, 0, + 331, 0, 21, 0, 0, 0, 934, 0, 338, 0, + 0, 0, 936, 0, 0, 40, 646, 652, 644, 0, + 641, 651, 645, 643, 642, 649, 647, 648, 654, 650, + 653, 655, 0, 0, 639, 51, 474, 0, 0, 470, + 471, 0, 468, 0, 739, 0, 0, 0, 0, 762, + 763, 0, 0, 0, 628, 0, 821, 819, 629, 0, + 0, 496, 0, 0, 0, 487, 0, 491, 501, 503, + 0, 483, 0, 0, 0, 0, 0, 478, 0, 481, + 0, 485, 358, 822, 0, 0, 823, 831, 0, 0, + 0, 832, 0, 0, 843, 0, 0, 735, 0, 368, + 0, 364, 365, 0, 363, 366, 367, 0, 0, 0, + 550, 0, 0, 529, 611, 0, 687, 0, 0, 682, + 684, 685, 686, 421, 422, 825, 0, 0, 0, 334, + 335, 0, 177, 176, 178, 0, 0, 0, 0, 360, + 0, 596, 0, 0, 426, 0, 429, 0, 427, 0, + 0, 0, 0, 0, 0, 455, 458, 0, 0, 450, + 457, 456, 0, 585, 586, 587, 588, 589, 590, 591, + 592, 593, 595, 594, 551, 553, 552, 558, 559, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 596, 0, 0, 514, 0, 0, - 0, 0, 0, 0, 0, 881, 883, 879, 0, 889, - 0, 0, 342, 944, 945, 366, 0, 0, 363, 0, - 0, 189, 0, 0, 954, 940, 942, 60, 58, 59, + 0, 0, 0, 0, 582, 0, 0, 500, 0, 0, + 0, 0, 0, 0, 0, 869, 871, 867, 0, 877, + 0, 0, 328, 932, 933, 352, 0, 0, 349, 0, + 0, 174, 0, 0, 942, 928, 930, 60, 58, 59, 0, 0, 53, 0, 0, 61, 63, 27, 25, 0, - 0, 0, 650, 0, 654, 439, 0, 487, 0, 538, - 0, 549, 179, 200, 0, 0, 169, 0, 0, 0, - 180, 542, 0, 857, 807, 0, 818, 805, 0, 809, - 0, 0, 0, 832, 0, 0, 0, 500, 0, 516, - 518, 0, 0, 456, 0, 0, 452, 0, 0, 479, - 0, 520, 494, 0, 155, 521, 153, 154, 523, 0, - 537, 0, 848, 0, 841, 0, 845, 529, 0, 0, - 0, 367, 0, 527, 0, 0, 539, 0, 860, 0, - 872, 0, 870, 0, 0, 640, 641, 0, 0, 0, - 690, 691, 689, 697, 836, 618, 624, 617, 0, 739, - 0, 347, 613, 0, 0, 0, 555, 444, 438, 442, - 437, 540, 478, 477, 474, 473, 0, 468, 433, 434, - 445, 0, 0, 757, 0, 0, 898, 874, 0, 899, - 0, 895, 0, 910, 0, 0, 0, 0, 878, 19, - 344, 687, 686, 0, 685, 0, 362, 956, 190, 951, - 0, 0, 54, 0, 0, 0, 0, 0, 0, 369, - 0, 644, 0, 0, 80, 79, 0, 483, 0, 0, - 0, 0, 0, 548, 0, 0, 0, 0, 0, 810, - 0, 0, 0, 0, 0, 856, 507, 506, 459, 0, - 0, 935, 936, 448, 454, 0, 457, 0, 481, 0, - 0, 0, 0, 0, 785, 851, 0, 842, 535, 530, - 0, 0, 526, 0, 863, 0, 802, 873, 871, 0, - 544, 626, 0, 622, 621, 620, 350, 612, 611, 628, - 476, 0, 466, 465, 598, 0, 771, 756, 0, 0, - 0, 760, 0, 876, 0, 903, 0, 918, 919, 912, - 882, 884, 924, 365, 364, 955, 0, 0, 62, 56, - 0, 64, 26, 23, 0, 0, 320, 0, 226, 0, - 101, 0, 77, 765, 128, 129, 0, 0, 0, 768, - 198, 199, 0, 0, 0, 0, 172, 181, 173, 175, - 0, 0, 0, 0, 814, 0, 819, 820, 0, 0, - 458, 460, 461, 455, 449, 453, 0, 512, 0, 480, - 491, 447, 524, 522, 0, 847, 0, 0, 531, 0, - 0, 639, 631, 0, 475, 0, 0, 752, 761, 875, - 0, 0, 0, 896, 0, 0, 0, 943, 0, 0, - 0, 69, 70, 73, 74, 0, 335, 326, 325, 0, - 645, 222, 97, 0, 754, 769, 184, 0, 196, 0, - 0, 0, 803, 865, 0, 0, 0, 821, 784, 496, - 493, 791, 0, 797, 0, 0, 789, 0, 794, 849, - 534, 533, 0, 0, 629, 0, 0, 877, 900, 0, - 0, 0, 914, 0, 925, 0, 75, 67, 0, 0, - 0, 321, 0, 0, 0, 0, 0, 185, 0, 176, - 174, 858, 811, 0, 0, 816, 0, 0, 786, 790, - 0, 795, 0, 861, 632, 0, 763, 0, 904, 921, - 922, 915, 885, 55, 0, 71, 72, 0, 0, 0, - 0, 0, 0, 0, 770, 183, 0, 195, 0, 0, - 822, 796, 0, 692, 850, 0, 772, 0, 0, 0, - 76, 0, 0, 336, 0, 322, 0, 330, 386, 385, - 0, 383, 674, 0, 646, 0, 675, 223, 98, 186, - 859, 806, 0, 862, 901, 0, 916, 0, 0, 0, - 0, 0, 0, 0, 0, 676, 0, 0, 0, 0, - 905, 29, 24, 337, 0, 0, 331, 384, 0, 0, - 0, 102, 99, 693, 0, 0, 0, 0, 323, 682, - 0, 683, 680, 0, 678, 95, 0, 94, 0, 0, - 83, 85, 86, 87, 88, 89, 90, 91, 92, 93, - 156, 0, 0, 239, 231, 232, 233, 234, 235, 236, - 237, 238, 0, 0, 229, 0, 0, 0, 902, 0, - 338, 334, 0, 0, 0, 647, 84, 0, 282, 277, - 281, 0, 224, 230, 116, 108, 109, 110, 111, 112, - 113, 114, 115, 117, 0, 0, 106, 100, 908, 906, - 681, 679, 0, 0, 0, 0, 0, 0, 0, 290, - 0, 0, 240, 0, 0, 248, 0, 167, 157, 166, - 0, 103, 107, 0, 0, 276, 0, 0, 275, 0, - 161, 0, 0, 356, 0, 354, 0, 0, 201, 0, - 0, 0, 0, 0, 648, 225, 118, 0, 353, 0, - 0, 0, 0, 132, 0, 0, 0, 0, 0, 0, - 158, 0, 0, 205, 0, 357, 0, 243, 242, 241, - 0, 0, 294, 0, 273, 134, 0, 271, 0, 0, - 0, 136, 0, 358, 0, 0, 202, 0, 0, 0, - 355, 246, 127, 125, 0, 0, 298, 0, 0, 0, - 0, 0, 162, 0, 279, 0, 0, 0, 0, 140, - 0, 0, 0, 0, 359, 360, 0, 0, 0, 0, - 0, 122, 313, 0, 295, 0, 0, 307, 0, 0, - 0, 302, 0, 152, 0, 0, 0, 0, 147, 0, - 0, 291, 0, 137, 0, 131, 141, 159, 165, 213, - 0, 203, 0, 0, 0, 0, 126, 0, 119, 123, - 0, 0, 0, 309, 0, 310, 299, 0, 0, 293, - 303, 274, 0, 0, 133, 148, 272, 0, 289, 0, - 280, 284, 143, 0, 0, 0, 210, 212, 206, 247, - 124, 314, 316, 296, 0, 0, 308, 305, 151, 149, - 163, 0, 0, 0, 160, 214, 216, 204, 0, 0, - 0, 307, 0, 285, 287, 144, 0, 0, 207, 318, - 319, 315, 317, 306, 164, 0, 0, 220, 219, 218, - 215, 217, 0, 0, 0, 208, 286, 288, + 0, 305, 636, 0, 640, 425, 0, 473, 0, 524, + 0, 535, 164, 185, 0, 0, 154, 0, 0, 0, + 165, 528, 0, 845, 795, 0, 806, 793, 0, 797, + 0, 0, 0, 820, 0, 0, 0, 486, 0, 502, + 504, 0, 0, 442, 0, 0, 438, 0, 0, 465, + 0, 506, 480, 0, 140, 507, 138, 139, 509, 0, + 523, 0, 836, 0, 829, 0, 833, 515, 0, 0, + 0, 353, 0, 513, 0, 0, 525, 0, 848, 0, + 860, 0, 858, 0, 0, 626, 627, 0, 0, 0, + 676, 677, 675, 683, 824, 604, 610, 603, 0, 725, + 0, 333, 599, 0, 0, 0, 541, 430, 424, 428, + 423, 526, 464, 463, 460, 459, 0, 454, 419, 420, + 431, 0, 0, 743, 0, 0, 886, 862, 0, 887, + 0, 883, 0, 898, 0, 0, 0, 0, 866, 19, + 330, 673, 672, 0, 671, 0, 348, 944, 175, 939, + 0, 0, 54, 0, 0, 0, 0, 0, 0, 355, + 0, 630, 0, 0, 80, 79, 0, 469, 0, 0, + 0, 0, 0, 534, 0, 0, 0, 0, 0, 798, + 0, 0, 0, 0, 0, 844, 493, 492, 445, 0, + 0, 923, 924, 434, 440, 0, 443, 0, 467, 0, + 0, 0, 0, 0, 773, 839, 0, 830, 521, 516, + 0, 0, 512, 0, 851, 0, 790, 861, 859, 0, + 530, 612, 0, 608, 607, 606, 336, 598, 597, 614, + 462, 0, 452, 451, 584, 0, 759, 742, 0, 0, + 0, 748, 0, 864, 0, 891, 0, 906, 907, 900, + 870, 872, 912, 351, 350, 943, 0, 0, 62, 56, + 0, 64, 26, 23, 0, 0, 0, 211, 0, 102, + 0, 77, 753, 113, 114, 0, 0, 0, 756, 183, + 184, 0, 0, 0, 0, 157, 166, 158, 160, 0, + 0, 0, 0, 802, 0, 807, 808, 0, 0, 444, + 446, 447, 441, 435, 439, 0, 498, 0, 466, 477, + 433, 510, 508, 0, 835, 0, 0, 517, 0, 0, + 625, 617, 0, 461, 0, 0, 738, 749, 863, 0, + 0, 0, 884, 0, 0, 0, 931, 0, 0, 0, + 69, 70, 73, 74, 0, 321, 0, 306, 631, 207, + 97, 0, 740, 757, 169, 0, 181, 0, 0, 0, + 791, 853, 0, 0, 0, 0, 809, 772, 482, 479, + 779, 0, 785, 0, 0, 777, 0, 782, 837, 520, + 519, 0, 0, 615, 0, 0, 865, 888, 0, 0, + 0, 902, 0, 913, 0, 75, 67, 0, 0, 0, + 312, 311, 0, 0, 0, 0, 0, 0, 170, 0, + 161, 159, 846, 799, 0, 0, 804, 0, 0, 774, + 778, 0, 783, 0, 849, 618, 0, 751, 0, 892, + 909, 910, 903, 873, 55, 0, 71, 72, 0, 0, + 307, 0, 0, 0, 0, 758, 168, 0, 180, 0, + 0, 810, 784, 0, 678, 838, 0, 760, 0, 0, + 0, 76, 0, 0, 322, 0, 372, 371, 0, 369, + 660, 0, 632, 0, 661, 208, 98, 171, 847, 794, + 0, 850, 889, 0, 904, 0, 0, 0, 308, 0, + 316, 0, 0, 0, 662, 0, 0, 0, 0, 893, + 29, 24, 323, 0, 0, 0, 370, 0, 0, 0, + 99, 679, 0, 0, 0, 0, 0, 317, 668, 0, + 669, 666, 0, 664, 95, 0, 94, 0, 0, 83, + 85, 86, 87, 88, 89, 90, 91, 92, 93, 141, + 0, 0, 224, 216, 217, 218, 219, 220, 221, 222, + 223, 0, 0, 214, 0, 0, 890, 0, 324, 0, + 309, 0, 0, 0, 633, 84, 0, 267, 262, 266, + 0, 209, 215, 0, 896, 894, 320, 667, 665, 0, + 0, 0, 0, 0, 0, 0, 275, 0, 0, 225, + 0, 0, 233, 0, 152, 142, 151, 0, 100, 0, + 0, 261, 0, 0, 260, 0, 146, 0, 0, 342, + 0, 340, 0, 0, 186, 0, 0, 0, 0, 0, + 634, 210, 0, 103, 0, 339, 0, 0, 0, 0, + 117, 0, 0, 0, 0, 0, 0, 143, 0, 0, + 190, 0, 343, 0, 228, 227, 226, 0, 101, 0, + 279, 0, 258, 119, 0, 256, 0, 0, 0, 121, + 0, 344, 0, 0, 187, 0, 0, 0, 341, 231, + 112, 110, 0, 0, 283, 0, 0, 0, 0, 0, + 147, 0, 264, 0, 0, 0, 0, 125, 0, 0, + 0, 0, 345, 346, 0, 0, 0, 0, 0, 107, + 298, 0, 280, 0, 0, 292, 0, 0, 0, 287, + 0, 137, 0, 0, 0, 0, 132, 0, 0, 276, + 0, 122, 0, 116, 126, 144, 150, 198, 0, 188, + 0, 0, 0, 0, 111, 0, 104, 108, 0, 0, + 0, 294, 0, 295, 284, 0, 0, 278, 288, 259, + 0, 0, 118, 133, 257, 0, 274, 0, 265, 269, + 128, 0, 0, 0, 195, 197, 191, 232, 109, 299, + 301, 281, 0, 0, 293, 290, 136, 134, 148, 0, + 0, 0, 145, 199, 201, 189, 0, 0, 0, 292, + 0, 270, 272, 129, 0, 0, 192, 303, 304, 300, + 302, 291, 149, 0, 0, 205, 204, 203, 200, 202, + 0, 0, 0, 193, 271, 273, }; protected static readonly short [] yyDgoto = { 7, 8, 50, 9, 51, 10, 11, 52, 235, 685, 429, 12, 13, 53, 22, 23, 24, 321, 195, 238, 670, - 828, 1016, 1133, 1480, 825, 239, 240, 241, 242, 243, + 828, 1015, 1134, 1468, 825, 239, 240, 241, 242, 243, 244, 245, 246, 663, 444, 664, 665, 928, 666, 667, - 932, 826, 1011, 1012, 1013, 269, 587, 1105, 837, 1199, - 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, - 1210, 463, 674, 1296, 942, 1112, 1075, 1145, 1183, 1168, - 1227, 1255, 1226, 1256, 1257, 1140, 1355, 1332, 1380, 1381, - 1382, 944, 1378, 945, 728, 1272, 1343, 1319, 1368, 512, - 1361, 1337, 1397, 907, 1366, 1369, 1370, 1464, 1398, 1399, - 1395, 1211, 1279, 1238, 1297, 686, 1345, 1444, 1316, 1401, - 1473, 464, 270, 687, 688, 689, 690, 691, 650, 568, - 1117, 651, 652, 843, 1299, 1323, 1412, 1373, 1446, 1300, - 1348, 1469, 1493, 1413, 1414, 1491, 1477, 1478, 940, 1074, - 1167, 1223, 1281, 1224, 1225, 1273, 1330, 1303, 1274, 323, - 226, 1377, 1276, 1362, 1359, 1212, 1240, 1293, 1441, 1403, - 1125, 1442, 588, 1486, 1487, 1292, 1358, 1334, 1390, 1385, - 1356, 1422, 1427, 1388, 1391, 1392, 1472, 1428, 1386, 1387, - 1482, 1470, 1471, 937, 1020, 1136, 1110, 1161, 1137, 1138, - 1175, 1071, 1159, 1187, 532, 196, 112, 431, 198, 562, - 439, 227, 1311, 648, 649, 814, 830, 324, 406, 530, - 303, 1141, 1142, 46, 114, 304, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, - 130, 131, 132, 133, 134, 135, 136, 255, 791, 981, - 508, 715, 864, 716, 717, 974, 137, 201, 721, 589, - 590, 591, 592, 785, 472, 473, 298, 979, 723, 407, - 300, 495, 496, 497, 498, 501, 730, 310, 745, 746, - 880, 266, 478, 758, 267, 477, 138, 139, 140, 141, - 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, - 152, 153, 154, 571, 572, 573, 767, 768, 896, 769, - 155, 558, 759, 353, 994, 546, 1054, 156, 490, 938, - 1073, 1165, 1277, 465, 1146, 1147, 1194, 1195, 815, 548, - 335, 763, 1153, 549, 550, 271, 272, 273, 159, 160, - 161, 274, 275, 276, 277, 278, 279, 280, 281, 282, - 283, 284, 285, 173, 286, 559, 174, 175, 317, 796, - 627, 910, 840, 681, 948, 908, 911, 912, 949, 950, - 287, 176, 177, 178, 1045, 985, 1046, 1047, 1048, 1091, - 1049, 179, 180, 181, 182, 698, 483, 699, 966, 1084, - 700, 964, 701, 1086, 1087, 183, 184, 185, 186, 187, - 188, 305, 521, 522, 987, 1093, 313, 963, 849, 1119, - 886, 1126, 189, 417, 190, 418, 913, 1001, 419, 639, - 809, 806, 807, 1006, 420, 421, 422, 423, 424, 425, - 917, 629, 915, 1098, 1170, 1229, 1003, 1129, 1186, 804, - 635, 805, 1062, 1005, 1063, 1130, 1007, 17, 19, 47, - 48, 230, 653, 822, 440, 654, 655, + 932, 826, 1010, 1011, 1012, 269, 587, 1106, 837, 1198, + 1199, 1200, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, + 1209, 463, 674, 1282, 941, 1113, 1076, 1143, 1167, 1225, + 1293, 1138, 1343, 1320, 1368, 1369, 1370, 943, 1366, 944, + 728, 1259, 1331, 1306, 1356, 512, 1349, 1325, 1385, 907, + 1354, 1357, 1358, 1452, 1386, 1387, 1383, 1210, 1266, 1237, + 1283, 686, 1333, 1432, 1303, 1389, 1461, 464, 270, 687, + 688, 689, 690, 691, 650, 568, 1118, 651, 652, 843, + 1285, 1310, 1400, 1361, 1434, 1286, 1336, 1457, 1481, 1401, + 1402, 1479, 1465, 1466, 939, 1075, 1166, 1222, 1268, 1223, + 1224, 1260, 1317, 1289, 1261, 323, 226, 1365, 1263, 1350, + 1347, 1211, 1239, 1279, 1429, 1391, 1126, 1430, 588, 1474, + 1475, 1278, 1346, 1322, 1378, 1373, 1344, 1410, 1415, 1376, + 1379, 1380, 1460, 1416, 1374, 1375, 1470, 1458, 1459, 831, + 1018, 1073, 1159, 1136, 1175, 1160, 1161, 1186, 1070, 1157, + 1185, 532, 196, 112, 431, 198, 562, 439, 227, 1298, + 648, 649, 814, 830, 324, 406, 530, 303, 1139, 1140, + 46, 114, 304, 116, 117, 118, 119, 120, 121, 122, + 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, + 133, 134, 135, 136, 255, 791, 980, 508, 715, 864, + 716, 717, 973, 137, 201, 721, 589, 590, 591, 592, + 785, 472, 473, 298, 978, 723, 407, 300, 495, 496, + 497, 498, 501, 730, 310, 745, 746, 880, 266, 478, + 758, 267, 477, 138, 139, 140, 141, 142, 143, 144, + 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, + 571, 572, 573, 767, 768, 896, 769, 155, 558, 759, + 353, 993, 546, 1053, 156, 490, 937, 1074, 1164, 1264, + 465, 1144, 1145, 1193, 1194, 815, 548, 335, 763, 1151, + 549, 550, 271, 272, 273, 159, 160, 161, 274, 275, + 276, 277, 278, 279, 280, 281, 282, 283, 284, 285, + 173, 286, 559, 174, 175, 317, 796, 627, 910, 840, + 681, 947, 908, 911, 1034, 912, 948, 949, 287, 176, + 177, 178, 1044, 984, 1045, 1046, 1047, 1092, 1048, 179, + 180, 181, 182, 698, 483, 699, 965, 1085, 700, 963, + 701, 1087, 1088, 183, 184, 185, 186, 187, 188, 305, + 521, 522, 986, 1094, 313, 962, 849, 1120, 886, 1127, + 189, 417, 190, 418, 913, 1000, 419, 639, 809, 806, + 807, 1005, 420, 421, 422, 423, 424, 425, 917, 629, + 915, 1099, 1169, 1227, 1002, 1130, 1184, 804, 635, 805, + 1061, 1004, 1062, 1131, 1006, 17, 19, 47, 48, 230, + 653, 822, 440, 654, 655, }; - protected static readonly short [] yySindex = { -157, - 0, -201, -137, -18, 44,11653, 0, 248, 0, 0, - 44, -18, 0, 0, 104, 0, 6498, 44, 0, -196, - -237, 0, 0, 0, 0, 0, 0, 0, 0, 99, - 0, 223, 0, 0, 0, 1006, 0, 0, 0, 0, - 0, 0, 0, 0, 93, 0, 0, 544, 0, 0, - 248, 259, 44, 0, 258, 0, 87, 294, 353,11153, - 318, -29, 328, 6655, 0, -29, -29, -29, -175, -29, - -29, 587, 0,10172, -29, -29, 0,10172, 0, 388, - 0, 353, 0, -29, 330, -29, 0, 8204,11672, 390, - -29, -29, -162,10976, 0,10172, 0,10852,10852,10852, -10852,10852,10852,10852,10852, 0, -103, 0,11726, 0, - 0, 363, -260, 795, 302, 0, 0, 447, 0, 0, + protected static readonly short [] yySindex = { -185, + 0, -190, -128, -221, -14,11657, 0, -93, 0, 0, + -14, -221, 0, 0, -72, 0, 6676, -14, 0, -173, + -247, 0, 0, 0, 0, 0, 0, 0, 0, 46, + 0, 112, 0, 0, 0, 5062, 0, 0, 0, 0, + 0, 0, 0, 0, 288, 0, 0, 335, 0, 0, + -93, 128, -14, 0, 5, 0, -36, 103, 129,11157, + 147, -272, 230, 6833, 0, -272, -272, -272, -166, -272, + -272, 374, 0,10176, -272, -272, 0,10176, 0, 267, + 0, 129, 0, -272, 228, -272, 0, 7930, 8225, 329, + -272, -272, -219,10980, 0,10176, 0,10856,10856,10856, +10856,10856,10856,10856,10856, 0, 70, 0, 8382, 0, + 0, 394, 341, 252, -233, 0, 0, 409, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1069, 0, - 0, 685, 66, 498, 616, 597, 456, 462, 480, 505, - 137, 548, 0, 0, 0, 0, 0, 0, 3318, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 893, 0, + 0, 708, 168, 373, 475, 556, 447, 460, 480, 445, + -74, 498, 0, 0, 0, 0, 0, 0, 3428, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 571, 600, -285, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -105, 95, - 259, 0, 401, 606, 627, 0, 615, 0, 0, 0, - 0,11726,11726, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 491, 570, 75, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, -208, -174, + 128, 0, 391, 574, 589, 0, 564, 0, 0, 0, + 0, 8382, 8382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 674, 633, 0, 646, 0, - -249, 0, 0, 0, 259,12475, 259, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 830, 688,10308, - 0, 0, 0, 0,10172, -29, -29, 834, 512, 795, - 0, 698, 0,11726, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 624, 583, 0, 586, 0, + -249, 0, 0, 0, 128,12382, 128, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 775, 630,10312, + 0, 0, 0, 0,10176, -272, -272, 781, 311, 252, + 0, 643, 0, 8382, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 801, 74,11153, 0,11726, -10172, 757, 776,10172,10172, 4520, 326, 109, 779,11743, - 264, 0, 782, 0, 822,11726,10172, 840, 516, -29, - 0,10172, 388, 9628, 0, 0, 330,10172, 330, -205, - 547, 803, 0, 600, 302, -1, 810,10172,10172,10172, - 328, 892, 0, 0, 6812, -56, 0, 0, 0, 0, - 0, 0, 0, 0, 870,10172, 0, 0, 0, 1324, - 0, 0,11582, -289, 860, 839, 0, -84, 0, 0, - 263, 0, 0, 842,10308, 9356, 0, 0,10852,10172, -10172,10172,10172,10172,10172,10172,10172,10172,10172,10172, -10852,10852,10852,11726,11726,10852,10852,10852,10852,10852, -10852,10852,10852,10852,10852,10852,10852,10852,10852,10852, -10852,10172, 0, 0, 0, 0, 600, 0, 0, 0, - 0,11797,11821, 849, 0, 0, 0, 0, 33, 856, - 0, 0, 0, 0, 0, 0, 0, 259, 259, 853, - 0, 867, 0, 839, 674, 674, 0, -86, 0, -206, - 674, 909, 0, -198,12475, 0, 0, 0, 0, -192, + 0, 0, 0, 0, 0, 725, 95,11157, 0, 8382, +10176, 697, 712,10176,10176, 4630, 604, -144, 717,11676, + 183, 0, 706, 0, 715, 8382,10176, 727, 561, -272, + 0,10176, 267, 9632, 0, 0, 228,10176, 228, -92, + 456, 710, 0, 570, -233, -83, 743,10176,10176,10176, + 230, 772, 0, 0, 6990, -258, 0, 0, 0, 0, + 0, 0, 0, 0, 734,10176, 0, 0, 0, 320, + 0, 0,11586, 235, 752, 755, 0, -126, 0, 0, + 240, 0, 0, 747,10312, 9360, 0, 0,10856,10176, +10176,10176,10176,10176,10176,10176,10176,10176,10176,10176, +10856,10856,10856, 8382, 8382,10856,10856,10856,10856,10856, +10856,10856,10856,10856,10856,10856,10856,10856,10856,10856, +10856,10176, 0, 0, 0, 0, 570, 0, 0, 0, + 0,11730,11747, 758, 0, 0, 0, 0, -252, 617, + 0, 0, 0, 0, 0, 0, 0, 128, 128, 761, + 0, 778, 0, 755, 624, 624, 0, -145, 0, 399, + 624, 764, 0, -192,12382, 0, 0, 0, 0, -171, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 235,12518, 0, 0, 0, 839, 419, 0, - 0, 561, 0, 886, 0, 920, 67, 388, -29, 0, - 0, 881, 7735, -147, 0, 940, 0, 0, 0, 945, - 946, 0, 417, 0, 951, 0, 947, 0, 0, 0, - 680, 0, 7871, 681,10172, 779, 9356, 0, 7283, 0, - 330, 0, 0, 0, 948, 950, 0, 0, 353, 388, - 267, 0, 4201, 952, 0, 953, 908, 0, 956, 0, -10172, 0, 0, 1035, 0, 0, 0,10172, 1036, 972, - 0, 975, 976, 0, 0,11582, 0, -288, 6812, 0, - 0, 0, 0, 0, 0, 0, 974, 388, 6812, 0, - 0, -286, 0, 0, 0, 330, -289, 935,11871, 0, - 980, 0, 987,10852, 0, 275, 0, 349, 0, 839, - 793,10172,10172, 994, 1110, 0, 0, -36, 993, 0, - 0, 0, 685, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 685, - 685, 66, 66, 498, 498, 498, 498, 616, 616, 597, - 456, 462, 480, 505, 0, 995, -186, 0,10172, 80, - 955, 113, 957, 996,10172, 0, 0, 0, 1012, 0, - 200, 839, 0, 0, 0, 0, 517, 242, 0,11871, - -206, 0, 997, 1000, 0, 0, 0, 0, 0, 0, - -289, 606, 0, 1001, 1005, 0, 0, 0, 0, 1007, -11895, 963, 0, 361, 0, 0, 542, 0,10308, 0, - 1016, 0, 0, 0, 711, 1010, 0, 1041, 1042, 1044, - 0, 0,10172, 0, 0, 1002, 0, 0, 1043, 0, - 1049,10172, 1130, 0, 6655, 6655, 8030, 0, 4520, 0, - 0, 9764, 236, 0, -281, 58, 0, 999, 1003, 0, - -185, 0, 0, 1053, 0, 0, 0, 0, 0, 1055, - 0, 1063, 0, 4360, 0, 388, 0, 0, 330, 428, - 573, 0, 1013, 0, 1060, 1061, 0, 6655, 0, 6655, - 0,10172, 0,10172,11726, 0, 0, 388, 388, 1066, - 0, 0, 0, 0, 0, 0, 0, 0, 8187, 0, -11726, 0, 0, 1015,11582, 1092, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 9220, 0, 0, 0, - 0, 9492,10172, 0, 7440, 1065, 0, 0, 1146, 0, - 1147, 0, 667, 0, 1068,10172,10172, 1025, 0, 0, - 0, 0, 0, 1028, 0, -86, 0, 0, 0, 0, - -206, -206, 0, 853, 1075, 1078, 1033, 1085, 963, 0, - 1079, 0, 1197, 1199, 0, 0,10172, 0, 9900, 1082, - 711,11871,11726, 0, 128, 1203, 1205, 1090, 1086, 0, -10172,10172, 1094,10172, 1188, 0, 0, 0, 0, 31, -10036, 0, 0, 0, 0, 7576, 0, 1225, 0, 600, -10172, 1115, 8030, 1116, 0, 0, 1067, 0, 0, 0, - 1072, 556, 0, 1073, 0, 1086, 0, 0, 0, 1111, - 0, 0, 1143, 0, 0, 0, 0, 0, 0, 0, - 0, 637, 0, 0, 0,11743, 0, 0, 1074, 1117, - 1065, 0,10172, 0,10172, 0,10172, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1125, 853, 0, 0, -10444, 0, 0, 0, 1136, 7300, 0, 963, 0, 963, - 0, 963, 0, 0, 0, 0, 1091, 1132, 1082, 0, - 0, 0, -188, -181, 1113, 1137, 0, 0, 0, 0, - 1134, 8030, 1065, -186, 0, 1138, 0, 0, 1140, 6655, - 0, 0, 0, 0, 0, 0, 1145, 0, 779, 0, - 0, 0, 0, 0, -203, 0, 1141, 556, 0, 1095, - 1065, 0, 0, 388, 0, 1096, 1142, 0, 0, 0, -10172, 1180,10172, 0,10172, 1179, 461, 0, 1005, 238, - 762, 0, 0, 0, 0, -18, 0, 0, 0, 1164, - 0, 0, 0, 1155, 0, 0, 0, 481, 0, 1156, - 1285, 1287, 0, 0, 1181, 1065,10172, 0, 0, 0, - 0, 0,10172, 0, 1184, -191, 0, -191, 0, 0, - 0, 0, 1182, 388, 0,10172, 7440, 0, 0, 1208, - 702, 1183, 0,10172, 0, 1186, 0, 0,10444, 44, - 67, 0, 1185, 1185, 1185, 9900, 1189, 0,10172, 0, - 0, 0, 0, 1192, 1049, 0, 6655, 1190, 0, 0, - 6812, 0, 1191, 0, 0, 1202, 0,10172, 0, 0, - 0, 0, 0, 0,10172, 0, 0, 259, 1195, 259, - 7457, 71, 71, 71, 0, 0,10172, 0, 6655, 6655, - 0, 0, 6812, 0, 0, 6655, 0, 1213,10172,10172, - 0, 259, 1201, 0, 1157, 0, 1204, 0, 0, 0, - 1207, 0, 0, 1158, 0, 1234, 0, 0, 0, 0, - 0, 0, 6812, 0, 0, 1235, 0, 1206, 71, 0, - 1216, 259, 7457, 1210, 1219, 0, 1220, 1221, 1224,10172, - 0, 0, 0, 0, 1212, 1206, 0, 0,11232, -65, - 259, 0, 0, 0, 1239,10172, 1222,10172, 0, 0, - 1226, 0, 0, 1228, 0, 0,12518, 0, 1232, -65, + 0, 0, -168, 9092, 0, 0, 0, 755, 111, 0, + 0, 631, 0, 774, 0, 832, -161, 267, -272, 0, + 0, 797, 7913, -202, 0, 840, 0, 0, 0, 845, + 848, 0, 241, 0, 853, 0, 849, 0, 0, 0, + 654, 0, 8049, 662,10176, 717, 9360, 0, 7461, 0, + 228, 0, 0, 0, 855, 857, 0, 0, 129, 267, + 463, 0, 1429, 858, 0, 859, 814, 0, 861, 0, +10176, 0, 0, 940, 0, 0, 0,10176, 943, 865, + 0, 868, 869, 0, 0,11586, 0, -261, 6990, 0, + 0, 0, 0, 0, 0, 0, 872, 267, 6990, 0, + 0, -254, 0, 0, 0, 228, 235, 831,11801, 0, + 877, 0, 880,10856, 0, 355, 0, 366, 0, 755, + 663,10176,10176, 882, 998, 0, 0, 38, 881, 0, + 0, 0, 708, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 708, + 708, 168, 168, 373, 373, 373, 373, 475, 475, 556, + 447, 460, 480, 445, 0, 884, -191, 0,10176, -48, + 839, 20, 842, 883,10176, 0, 0, 0, 906, 0, + 545, 755, 0, 0, 0, 0, 520, 247, 0,11801, + 399, 0, 891, 892, 0, 0, 0, 0, 0, 0, + 235, 574, 0, 895, 897, 0, 0, 0, 0, 894, +11825, 0, 0, 68, 0, 0, 204, 0,10312, 0, + 896, 0, 0, 0, 542, 903, 0, 907, 909, 910, + 0, 0,10176, 0, 0, 862, 0, 0, 911, 0, + 912,10176, 995, 0, 6833, 6833, 8208, 0, 4630, 0, + 0, 9768, 189, 0, -61, -138, 0, 863, 867, 0, + -90, 0, 0, 919, 0, 0, 0, 0, 0, 932, + 0, 941, 0, 4152, 0, 267, 0, 0, 228, 370, + 560, 0, 889, 0, 951, 953, 0, 6833, 0, 6833, + 0,10176, 0,10176, 8382, 0, 0, 267, 267, 957, + 0, 0, 0, 0, 0, 0, 0, 0, 8365, 0, + 8382, 0, 0, 913,11586, 987, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 9224, 0, 0, 0, + 0, 9496,10176, 0, 7618, 958, 0, 0, 1039, 0, + 1041, 0, 744, 0, 969,10176,10176, 926, 0, 0, + 0, 0, 0, 927, 0, -145, 0, 0, 0, 0, + 399, 399, 0, 761, 976, 977, 929, 983, 935, 0, + 935, 0, 1099, 1101, 0, 0,10176, 0, 9904, 990, + 542,11801, 8382, 0, 332, 1105, 1109, 997, 992, 0, +10176,10176, 999,10176, 1095, 0, 0, 0, 0, 85, +10040, 0, 0, 0, 0, 7754, 0, 1123, 0, 570, +10176, 1014, 8208, 1017, 0, 0, 964, 0, 0, 0, + 970, 239, 0, 971, 0, 992, 0, 0, 0, 1015, + 0, 0, 1047, 0, 0, 0, 0, 0, 0, 0, + 0, 421, 0, 0, 0,11676, 0, 0, 973, 1016, + 958, 0,10176, 0,10176, 0,10176, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1024, 761, 0, 0, +10448, 0, 0, 0, 1025, 1023, 935, 0, 935, 0, + 935, 0, 0, 0, 0, 982, 1026, 990, 0, 0, + 0, -167, -156, 1027, 1029, 0, 0, 0, 0, 1028, + 8208, 958, -191, 0, 1032, 0, 0, 1033, 6833, 0, + 0, 0, 0, 0, 0, 1040, 0, 717, 0, 0, + 0, 0, 0, -213, 0, 1037, 239, 0, 991, 958, + 0, 0, 267, 0, 988, 1034, 0, 0, 0,10176, + 1067,10176, 0,10176, 1065, 225, 0, 897, 219, 557, + 0, 0, 0, 0, -221, 0, 4311, 0, 0, 0, + 0, 1036, 0, 0, 0, 493, 0, 1038, 1162, 1164, + 0, 0, 958, 1049, 958,10176, 0, 0, 0, 0, + 0,10176, 0, 1055, -224, 0, -224, 0, 0, 0, + 0, 1052, 267, 0,10176, 7618, 0, 0, 1078, 782, + 1053, 0,10176, 0, 1056, 0, 0,10448, -14, -161, + 0, 0, 1061, 1054, 1054, 1054, 9904, 1060, 0,10176, + 0, 0, 0, 0, 1059, 912, 0, 6833, 1057, 0, + 0, 6990, 0, 1066, 0, 0, 1064, 0,10176, 0, + 0, 0, 0, 0, 0,10176, 0, 0, 128, 1068, + 0, 4470, -153, -153, -153, 0, 0,10176, 0, 6833, + 6833, 0, 0, 6990, 0, 0, 6833, 0, 1088,10176, +10176, 0, 128, 1069, 0, 128, 0, 0, 1070, 0, + 0, 1020, 0, 1100, 0, 0, 0, 0, 0, 0, + 6990, 0, 0, 1093, 0, 1071, -153, 1030, 0, 1075, + 0, 4470, 1076, 1083, 0, 1089, 1092, 1074,10176, 0, + 0, 0, 0, 0, 1087, 128, 0,11236, -75, 128, + 0, 0, 1104,10176, 1086, 1062, 1071, 0, 0, 1090, + 0, 0, 1096, 0, 0, 9092, 0, 1120, -75, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, -262,12518, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1238, 259, 0, 259, 1206, 1178, 0, 1239, - 0, 0, 1236,11232,11398, 0, 0, -255, 0, 0, - 0,11430, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1242, 259, 0, 0, 0, 0, - 0, 0,11726,11726, 225,11743, 316, 330, 1270, 0, - -289, 640, 0, 1306, 0, 0, 1206, 0, 0, 0, - 1206, 0, 0, 1198, 1200, 0,11726, -164, 0,11726, - 0, 1209, 1244, 0, -289, 0, 1246, 9112, 0, 1251, - 1211, -46, 351, 1006, 0, 0, 0, -289, 0, 1254, - 1214, 1252, 1237, 0, 1255, 1200, 1260, 67, 1241, 1261, - 0, 1262, 1258, 0, 839, 0, 678, 0, 0, 0, - 1264, -184, 0, 1266, 0, 0, 1267, 0, 1268, 1271, - 1273, 0, 1274, 0, 67, 67, 0, 67, 1276, 1277, - 0, 0, 0, 0, 1278, 62, 0, 1282, 67, 1401, - 1286, 67, 0, -255, 0, 8030, 1245, 1283, 1274, 0, - 1290, 1292, 77, 1295, 0, 0, 67, 9900, 1248, 1291, - 1278, 0, 0,12518, 0, 259, 259, 0, 1250, 1293, - 1282, 0, 1298, 0,10172, 1257, 1296, 1286, 0, 1301, - 67, 0, -77, 0, 1299, 0, 0, 0, 0, 0, -12518, 0, 77, 77, 1309, 1305, 0, -184, 0, 0, - 219, 1311,12518, 0,12518, 0, 0, 8030, 1300, 0, - 0, 0, 1312, 1267, 0, 0, 0, 1316, 0, 20, - 0, 0, 0, 71, 848, 1321, 0, 0, 0, 0, - 0, 0, 0, 0, 1375, 1428, 0, 0, 0, 0, - 0, 1323, 1325, 8030, 0, 0, 0, 0, 77, 412, - 412, 0, 71, 0, 0, 0, 110, 110, 0, 0, - 0, 0, 0, 0, 0, 9356, 9356, 0, 0, 0, - 0, 0, 1327, 1326, 1331, 0, 0, 0, + -248, 9092, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 1121, 128, 0, -75, 1045, 0, 1104, 0,10176, + 0, 1097,11236,11402, 0, 0, -244, 0, 0, 0, +11434, 0, 0, 1122, 0, 0, 0, 0, 0, 8382, + 8382, -122,11676, -109, 228, 1154, 0, 235, 9160, 0, + 1188, 0, 0, 1071, 0, 0, 0, 1071, 0, 1081, + 1082, 0, 8382, -152, 0, 8382, 0, 1108, 1125, 0, + 235, 0, 1130, 682, 0, 1135, 1112, 1, 354, 5062, + 0, 0, 1071, 0, 235, 0, 1127, 1113, 1134, 1139, + 0, 1156, 1082, 1163, -161, 1152, 1165, 0, 1168, 1173, + 0, 755, 0, 736, 0, 0, 0, 1170, 0, -178, + 0, 1161, 0, 0, 1174, 0, 1175, 1176, 1178, 0, + 1171, 0, -161, -161, 0, -161, 1181, 1182, 0, 0, + 0, 0, 1177, -59, 0, 1183, -161, 1300, 1184, -161, + 0, -244, 0, 8208, 1141, 1185, 1171, 0, 1190, 1191, + 27, 1194, 0, 0, -161, 9904, 1142, 1189, 1177, 0, + 0, 9092, 0, 128, 128, 0, 1148, 1192, 1183, 0, + 1197, 0,10176, 1155, 1196, 1184, 0, 1202, -161, 0, + -107, 0, 1195, 0, 0, 0, 0, 0, 9092, 0, + 27, 27, 1220, 1217, 0, -178, 0, 0, -148, 1224, + 9092, 0, 9092, 0, 0, 8208, 1212, 0, 0, 0, + 1225, 1174, 0, 0, 0, 1222, 0, 83, 0, 0, + 0, -153, 834, 1228, 0, 0, 0, 0, 0, 0, + 0, 0, 1282, 1335, 0, 0, 0, 0, 0, 1229, + 1233, 8208, 0, 0, 0, 0, 27, 484, 484, 0, + -153, 0, 0, 0, -80, -80, 0, 0, 0, 0, + 0, 0, 0, 9360, 9360, 0, 0, 0, 0, 0, + 1240, 1237, 1238, 0, 0, 0, }; - protected static readonly short [] yyRindex = { 2851, - 0, 0, 6969, 2851, 0, 0, 0, 1704, 0, 0, - 3004, 2782, 0, 0, 0, 0, 0, 3004, 0, 0, - 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, + protected static readonly short [] yyRindex = { 2961, + 0, 0, 7147, 2961, 0, 0, 0, 1611, 0, 0, + 3114, 2892, 0, 0, 0, 0, 0, 3114, 0, 0, + 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1613, 0, 0, 1613, 0, 0, + 1611, 3157, 3008, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 1247, 0, 0, 0, 0, 0, 0, 0, + 0,11875, 0, 1239, 0, 0, 0, 1239, 0, 0, + 0, 0, 0, 0, -35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1708, 0, 0, 1708, 0, 0, - 1704, 3047, 2898, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 1342, 0, 0, 0, 0, 0, 0, 0, - 0,11949, 0, 1334, 0, 0, 0, 1334, 0, 0, - 0, 0, 0, 0, 206, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 3740, 0, 0, 0, + 0, 0, 171, 4628, 3581, 0, 0, 4469, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 3630, 0, 0, 0, - 0, 0, 313, 4518, 3789, 0, 0, 4359, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 4784, 0, + 0, 4852, 5196, 5400, 5740, 5944, 6080, 6216, 6352, 6488, + 529, 966, 0, 0, 0, 0, 0, 0, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 4674, 0, - 0, 4742, 5086, 5290, 5630, 358, 5902, 6038, 6174, 6310, - -194, 293, 0, 0, 0, 0, 0, 0, 42, 0, + 0, 0, 0, 0, 1198, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 805, 805, + 3200, 0, 572, 1242, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1294, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 939, 939, - 3090, 0, 595, 1337, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1613, 47, 0, 0, 0, + 0, 0, 0, 0, 3243, 432, 3286, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1708, 228, 0, 0, 0, - 0, 0, 0, 0, 3133, 402, 3176, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 3515, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3405, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1262, 0, 0, 0, 0, + 3515, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 2149, 0, 1273, 132, + 2279, 0, 0, 2426, 2279, 132, 0, 0, 0, 0, + 1247, 0, 0, 0, 4, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1239, 0, 0, 0, 0, + 0, 0, 1259, 2551, 0, 3515, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 106, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1350, 0, 0, 0, 0, - 3405, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 2039, 0, 1150, 692, - 2169, 0, 0, 2316, 2169, 692, 0, 0, 0, 0, - 1342, 0, 0, 0, 145, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1334, 0, 0, 0, 0, - 0, 0, 1349, 2441, 0, 3405, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 1532, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, + 0, 0, 0, 0, 0, 0, 0, 3349, 2716, 0, + 0, 0, 0, 1996, 1613, 1613, 0, -189, 0, 7478, + 1613, 1632, 0, 0, 135, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 1422, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 169, - 0, 0, 0, 0, 0, 0, 0, 3239, 2606, 0, - 0, 0, 0, 1886, 1708, 1708, 0, -122, 0, 7752, - 1708, 1722, 0, 0, 45, 0, 0, 0, 0, 0, + 0, 0, 296,11089, 0, 0, 0, 3515, 3899, 0, + 0, 0, 0, 0, 0, 0,11478, 0, 0, 0, + 0, 0, 1257, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 719, 785, 0, 0, 1266, 0, 0, 0, + 0, 0, 6, 0, 0, 3992, 1263, 0, 0, 0, + 184, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1700, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 364,11085, 0, 0, 0, 3405, 3948, 0, - 0, 0, 0, 0, 0, 0,11474, 0, 0, 0, - 0, 0, 1354, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 731, 818, 0, 0, 1357, 0, 0, 0, - 0, 0, 191, 0, 0, 3882, 1363, 0, 0, 0, - 124, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1590, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1259, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 0, 0, 8522, 0, 0, + 0, 0, 0, 0, 0, -181, 385, 0, 0, 0, + 1264, 0, 0, 0, 0, 3515, 0, 3515, 0, 4151, + 0, 0, 0, 90, 0, 0, 0, 0, 144, 0, + 0, 0, 4956, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 5024, + 5128, 5264, 5332, 5468, 5536, 5604, 5672, 5808, 5876, 6012, + 6148, 6284, 6420, 6544, 0, 0, 597, 0, 0, 132, + 0, 132, 0, 0, 0, 0, 0, 0, 1231, 0, + 0, 1996, 0, 0, 0, 0, 1219, 0, 0, 0, +11899, 0, 0, 641, 0, 0, 0, 0, 0, 0, + 519, 626, 0, 0, 1268, 0, 0, 0, 0, 1275, + 0, 0, 0, 0, 0, 0,10584, 0, 0, 0, + 733, 0, 0, 0,11953, 0, 0, 732, 746, 749, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1349, 0, 0, 201, 0, - 0, 0, 0, 0, 0, 0, 0, 8344, 0, 0, - 0, 0, 0, 0, 0, -197, 537, 0, 0, 0, - 1365, 0, 0, 0, 0, 3405, 0, 3405, 0, 4041, - 0, 0, 0, 127, 0, 0, 0, 0, -20, 0, - 0, 0, 4846, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 4914, - 5018, 5154, 5222, 5358, 5426, 5494, 5562, 5698, 5766, 5834, - 5970, 6106, 6242, 6366, 0, 0, 786, 0, 0, 692, - 0, 692, 0, 0, 0, 0, 0, 0, 988, 0, - 0, 1886, 0, 0, 0, 0, 1322, 0, 0, 0, -11966, 0, 0, 800, 0, 0, 0, 0, 0, 0, - 744, 664, 0, 0, 1374, 0, 0, 0, 0, 1378, - 0, 0, 0, 0, 0, 0,10580, 0, 0, 0, - 807, 0, 0, 0,12020, 0, 0, 808, 824, 833, + 1270, 0, 0, 0, 0, 0, 0, 0, 1285, 0, + 0, 0, 1124, 0, 0, 41, 0, 117, 3674, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1286, + 0, 0, 0, 0, 0, 0, 0, 0, -68, 595, + 650, 0, 0, 0, 0, 1278, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 8522, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1370, 0, 0, 0, 0, 0, 0, 0, 1380, 0, - 0, 0, 3471, 0, 0, 202, 0, 49, 3564, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1381, - 0, 0, 0, 0, 0, 0, 0, 0, 254, 804, - 658, 0, 0, 0, 0, 1379, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 8344, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 162, 0, 0, 0, 1288, 0, 0, 0, 0, + 0, 0, 458, 0, 677, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -189, 0, 0, 0, 0, +11953, 7635, 0, 1291, 0, 680, 0, 0, 0, 0, + 0, 0, 1248, 1258, 0, 0, 0, 0, 0, 1289, +11970, 0, 0, 0,11554, 0, 0, 0, 748, 0, + 1299, 0, 0, 0, 1867, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 3833, + 0, 4310, 1309, 0, 0, 0, 1306, 0, 0, 0, + 0, 595, 0, 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 251, 0, 0, 0, 1377, 0, 0, 0, 0, - 0, 0, 641, 0, 614, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -122, 0, 0, 0, 0, -12020, 8047, 0, 1384, 0, 805, 0, 0, 0, 0, - 1383, 0, 1338, 1341, 0, 0, 0, 0, 0, 1386, -12044, 0, 0, 0,11550, 0, 0, 0, 857, 0, - 1387, 0, 0, 0, 1757, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 3723, - 0, 4200, 1396, 0, 0, 0, 1393, 0, 0, 0, - 0, 804, 0, 0, 0, 857, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1303, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 821, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 751, 0, 0, 0, 0, 1313, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 1305, 0, 0, + 0, 0, 0, 790, 794, 0, 0, 0, 0, 0, + 0, 1310, 597, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 3992, 0, 0, + 0, 0, 0, 1315, 0, 0, 595, 0, 828, 1310, + 0, 0, 8522, 0, 614, 636, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 44, 0, 1268, 8572, 0, + 0, 0, 0, 0,12001, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 671, 0, 692, 0, 0, + 0, 0, 858, 0, 1288, 1312, 0, 0, 0, 0, + 0, 0, 0, 0, 1319, 0, 7304, 0, 0, 0, + 0, 0, 8522, 0, 0, 0, 0, 0, 0, 588, + 703, 0, 0, 0, 0, 0, 0, 0,12044,11478, + 0, 0, 0, -51, -51, -51, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 1316, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 871, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1391, 0, - 0, 0, 0, 0, 880, 884, 0, 0, 0, 0, - 0, 0, 1407, 786, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 3882, 0, - 0, 0, 0, 0, 1412, 0, 0, 804, 0, 932, - 1407, 0, 0, 8344, 0, 632, 670, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 176, 0, 1374, 8394, - 0, 0, 0, 0, 0,12092, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 770, 0, 775, - 0, 0, 0, 0, 0, 1377, 1409, 0, 0, 0, - 0, 0, 0, 0, 0, 1414, 0, 7126, 0, 0, - 0, 0, 0, 8344, 0, 0, 0, 0, 0, 0, - 679, 730, 0, 0, 0, 0, 0, 0, 0,12135, -11474, 0, 170, 170, 170, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 1411, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0,12113, 0, + 0, 0, 1323, 1323, 1323, 0, 0, 0, 0, 0, + 0, 0, 0, -205, 0, 0, 0, 0, 0, 0, + 0, 0,12156, 0, 0, 64, 0, 0, 109, 0, + 0, 0, 0, 540, 0, 0, 0, 0, 0, 0, + 1324, 0, 0, 0, 0, 3071, 1317, 0, 0, 1327, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0,12246, 0, -290, - 0, 1418, 1418, 1418, 0, 0, 0, 0, 0, 0, - 0, 0, -178, 0, 0, 0, 0, 0, 0, 0, - 0,12289, 0, 0, 0, 0, 1419, 0, 0, 0, - 216, 0, 0, 0, 0, 445, 0, 0, 0, 0, - 0, 0, 1420, 0, 0, 0, 0, 2961, 1410, -257, - 0, 65, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 2719, 0, 0, 0, 8548, - 8944, 0, 0, 0, 745, 0, 0, 0, 0, 0, - 0, 0, 0, -244, 0, 0,11256, 0, 0, 8647, + 0, 0, 0, 485, 0, 154, 0, 0, 8726, 8924, + 0, 0, 728, 0, 0, 0, 2829, 0, 0, 0, + 0, 0, 397, 0, 0,11260, 0, 0, 8825, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0,11324, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 9038, 0, 8746, 2719, 0, 0, 745, - 0, 0, 0, 0, 364, 0, 0, 0, 0, 0, - 0, 364, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 8845, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 4648, 457, 0, - 9080, 0, 0, 0, 9150, 0, 2719, 0, 0, 0, - 2719, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 866, 0, 1424, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 888, 0, 551, - 0, 0, 0, 0, 0, 0, 0,11474, 889, 0, - 0, 0, 0, 0, 1426, 0, 906, 0, 0, 0, - 0, 0, 0, 900, 0, 0, 0, 0, 0, 0, - 0, 0, 1437, 0,11474,11474, 0,11506, 0, 0, - 0, 0, 0, 0, 1460, 1390, 0, 1461,11474,10716, - 1463,11474, 0, 0, 0, 0, 0, 0, 1465, 0, - 0, 0,12445, 0, 0, 0,11474, 0, 0, 0, - 1467, 0, 0, 285, 0,11007,12407, 0, 0, 0, - 1468, 0, 0, 0, 0, 0, 0, 1472, 0, 0, -11474, 0, 490, 0, 910, 0, 0, 0, 0, 0, - 942, 0,12331,12369, 0, 0, 0, 0, 0, 0, - 0, 0, 1487, 0, 1586, 0, 0, 0, 926, 0, + 0,11328, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 9018, 0, 8726, 0, 0, 728, 0, 0, + 0, 0, 0, 296, 0, 0, 0, 0, 0, 0, + 296, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 4758, 344, 0, 9060, 0, 0, + 0, 9130, 0, 2829, 0, 0, 0, 2829, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 492, 0, 0, 0, 0, 0, 0, + 307, 0, 1330, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 2829, 0, 425, 0, 442, 0, 0, 0, + 0, 0, 0, 0,11478, 798, 0, 0, 0, 0, + 0, 1325, 0, 767, 0, 0, 0, 0, 0, 0, + 0, 806, 0, 0, 0, 0, 0, 0, 0, 0, + 1329, 0,11478,11478, 0,11510, 0, 0, 0, 0, + 0, 0, 1331,12342, 0, 1333,11478,10720, 1336,11478, + 0, 0, 0, 0, 0, 0, 1337, 0, 0, 0, +12312, 0, 0, 0,11478, 0, 0, 0, 1339, 0, + 0, 266, 0, 1470,12274, 0, 0, 0, 1340, 0, + 0, 0, 0, 0, 0, 1342, 0, 0,11478, 0, + 548, 0, 818, 0, 0, 0, 0, 0, 838, 0, +12198,12236, 0, 0, 0, 0, 0, 0, 0, 0, + 1386, 0, 1440, 0, 0, 0, 819, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0,12445,10888, -12203, 0, 492, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1363, 1363, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, + 0, 559, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0,12312, 382,10892, 0, + 559, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1263, 1263, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, }; protected static readonly short [] yyGindex = { 0, - 0, 1799, 0, 0, 0, -2, -10, -179, -42, 1800, - 0, 1841, 1854, 83, 0, 0, -6, 0, 0, 0, - 0, 0, 0, -826, -694, -224, -431, 0, 0, 0, - 0, 0, -193, 0, 0, 0, 934, 0, 1047, 0, - 0, 0, 0, 814, 815, -17, -230, 0, 0, 0, - 0, 672,-1118, -618, -488, -460, -427, -357, -308, -219, --1116,-1131, 0, 1, 0, 234, 0,-1073, 0, 0, - 0, 0, 0, 0, 617, 173, 458, 0, 0, 0, - 493,-1039, 0, -276, -293, 1217, 0, 0, 0, -863, - 453, 0, 0, -492, 0, 0, 522, 0, 0, 497, - 0, 0, 532, 0,-1189, -934, 0, 0, 0, 0, - 0, 625, -13, 0, 0, 1054, 1056, 1057, 1215, -521, - 0, 0, -321, 1062, 613, 0, -995, 0, 0, 0, - 0, 0, 0, 0, 0, 427, 0, 0, 0, 0, - 0, 0, 0, 0, 683, 0, 0, 0, 0, -340, - 607, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 701, 0, -504, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 438, 0, 0, 535, 0, 0, 541, 543, - 465, 0, 0, 0, 0, 0, 0, 0, 0, 771, - 0, 0, 0, 0, -59, 0, -15, -91, 0, 0, - 605, 0, 665, 0, 1122, 0, 1416, -291, -274, -66, - 451, 0, 777, 0, -38, 518, 0, 0, 1027, 0, + 0, 1655, 0, 0, 0, -1, -12, -179, -50, 1659, + 0, 1707, 1715, 87, 0, 0, -3, 0, 0, 0, + 0, 0, 0, -781, -693, -222, -446, 0, 0, 0, + 0, 0, -198, 0, 0, 0, 793, 0, 898, 0, + 0, 0, 0, 655, 657, -17, -235, 0, 0, 501, + 0, 528, -686, -685, -617, -594, -592, -575, -571, -553, + 0,-1140, 0, 12, 0, 131, 0,-1061, 0, 0, + 0, -8, 322, 0, 0, 0, 361,-1046, 0, -280, + -291, 1073, 0, 0, 0, -871, 310, 0, 0, -493, + 0, 0, 378, 0, 0, 350, 0, 0, 386, 0, + -555, -806, 0, 0, 0, 0, 0, 478, -13, 0, + 0, 905, 908, 916, 1063, -524, 0, 0, -326, 899, + 468, 0,-1078, 0, 0, 0, 0, 0, 0, 0, + 0, 275, 0, 0, 0, 0, 0, 0, 0, 0, + 532, 0, 0, 0, 0, -339, 462, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 546, 0, -498, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 298, 0, + 0, 377, 0, 0, 387, 390, 306, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 592, 0, 0, 0, + 0, -53, 0, -15, -67, 0, 0, 455, 0, 511, + 0, 959, 0, 1251, -293, -274, -64, 622, 0, 616, + 0, -38, 158, 0, 0, 56, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -262, 0, 1292, 0, 0, -279, 0, 0, + 0, 917, 0, -299, -134, 1077, 989, 0, 994, 0, + 1207, 1427, 1116, 0, 0, 820, 1724, 0, 0, 0, + 0, 1098, 0, 0, 0, 0, 0, -537, 1466, 0, + 0, 0, 0, 1705, 1085, 0, 0, 483, 821, 678, + 817, 1405, 1407, 1404, 1406, 1409, 0, 1411, 0, 0, + 0, 1035, 1267, -723, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, -290, 0, 0, 0, 0, + -445, 0, 670, 0, 582, 0, 666, 0, 0, 0, + 726, -526, -16, -305, -7, 0, 1660, 0, 42, 0, + 51, 53, 60, 76, 89, 104, 108, 110, 122, 134, + 0, -664, 0, -28, 0, 0, 860, 0, 786, 0, + 0, 0, 766, -325, 830, -820, 0, 876, -457, 0, + 0, 0, 0, 0, 0, 780, 0, 0, 784, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -269, 0, 132, 0, 0, - -320, 0, 0, 0, 1076, 0, -298, -134, 1229, 1159, - 0, 1151, 0, 1361, 1580, 1269, 0, 0, 968, 1882, - 0, 0, 0, 0, 1247, 0, 0, 0, 0, 0, - -515, 1624, 0, 0, 0, 0, 1865, 489, 0, 0, - 474, 922, 905, 918, 1564, 1565, 1566, 1572, 1563, 0, - 1571, 0, 0, 0, 1218, 1427, -708, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -287, 0, - 0, 0, 0, -446, 0, 819, 0, 741, 0, 825, - 0, 0, 0, 890, -526, -16, -307, 12, 0, 1818, - 0, 68, 0, 86, 101, 105, 114, 117, 122, 147, - 148, 149, 150, 0, -667, 0, -25, 0, 0, 1020, - 0, -575, 0, 0, 0, 923, 0, 1077, 0, 1030, - -457, 0, 0, 0, 0, 0, 0, 941, 0, 0, - 937, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 949, 0, 0, 0, 0, 0, 0, 0, - 0, -26, 0, 1469, 0, 0, 0, 1103, 0, 0, - 0, 0, 0, -169, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 1574, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 761, 0, 0, 0, 0, - 0, 0, 0, 0, 862, 0, 0, 0, 0, 0, - 0, -14, 1173, 0, 0, 0, 1175, + 791, 0, 0, 0, 0, 0, 0, 0, 0, -40, + 0, 1307, 0, 0, 0, 947, 0, 0, 0, 0, + 0, -170, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 1415, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 608, 0, 0, 0, 0, 0, 0, + 0, 0, 709, 0, 0, 0, 0, 0, 0, 39, + 1042, 0, 0, 0, 1031, }; protected static readonly short [] yyTable = { 110, - 157, 18, 724, 111, 197, 510, 44, 191, 513, 236, - 446, 428, 570, 194, 486, 352, 729, 675, 316, 471, - 427, 260, 764, 506, 403, 697, 494, 552, 158, 540, - 529, 569, 770, 232, 262, 874, 1115, 855, 856, 1148, - 1149, 933, 996, 466, 6, 254, 360, 774, 368, 535, - 892, 308, 1042, 359, 14, 367, 302, 658, 375, 192, - 302, 595, 1215, 668, 1043, 1235, 309, 1027, 311, 794, - 869, 1353, 197, 197, 1029, 442, 1043, 327, 336, 761, - 885, 1242, 887, 659, 162, 1174, 862, 771, 531, 793, - 408, 1313, 291, 197, 677, 1309, 357, 20, 1, 563, - 292, 349, 163, 200, 1124, 1215, 564, 1246, 1322, 1254, - 332, 95, 358, 1239, 331, 660, 332, 164, 565, 16, - 1278, 165, 677, 333, 350, 315, 1339, 48, 818, 772, - 166, 677, 628, 167, 471, 200, 1109, 1246, 168, 1254, - 762, 110, 157, 409, 595, 111, 702, 863, 236, 595, - 410, 595, 595, 595, 595, 595, 595, 595, 595, 595, - 595, 595, 345, 169, 170, 171, 172, 352, 43, 646, - 158, 48, 375, 595, 375, 595, 375, 595, 1439, 595, - 595, 595, 742, 48, 870, 349, 197, 197, 871, 793, - 1196, 199, 445, 264, 795, 595, 1354, 288, 289, 290, - 2, 294, 295, 446, 718, 570, 306, 307, 350, 352, - 346, 437, 722, 312, 857, 314, 15, 318, 1044, 661, - 375, 193, 329, 330, 569, 669, 162, 361, 570, 1028, - 1044, 443, 470, 411, 595, 466, 1030, 474, 412, 347, - 413, 552, 293, 793, 163, 366, 414, 415, 197, 260, - 528, 552, 1421, 1314, 533, 332, 333, 260, 537, 164, - 322, 327, 482, 165, 575, 536, 3, 4, 5, 6, - 703, 348, 166, 485, 197, 167, 489, 491, 1326, 1445, - 168, 355, 234, 1462, 197, 1055, 869, 349, 527, 516, - 197, 1455, 538, 1456, 524, 48, 526, 1440, 933, 525, - 489, 6, 1039, 234, 933, 169, 170, 171, 172, 570, - 350, 542, 543, 865, 1066, 554, 651, 1383, 551, 557, - 953, 651, 683, 416, 351, 651, 1143, 384, 302, 819, - 742, 1173, 1410, 576, 197, 789, 462, 197, 1417, 2, - 651, 252, 643, 577, 1463, 1095, 553, 470, 586, 1189, - 410, 463, 594, 595, 596, 597, 598, 599, 600, 601, - 602, 603, 604, 385, 502, 1488, 989, 651, 197, 197, - 1465, 1327, 555, 798, 435, 436, 676, 352, 20, 373, - 983, 636, 637, 1341, 626, 236, 651, 1035, 312, 349, - 253, 366, 790, 462, 967, 647, 197, 197, 971, 1485, - 1258, 352, 1288, 202, 871, 848, 800, 684, 463, 1144, - 1371, 1372, 350, 1374, 197, 1053, 933, 1447, 1448, 1121, - 644, 645, 933, 641, 1393, 670, 656, 1400, 197, 507, - 234, 866, 329, 411, 570, 234, 476, 662, 412, 494, - 413, 523, 1416, 386, 387, 234, 414, 415, 471, 480, - 1305, 1151, 1152, 569, 1306, 248, 45, 696, 1154, 249, - 1083, 638, 484, 228, 692, 229, 1438, 113, 955, 1034, - 349, 671, 1051, 1479, 1052, 503, 95, 504, 515, 252, - 1286, 1452, 48, 361, 779, 1489, 781, 720, 782, 586, - 373, 727, 373, 350, 373, 373, 234, 373, 638, 373, - 638, 570, 481, 349, 49, 733, 735, 743, 670, 250, - 113, 671, 694, 751, 113, 672, 741, 887, 887, 951, - 753, 55, 561, 426, 886, 886, 350, 203, 253, 1287, - 197, 505, 551, 1453, 115, 519, 670, 400, 325, 325, - 973, 373, 551, 373, 766, 946, 373, 651, 597, 401, - 811, 982, 736, 197, 671, 638, 608, 609, 450, 325, - 553, 903, 1216, 965, 784, 784, 361, 718, 695, 451, - 553, 1289, 432, 694, 747, 810, 673, 115, 347, 697, - 347, 115, 671, 867, 631, 633, 337, 338, 339, 340, - 341, 342, 343, 344, 361, 978, 764, 887, 361, 651, - 361, 361, 361, 361, 886, 1216, 347, 1247, 361, 113, - 693, 797, 677, 585, 513, 816, 861, 803, 1067, 450, - 1290, 352, 467, 747, 467, 368, 349, 234, 349, 695, - 451, 597, 832, 247, 197, 649, 597, 1247, 597, 597, - 597, 597, 597, 597, 597, 597, 597, 597, 597, 350, - 734, 350, 325, 325, 349, 197, 833, 817, 357, 649, - 597, 470, 597, 351, 597, 351, 597, 597, 597, 251, - 260, 368, 831, 651, 533, 489, 115, 350, 651, 467, - 578, 339, 651, 834, 853, 722, 649, 315, 350, 727, - 579, 351, 1217, 263, 720, 499, 585, 651, 265, 500, - 1015, 585, 778, 585, 585, 585, 585, 585, 585, 585, - 585, 585, 585, 585, 325, 315, 410, 95, 197, 95, - 1218, 597, 878, 252, 651, 585, 1328, 585, 650, 585, - 339, 585, 585, 585, 888, 1217, 889, 1248, 113, 197, - 325, 585, 585, 651, 891, 766, 585, 585, 1198, 1214, - 325, 895, 650, 1219, 95, 197, 325, 585, 585, 197, - 328, 347, 350, 1218, 113, 1249, 1088, 1248, 1198, 586, - 585, 518, 253, 647, 586, 905, 780, 727, 95, 650, - 356, 430, 946, 552, 519, 113, 585, 1172, 921, 922, - 643, 349, 1214, 677, 1245, 1249, 1219, 707, 1250, 411, - 325, 520, 1118, 325, 412, 115, 413, 349, 197, 349, - 812, 673, 414, 415, 350, 552, 541, 662, 349, 943, - 673, 485, 813, 1220, 1245, 369, 197, 197, 1250, 935, - 350, 115, 350, 489, 325, 325, 969, 1065, 1015, 396, - 1150, 350, 593, 972, 351, 552, 351, 835, 879, 1077, - 397, 675, 115, 980, 836, 727, 283, 541, 672, 610, - 611, 1078, 325, 325, 398, 283, 1220, 672, 1251, 605, - 606, 607, 1221, 1404, 541, 541, 541, 541, 541, 541, + 157, 236, 18, 111, 197, 191, 513, 510, 724, 158, + 486, 428, 446, 570, 471, 729, 194, 44, 675, 427, + 316, 260, 764, 506, 403, 697, 569, 529, 540, 552, + 1116, 262, 770, 494, 995, 892, 874, 308, 466, 352, + 855, 856, 1041, 1042, 774, 254, 347, 410, 360, 535, + 368, 921, 1146, 1147, 1042, 1234, 302, 331, 162, 359, + 302, 367, 781, 658, 794, 14, 309, 163, 311, 164, + 1, 1241, 197, 197, 361, 442, 165, 1341, 336, 322, + 327, 410, 192, 885, 668, 887, 232, 20, 1025, 659, + 998, 702, 166, 197, 683, 1173, 636, 637, 252, 1027, + 355, 291, 1141, 1300, 48, 167, 761, 200, 671, 292, + 646, 502, 672, 554, 1440, 261, 48, 865, 1125, 771, + 168, 660, 95, 357, 169, 818, 170, 1238, 16, 471, + 411, 1265, 628, 1272, 6, 412, 2, 413, 171, 200, + 236, 110, 157, 414, 415, 111, 1275, 253, 1427, 261, + 172, 158, 315, 261, 261, 261, 261, 261, 261, 261, + 261, 772, 781, 49, 411, 869, 1441, 762, 43, 412, + 555, 413, 2, 673, 115, 1476, 638, 414, 415, 684, + 1195, 199, 1273, 742, 445, 1142, 197, 197, 361, 795, + 361, 352, 361, 435, 436, 1276, 1371, 1043, 332, 333, + 162, 531, 1342, 718, 656, 446, 570, 234, 1043, 163, + 538, 164, 998, 857, 722, 703, 781, 115, 165, 569, + 416, 115, 503, 234, 504, 661, 252, 15, 48, 570, + 466, 1409, 470, 352, 166, 866, 361, 474, 3, 4, + 5, 6, 443, 552, 193, 798, 669, 167, 197, 260, + 1026, 293, 528, 552, 426, 476, 533, 260, 1433, 482, + 537, 1028, 168, 1110, 437, 1301, 169, 1428, 170, 1054, + 1443, 536, 1444, 485, 197, 253, 489, 491, 505, 870, + 171, 484, 1398, 871, 197, 527, 95, 656, 575, 516, + 197, 576, 172, 234, 524, 1477, 526, 515, 349, 525, + 489, 577, 347, 354, 1038, 557, 862, 349, 921, 234, + 570, 542, 543, 800, 1065, 656, 115, 952, 551, 1405, + 20, 350, 1435, 1436, 819, 1313, 400, 553, 302, 1096, + 350, 742, 248, 733, 197, 345, 249, 197, 401, 832, + 869, 561, 349, 261, 988, 55, 1450, 470, 586, 354, + 202, 261, 594, 595, 596, 597, 598, 599, 600, 601, + 602, 603, 604, 833, 657, 350, 643, 863, 197, 197, + 1453, 680, 921, 436, 1172, 608, 609, 236, 1467, 982, + 247, 1274, 733, 346, 626, 347, 250, 647, 875, 875, + 834, 6, 874, 874, 966, 234, 197, 197, 681, 1473, + 676, 352, 848, 631, 633, 1231, 637, 1451, 437, 789, + 349, 637, 347, 347, 197, 637, 203, 347, 1314, 347, + 347, 347, 347, 1122, 261, 352, 641, 347, 197, 384, + 637, 313, 680, 350, 436, 570, 261, 261, 261, 359, + 662, 261, 261, 471, 348, 115, 494, 657, 569, 1050, + 408, 1051, 970, 347, 696, 1149, 1150, 637, 871, 681, + 349, 624, 1152, 624, 692, 385, 790, 1032, 875, 437, + 480, 115, 874, 644, 645, 657, 637, 448, 251, 656, + 410, 48, 1291, 350, 921, 677, 1292, 720, 332, 586, + 921, 727, 115, 1214, 1215, 95, 234, 351, 1329, 252, + 332, 349, 570, 409, 332, 733, 735, 743, 779, 835, + 781, 1319, 782, 751, 950, 449, 836, 332, 624, 741, + 753, 315, 263, 481, 350, 347, 1359, 1360, 637, 1362, + 197, 347, 551, 453, 448, 453, 1214, 1215, 351, 325, + 1381, 553, 551, 1388, 766, 386, 387, 945, 253, 332, + 359, 553, 359, 197, 359, 359, 903, 359, 1404, 359, + 964, 347, 1216, 411, 784, 784, 718, 635, 412, 861, + 413, 48, 449, 349, 811, 560, 414, 415, 697, 349, + 637, 972, 1426, 867, 25, 1217, 26, 1218, 325, 27, + 453, 635, 981, 677, 28, 977, 350, 764, 29, 1066, + 265, 359, 350, 359, 1219, 1216, 359, 31, 1220, 349, + 351, 797, 513, 315, 33, 636, 351, 803, 635, 34, + 816, 707, 252, 35, 361, 349, 1221, 45, 1217, 261, + 1218, 349, 350, 95, 197, 37, 1033, 38, 113, 636, + 115, 39, 28, 362, 363, 352, 351, 1219, 350, 40, + 41, 1220, 350, 42, 350, 197, 319, 578, 228, 879, + 229, 470, 817, 364, 1033, 28, 636, 579, 351, 1221, + 260, 253, 954, 337, 365, 489, 533, 337, 28, 332, + 115, 113, 115, 28, 853, 113, 722, 115, 28, 727, + 28, 28, 28, 28, 720, 1014, 28, 357, 28, 328, + 234, 349, 28, 637, 563, 228, 115, 231, 637, 325, + 325, 564, 637, 358, 28, 1296, 115, 28, 197, 28, + 95, 337, 878, 565, 350, 877, 315, 637, 1309, 1315, + 325, 519, 1197, 1213, 888, 663, 889, 354, 351, 197, + 296, 332, 297, 28, 891, 766, 890, 1327, 736, 28, + 28, 895, 1197, 332, 637, 197, 600, 332, 600, 197, + 349, 1089, 897, 663, 261, 647, 388, 389, 350, 586, + 332, 430, 663, 637, 586, 905, 1213, 727, 1197, 350, + 113, 349, 778, 350, 581, 945, 552, 369, 921, 922, + 879, 337, 994, 780, 792, 337, 905, 332, 337, 1119, + 337, 905, 332, 905, 350, 337, 905, 905, 197, 905, + 905, 356, 357, 812, 643, 277, 518, 277, 552, 942, + 662, 485, 277, 325, 325, 813, 197, 197, 432, 519, + 396, 905, 1014, 489, 953, 1064, 968, 1148, 675, 337, + 935, 315, 936, 971, 399, 552, 520, 563, 397, 841, + 95, 593, 318, 979, 564, 727, 390, 391, 318, 1171, + 1392, 1078, 115, 115, 398, 319, 565, 581, 610, 611, + 392, 393, 581, 1079, 581, 581, 581, 581, 581, 581, + 581, 581, 581, 581, 581, 325, 905, 402, 332, 332, + 197, 332, 332, 57, 1262, 999, 581, 1001, 581, 1003, + 581, 1262, 581, 581, 581, 115, 659, 115, 405, 113, + 446, 325, 197, 1013, 268, 659, 357, 432, 581, 811, + 810, 325, 1445, 268, 662, 658, 908, 325, 1067, 1133, + 1068, 908, 881, 908, 658, 113, 908, 908, 297, 908, + 908, 352, 447, 727, 332, 315, 432, 332, 1019, 1247, + 1020, 332, 1021, 394, 395, 411, 113, 581, 1464, 513, + 412, 908, 413, 332, 433, 448, 332, 332, 414, 415, + 741, 325, 741, 499, 325, 1482, 1483, 500, 449, 766, + 332, 434, 1057, 451, 1059, 761, 1060, 761, 452, 761, + 453, 454, 455, 456, 228, 65, 65, 438, 457, 65, + 678, 197, 458, 441, 679, 325, 325, 750, 1072, 750, + 941, 750, 941, 1069, 459, 899, 908, 460, 325, 461, + 899, 325, 899, 710, 485, 899, 899, 711, 899, 899, + 467, 719, 783, 325, 325, 500, 679, 1097, 727, 766, + 167, 901, 167, 462, 167, 1104, 901, 468, 901, 66, + 1013, 901, 901, 66, 901, 901, 1109, 331, 236, 485, + 475, 179, 485, 179, 479, 179, 895, 614, 615, 616, + 617, 895, 487, 895, 945, 551, 895, 895, 358, 895, + 895, 1129, 236, 509, 553, 1158, 494, 488, 1132, 332, + 514, 332, 494, 381, 382, 383, 197, 918, 919, 1295, + 485, 155, 517, 155, 113, 899, 752, 551, 752, 556, + 332, 332, 1154, 1060, 545, 162, 553, 162, 163, 852, + 163, 852, 68, 574, 68, 1158, 115, 534, 1196, 1212, + 332, 901, 657, 347, 551, 1101, 1102, 347, 332, 332, + 347, 332, 347, 553, 325, 680, 197, 347, 1196, 350, + 438, 1183, 495, 874, 874, 411, 895, 411, 495, 185, + 539, 185, 197, 156, 580, 156, 1228, 325, 350, 1192, + 113, 120, 1212, 120, 1196, 634, 411, 411, 354, 282, + 113, 282, 337, 338, 339, 340, 341, 342, 343, 344, + 325, 127, 289, 127, 289, 642, 411, 1454, 1455, 518, + 518, 637, 637, 682, 411, 1114, 1115, 411, 612, 613, + 618, 619, 485, 1307, 694, 704, 705, 197, 197, 706, + 708, 583, 709, 1267, 1192, 197, 731, 1307, 732, 747, + 748, 749, 750, 752, 197, 197, 754, 197, 755, 756, + 757, 1270, 1271, 1287, 1337, 115, 1338, 765, 773, 115, + 775, 776, 787, 788, 792, 1287, 799, 197, 793, 801, + 197, 808, 820, 802, 1299, 821, 827, 1302, 1287, 823, + 824, 325, 357, 370, 844, 1316, 839, 115, 115, 850, + 845, 115, 846, 847, 115, 852, 851, 1287, 854, 868, + 872, 199, 325, 1372, 371, 372, 373, 374, 375, 376, + 377, 378, 379, 380, 583, 873, 882, 875, 115, 583, + 1399, 583, 583, 583, 583, 583, 583, 583, 583, 583, + 583, 583, 883, 1411, 1413, 884, 113, 113, 893, 900, + 898, 909, 914, 583, 916, 583, 727, 583, 1267, 583, + 583, 583, 920, 923, 924, 930, 933, 931, 485, 934, + 1399, 1399, 43, 264, 938, 325, 940, 288, 289, 290, + 958, 294, 295, 946, 959, 1421, 306, 307, 960, 113, + 967, 113, 961, 312, 969, 314, 325, 318, 976, 332, + 503, 985, 329, 330, 983, 332, 991, 987, 989, 992, + 996, 997, 325, 1007, 583, 1016, 325, 1017, 727, 1022, + 1029, 1023, 1030, 1031, 1037, 366, 1399, 1036, 1049, 1039, + 1055, 879, 541, 1058, 1056, 1063, 1077, 1081, 1080, 1082, + 1083, 332, 1090, 1095, 1100, 1105, 1103, 1111, 1112, 1117, + 1121, 1123, 1125, 1128, 727, 1153, 1156, 1163, 1142, 1135, + 1170, 1182, 1230, 1162, 1469, 1469, 1171, 1174, 1176, 1179, + 1178, 1478, 1478, 541, 1187, 1180, 586, 586, 1181, 1226, + 1232, 1229, 1245, 325, 325, 605, 606, 607, 1248, 1233, 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, - 197, 388, 389, 346, 1275, 1000, 811, 1002, 1251, 1004, - 447, 1275, 349, 357, 399, 346, 877, 446, 614, 346, - 614, 1232, 197, 1014, 228, 1221, 231, 1252, 352, 432, - 197, 662, 346, 448, 292, 350, 292, 890, 1132, 357, - 678, 292, 315, 113, 679, 1457, 449, 402, 1021, 351, - 1022, 451, 1023, 897, 727, 881, 452, 1252, 453, 454, - 455, 456, 911, 296, 346, 297, 457, 911, 315, 911, - 458, 1222, 911, 911, 1294, 911, 911, 346, 297, 350, - 346, 1476, 459, 325, 513, 460, 879, 461, 432, 917, - 766, 1494, 1495, 1058, 917, 1060, 917, 1061, 405, 917, - 917, 541, 917, 917, 394, 395, 325, 390, 391, 113, - 115, 462, 433, 773, 1222, 773, 1253, 773, 995, 113, - 792, 392, 393, 1070, 917, 954, 563, 920, 841, 325, - 918, 919, 920, 564, 920, 485, 339, 920, 920, 339, - 920, 920, 434, 65, 65, 565, 1253, 65, 1096, 727, - 766, 762, 911, 762, 228, 762, 1103, 438, 346, 710, - 719, 1014, 920, 711, 500, 1100, 1101, 1295, 485, 1108, - 346, 485, 777, 441, 346, 236, 115, 1135, 913, 917, - 381, 382, 383, 913, 551, 913, 115, 346, 913, 913, - 1128, 913, 913, 907, 946, 467, 261, 1131, 907, 236, - 907, 350, 438, 907, 907, 197, 907, 907, 508, 485, - 325, 346, 553, 346, 508, 468, 551, 920, 1019, 346, - 331, 1156, 1061, 346, 346, 475, 346, 346, 57, 1135, - 261, 325, 346, 346, 261, 261, 261, 261, 261, 261, - 261, 261, 487, 1068, 553, 1069, 551, 1197, 1213, 182, - 479, 182, 346, 182, 194, 509, 194, 197, 194, 371, - 346, 488, 1185, 346, 358, 113, 113, 1197, 913, 755, - 346, 755, 783, 197, 553, 252, 679, 361, 1230, 953, - 485, 953, 346, 907, 66, 346, 346, 170, 66, 170, - 764, 1213, 764, 1197, 325, 509, 362, 363, 425, 346, - 425, 509, 759, 177, 411, 177, 759, 514, 113, 412, - 113, 413, 178, 1320, 178, 325, 364, 414, 415, 425, - 425, 1466, 1467, 1197, 253, 517, 1320, 365, 197, 197, - 534, 325, 115, 115, 1280, 325, 197, 539, 864, 425, - 864, 574, 351, 1349, 545, 1350, 351, 425, 346, 130, - 425, 130, 68, 923, 68, 556, 130, 197, 197, 200, - 197, 200, 350, 171, 351, 171, 1301, 680, 351, 580, - 346, 351, 135, 351, 135, 115, 634, 115, 351, 1301, - 354, 197, 361, 297, 197, 297, 361, 657, 346, 361, - 351, 361, 1301, 142, 642, 142, 361, 886, 886, 1329, - 204, 682, 325, 325, 614, 615, 616, 617, 694, 304, - 1301, 304, 351, 532, 532, 651, 651, 1113, 1114, 612, - 613, 618, 619, 1384, 261, 704, 705, 706, 708, 731, - 709, 732, 261, 747, 748, 749, 923, 750, 752, 754, - 1411, 923, 205, 923, 923, 923, 923, 923, 923, 923, - 923, 923, 923, 1423, 1425, 755, 756, 757, 727, 765, - 1280, 1193, 773, 775, 541, 923, 325, 923, 776, 923, - 485, 923, 923, 923, 787, 788, 792, 808, 820, 793, - 1411, 1411, 799, 821, 801, 823, 802, 1433, 824, 827, - 43, 844, 206, 207, 208, 209, 325, 210, 211, 212, - 213, 214, 215, 216, 217, 261, 839, 218, 219, 220, - 221, 222, 223, 224, 225, 371, 1193, 261, 261, 261, - 727, 371, 261, 261, 845, 846, 923, 847, 851, 850, - 113, 513, 852, 854, 872, 868, 1411, 199, 873, 875, - 882, 883, 898, 884, 900, 1284, 1285, 893, 909, 914, - 916, 920, 923, 371, 930, 924, 727, 371, 931, 370, - 933, 934, 939, 936, 941, 947, 1481, 1481, 959, 1312, - 960, 961, 1315, 1490, 1490, 968, 962, 970, 586, 586, - 371, 372, 373, 374, 375, 376, 377, 378, 379, 380, - 977, 503, 992, 984, 986, 993, 1031, 115, 371, 988, - 990, 997, 998, 371, 1008, 371, 371, 371, 371, 371, - 371, 371, 371, 371, 371, 371, 1017, 1025, 1024, 1033, - 1032, 1038, 1050, 1037, 1040, 879, 371, 371, 1056, 371, - 371, 371, 1057, 371, 371, 371, 1059, 371, 371, 1064, - 1072, 371, 371, 371, 371, 1076, 1079, 113, 371, 371, - 1080, 113, 1081, 371, 371, 371, 371, 371, 371, 371, - 371, 1089, 1082, 1094, 1099, 1104, 1102, 1124, 1116, 1111, - 1155, 325, 371, 1120, 1122, 371, 1134, 371, 1158, 113, - 113, 1127, 1144, 113, 1160, 1164, 113, 1162, 371, 560, - 1163, 1172, 1171, 1176, 1179, 1180, 1181, 1182, 25, 840, - 26, 1184, 1188, 27, 1228, 1259, 1233, 1231, 28, 1236, - 261, 1234, 29, 113, 115, 1243, 1291, 1261, 115, 1282, - 1304, 31, 1336, 325, 1318, 1307, 1321, 1308, 33, 1324, - 1333, 1342, 1335, 34, 1347, 1338, 1317, 35, 1325, 325, - 1340, 1327, 1346, 1344, 1352, 1360, 115, 115, 1363, 37, - 115, 38, 1364, 115, 1365, 39, 1357, 1367, 1375, 1376, - 48, 1379, 48, 40, 41, 1389, 1394, 42, 1406, 1396, - 319, 1408, 1405, 1409, 1415, 1418, 1419, 1429, 1430, 1432, - 115, 1435, 1437, 48, 1434, 1449, 1450, 513, 1454, 1443, - 1458, 1459, 513, 513, 325, 325, 48, 1461, 1468, 1453, - 1452, 48, 325, 1474, 1496, 1475, 48, 1497, 48, 48, - 48, 48, 1498, 9, 48, 513, 48, 949, 545, 838, - 48, 740, 32, 325, 325, 513, 325, 503, 513, 513, - 615, 941, 48, 513, 504, 48, 513, 48, 513, 808, - 513, 513, 513, 513, 462, 261, 616, 325, 513, 684, - 325, 354, 513, 30, 22, 812, 513, 502, 30, 324, - 528, 48, 758, 31, 513, 221, 783, 513, 96, 513, - 513, 766, 813, 31, 846, 513, 767, 513, 513, 513, - 513, 513, 513, 513, 513, 513, 513, 513, 758, 787, - 815, 788, 817, 513, 672, 672, 328, 694, 513, 513, - 353, 513, 513, 513, 513, 513, 513, 513, 346, 513, - 513, 651, 513, 513, 513, 513, 513, 513, 513, 513, - 513, 513, 138, 513, 513, 513, 513, 513, 513, 513, - 513, 513, 513, 513, 513, 513, 513, 513, 513, 513, - 513, 513, 513, 513, 513, 120, 300, 513, 145, 513, - 139, 513, 121, 301, 513, 840, 840, 146, 651, 233, - 513, 237, 54, 840, 840, 840, 840, 840, 21, 840, - 840, 1009, 840, 840, 840, 840, 840, 840, 840, 840, - 929, 1237, 1283, 1420, 840, 1451, 840, 840, 840, 840, - 840, 840, 1106, 1107, 840, 346, 1460, 829, 840, 840, - 1407, 840, 840, 840, 1436, 1402, 1298, 1310, 956, 842, - 957, 958, 952, 840, 1492, 840, 1244, 840, 840, 1484, - 1331, 840, 1241, 840, 840, 840, 840, 840, 840, 840, - 840, 840, 840, 840, 840, 1431, 840, 1426, 1424, 840, - 840, 1351, 1177, 840, 840, 1483, 1302, 925, 744, 1178, - 860, 976, 904, 786, 581, 902, 1041, 838, 840, 840, - 840, 840, 840, 299, 544, 858, 840, 840, 334, 620, - 840, 621, 624, 622, 1166, 840, 840, 840, 840, 840, - 623, 625, 760, 840, 1262, 840, 404, 1169, 1026, 1097, - 1123, 840, 840, 1036, 1092, 1085, 1090, 999, 991, 737, - 1260, 1157, 899, 640, 927, 926, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 840, 840, 840, 840, - 0, 840, 783, 783, 0, 0, 0, 0, 840, 0, - 783, 783, 783, 783, 783, 0, 783, 783, 0, 783, - 783, 783, 783, 783, 783, 783, 0, 0, 748, 0, - 0, 783, 0, 783, 783, 783, 783, 783, 783, 0, - 0, 783, 0, 0, 0, 783, 783, 0, 783, 783, - 783, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 783, 0, 783, 0, 783, 783, 0, 0, 783, 0, - 783, 783, 783, 783, 783, 783, 783, 783, 783, 783, - 783, 783, 0, 783, 0, 0, 783, 783, 0, 0, - 783, 783, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 783, 783, 783, 783, 783, - 0, 0, 0, 783, 783, 0, 0, 783, 0, 0, - 0, 0, 783, 783, 783, 783, 783, 0, 0, 0, - 783, 346, 783, 0, 0, 0, 346, 346, 783, 783, + 541, 541, 541, 541, 541, 541, 911, 1235, 1242, 1269, + 1277, 332, 1290, 1321, 332, 1305, 332, 332, 1294, 1295, + 1308, 332, 332, 1311, 1323, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 1324, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 1304, 1326, 325, 357, 1312, + 1314, 499, 1330, 1328, 357, 332, 332, 1332, 1334, 1335, + 1340, 1345, 1348, 332, 1355, 1351, 332, 1352, 312, 1353, + 1367, 366, 332, 1363, 1364, 1382, 1377, 1384, 1393, 1406, + 1394, 1396, 1397, 1403, 1407, 1417, 357, 1418, 1420, 911, + 357, 1423, 1422, 1425, 911, 1431, 911, 911, 911, 911, + 911, 911, 911, 911, 911, 911, 1437, 541, 1438, 507, + 113, 1442, 1446, 1449, 1447, 1456, 1441, 1440, 911, 1462, + 911, 523, 911, 1463, 911, 911, 911, 1484, 1485, 1486, + 9, 357, 937, 531, 826, 726, 357, 32, 357, 357, + 357, 357, 357, 357, 357, 357, 357, 357, 357, 489, + 601, 929, 796, 490, 448, 602, 670, 30, 325, 357, + 357, 22, 357, 357, 357, 800, 357, 357, 357, 514, + 357, 357, 488, 30, 357, 357, 357, 357, 777, 911, + 31, 357, 357, 744, 754, 206, 357, 357, 357, 357, + 357, 357, 357, 357, 801, 96, 31, 834, 745, 310, + 755, 746, 775, 803, 738, 357, 776, 805, 357, 658, + 357, 680, 658, 25, 314, 26, 339, 332, 27, 828, + 637, 357, 637, 28, 123, 233, 105, 29, 285, 113, + 237, 130, 124, 113, 106, 286, 31, 131, 54, 21, + 1008, 929, 1107, 33, 1108, 1244, 1236, 1439, 34, 1408, + 48, 1448, 35, 325, 1395, 1424, 1284, 1390, 1297, 951, + 1480, 113, 113, 829, 37, 113, 38, 842, 113, 955, + 39, 1318, 956, 48, 1243, 1419, 1240, 1472, 40, 41, + 957, 1414, 42, 1412, 1471, 739, 48, 1188, 1339, 1288, + 693, 48, 113, 744, 925, 902, 48, 1177, 48, 48, + 48, 48, 975, 325, 48, 904, 48, 499, 860, 786, + 48, 581, 499, 499, 838, 299, 544, 1040, 334, 325, + 620, 622, 48, 621, 623, 48, 858, 48, 624, 899, + 734, 625, 760, 1165, 1249, 499, 1168, 1124, 404, 1052, + 1084, 1098, 1035, 1024, 1091, 499, 1086, 737, 499, 499, + 1093, 48, 990, 499, 640, 1246, 499, 296, 499, 1155, + 499, 499, 499, 499, 0, 0, 740, 0, 499, 0, + 0, 926, 499, 0, 325, 325, 499, 0, 0, 0, + 0, 0, 325, 927, 499, 0, 771, 499, 0, 499, + 499, 325, 325, 0, 325, 499, 0, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 499, 499, 0, 0, + 0, 0, 0, 499, 325, 0, 0, 325, 499, 499, + 0, 499, 499, 499, 499, 499, 499, 499, 0, 499, + 499, 0, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 0, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 499, 499, 499, 0, 0, 499, 0, 499, + 541, 499, 0, 0, 499, 828, 828, 0, 0, 0, + 499, 0, 0, 828, 828, 828, 828, 828, 0, 828, + 828, 0, 828, 828, 828, 828, 828, 828, 828, 828, + 0, 0, 0, 0, 828, 0, 828, 828, 828, 828, + 828, 828, 0, 0, 828, 332, 0, 0, 828, 828, + 0, 828, 828, 828, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 828, 0, 828, 0, 828, 828, 0, + 0, 828, 0, 828, 828, 828, 828, 828, 828, 828, + 828, 828, 828, 828, 828, 0, 828, 0, 0, 828, + 828, 0, 0, 828, 828, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 828, 828, + 828, 828, 828, 0, 0, 0, 828, 828, 0, 0, + 828, 0, 0, 0, 0, 828, 828, 828, 828, 828, + 0, 0, 0, 828, 0, 828, 0, 0, 0, 0, + 0, 828, 828, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 339, 346, - 0, 0, 0, 783, 783, 783, 783, 0, 783, 346, - 0, 0, 346, 346, 0, 783, 0, 346, 0, 0, - 346, 0, 346, 0, 346, 346, 346, 346, 0, 0, - 0, 0, 346, 0, 0, 0, 346, 0, 0, 0, - 346, 0, 0, 0, 0, 0, 0, 0, 346, 0, - 0, 346, 0, 346, 346, 0, 0, 0, 0, 346, - 0, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 0, 0, 0, 0, 346, 0, 0, - 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 0, 346, 346, 0, 0, 346, 346, 346, - 346, 346, 0, 0, 346, 346, 0, 0, 0, 346, - 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, - 0, 0, 0, 0, 748, 0, 0, 0, 346, 748, - 748, 346, 0, 346, 0, 346, 0, 0, 346, 0, - 0, 0, 0, 0, 346, 376, 0, 0, 0, 0, - 0, 0, 748, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 748, 0, 0, 748, 748, 0, 0, 0, - 748, 0, 0, 748, 0, 748, 0, 748, 748, 748, - 748, 0, 0, 0, 0, 748, 0, 0, 0, 748, - 0, 0, 0, 748, 0, 0, 0, 0, 0, 0, - 0, 748, 0, 0, 748, 0, 748, 748, 0, 0, - 0, 0, 748, 0, 748, 748, 748, 748, 748, 748, - 748, 748, 748, 748, 748, 0, 0, 0, 0, 0, - 748, 0, 0, 0, 0, 748, 748, 748, 748, 748, - 748, 0, 748, 748, 748, 0, 748, 748, 0, 0, - 748, 748, 748, 748, 339, 0, 0, 748, 748, 339, - 339, 0, 748, 748, 748, 748, 748, 748, 748, 748, - 346, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 748, 339, 0, 748, 0, 748, 0, 748, 0, - 0, 748, 339, 0, 0, 339, 339, 748, 0, 0, - 339, 0, 0, 339, 0, 339, 0, 339, 339, 339, - 339, 0, 0, 0, 0, 339, 0, 0, 0, 339, - 0, 0, 0, 339, 0, 0, 0, 0, 0, 0, - 0, 339, 0, 0, 339, 0, 339, 339, 0, 0, - 0, 0, 339, 0, 339, 339, 339, 339, 339, 339, - 339, 339, 339, 339, 339, 0, 0, 0, 0, 0, - 339, 0, 0, 0, 0, 339, 339, 339, 339, 339, - 339, 0, 339, 339, 339, 0, 339, 339, 0, 0, - 339, 339, 339, 339, 0, 0, 0, 339, 339, 0, - 0, 0, 339, 339, 339, 339, 339, 339, 339, 339, - 0, 376, 0, 0, 0, 0, 376, 376, 0, 0, - 0, 339, 0, 0, 339, 0, 339, 0, 339, 0, - 0, 339, 0, 0, 0, 0, 0, 339, 0, 376, - 0, 0, 0, 0, 0, 49, 0, 0, 0, 376, - 0, 0, 376, 376, 0, 0, 0, 376, 0, 0, - 376, 0, 376, 0, 376, 376, 376, 376, 0, 0, - 0, 0, 376, 0, 0, 0, 376, 0, 0, 0, - 376, 0, 0, 0, 0, 0, 0, 0, 376, 0, - 0, 376, 0, 376, 376, 0, 0, 0, 0, 376, - 0, 376, 376, 376, 376, 376, 376, 376, 376, 376, - 376, 376, 0, 0, 0, 0, 0, 376, 0, 0, - 0, 0, 376, 376, 0, 376, 376, 376, 0, 376, - 376, 376, 0, 376, 376, 0, 346, 376, 376, 376, - 376, 0, 346, 0, 376, 376, 0, 0, 0, 376, - 376, 376, 376, 376, 376, 376, 376, 0, 28, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 376, 0, - 0, 376, 0, 376, 346, 0, 0, 0, 346, 0, - 0, 0, 0, 0, 376, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 828, 828, 828, 828, + 0, 828, 771, 771, 0, 0, 0, 0, 828, 0, + 771, 771, 771, 771, 771, 0, 771, 771, 0, 771, + 771, 771, 771, 771, 771, 771, 0, 0, 734, 0, + 0, 771, 0, 771, 771, 771, 771, 771, 771, 0, + 0, 771, 0, 0, 0, 771, 771, 0, 771, 771, + 771, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 771, 0, 771, 0, 771, 771, 0, 0, 771, 0, + 771, 771, 771, 771, 771, 771, 771, 771, 771, 771, + 771, 771, 0, 771, 0, 0, 771, 771, 0, 0, + 771, 771, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 771, 771, 771, 771, 771, + 0, 0, 0, 771, 771, 0, 0, 771, 0, 0, + 0, 0, 771, 771, 771, 771, 771, 0, 0, 0, + 771, 332, 771, 0, 0, 0, 332, 332, 771, 771, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 325, 332, + 0, 0, 0, 771, 771, 771, 771, 0, 771, 332, + 0, 0, 332, 332, 0, 771, 0, 332, 0, 0, + 332, 0, 332, 0, 332, 332, 332, 332, 0, 0, + 0, 0, 332, 0, 0, 0, 332, 0, 0, 0, + 332, 0, 0, 0, 0, 0, 0, 0, 332, 0, + 0, 332, 0, 332, 332, 0, 0, 0, 0, 332, + 0, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 0, 0, 0, 0, 332, 0, 0, + 0, 0, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 0, 332, 332, 0, 0, 332, 332, 332, + 332, 332, 0, 0, 332, 332, 0, 0, 0, 332, + 332, 332, 332, 332, 332, 332, 332, 0, 0, 0, + 0, 0, 0, 0, 734, 0, 0, 0, 332, 734, + 734, 332, 0, 332, 0, 332, 0, 0, 332, 0, + 0, 0, 0, 0, 332, 362, 0, 0, 0, 0, + 0, 0, 734, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 734, 0, 0, 734, 734, 0, 0, 0, + 734, 0, 0, 734, 0, 734, 0, 734, 734, 734, + 734, 0, 0, 0, 0, 734, 0, 0, 0, 734, + 0, 0, 0, 734, 0, 0, 0, 0, 0, 0, + 0, 734, 0, 0, 734, 0, 734, 734, 0, 0, + 0, 0, 734, 0, 734, 734, 734, 734, 734, 734, + 734, 734, 734, 734, 734, 0, 0, 0, 0, 0, + 734, 0, 0, 0, 0, 734, 734, 734, 734, 734, + 734, 0, 734, 734, 734, 0, 734, 734, 0, 0, + 734, 734, 734, 734, 325, 0, 0, 734, 734, 325, + 325, 0, 734, 734, 734, 734, 734, 734, 734, 734, + 332, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 734, 325, 0, 734, 0, 734, 0, 734, 0, + 0, 734, 325, 0, 0, 325, 325, 734, 0, 0, + 325, 0, 0, 325, 0, 325, 0, 325, 325, 325, + 325, 0, 0, 0, 0, 325, 0, 0, 0, 325, + 0, 0, 0, 325, 0, 0, 0, 0, 0, 0, + 0, 325, 0, 0, 325, 0, 325, 325, 0, 0, + 0, 0, 325, 0, 325, 325, 325, 325, 325, 325, + 325, 325, 325, 325, 325, 0, 0, 0, 0, 0, + 325, 0, 0, 0, 0, 325, 325, 325, 325, 325, + 325, 0, 325, 325, 325, 0, 325, 325, 0, 0, + 325, 325, 325, 325, 0, 0, 0, 325, 325, 0, + 0, 0, 325, 325, 325, 325, 325, 325, 325, 325, + 0, 362, 0, 0, 0, 0, 362, 362, 0, 0, + 0, 325, 0, 0, 325, 0, 325, 0, 325, 0, + 0, 325, 0, 0, 0, 0, 0, 325, 0, 362, + 0, 0, 0, 0, 0, 49, 0, 0, 0, 362, + 0, 0, 362, 362, 0, 0, 0, 362, 0, 0, + 362, 0, 362, 0, 362, 362, 362, 362, 0, 0, + 0, 0, 362, 0, 0, 0, 362, 0, 0, 0, + 362, 0, 0, 0, 0, 0, 0, 0, 362, 0, + 0, 362, 0, 362, 362, 0, 0, 0, 0, 362, + 0, 362, 362, 362, 362, 362, 362, 362, 362, 362, + 362, 362, 0, 0, 0, 0, 0, 362, 0, 0, + 0, 0, 362, 362, 0, 362, 362, 362, 0, 362, + 362, 362, 0, 362, 362, 0, 332, 362, 362, 362, + 362, 0, 332, 0, 362, 362, 0, 0, 0, 362, + 362, 362, 362, 362, 362, 362, 362, 0, 28, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 362, 0, + 0, 362, 0, 362, 332, 0, 0, 0, 332, 0, + 0, 0, 0, 0, 362, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 346, - 0, 36, 0, 0, 346, 0, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 0, 346, 346, - 0, 0, 346, 346, 346, 346, 346, 0, 0, 346, - 346, 0, 0, 0, 346, 346, 346, 346, 346, 346, - 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, - 35, 0, 0, 346, 0, 0, 346, 0, 346, 0, - 346, 0, 49, 346, 0, 0, 49, 0, 49, 346, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 332, + 0, 36, 0, 0, 332, 0, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 0, 332, 332, + 0, 0, 332, 332, 332, 332, 332, 0, 0, 332, + 332, 0, 0, 0, 332, 332, 332, 332, 332, 332, + 332, 332, 0, 0, 0, 0, 0, 0, 0, 0, + 35, 0, 0, 332, 0, 0, 332, 0, 332, 0, + 332, 0, 49, 332, 0, 0, 49, 0, 49, 332, 49, 0, 49, 0, 0, 49, 0, 49, 49, 0, 49, 0, 49, 0, 49, 0, 49, 49, 49, 49, 0, 0, 49, 49, 0, 0, 0, 34, 49, 49, @@ -9698,7 +9835,7 @@ void case_956() 0, 28, 28, 36, 28, 28, 28, 0, 36, 0, 28, 0, 36, 0, 0, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 36, 36, 0, - 28, 0, 36, 36, 0, 0, 28, 28, 36, 931, + 28, 0, 36, 36, 0, 0, 28, 28, 36, 919, 36, 36, 36, 36, 0, 28, 0, 0, 36, 0, 0, 0, 36, 0, 36, 0, 0, 35, 0, 0, 0, 35, 0, 0, 36, 0, 36, 36, 0, 36, @@ -9713,7 +9850,7 @@ void case_956() 0, 0, 0, 0, 34, 0, 34, 34, 34, 34, 0, 0, 35, 0, 34, 0, 0, 28, 34, 35, 34, 28, 0, 0, 0, 0, 0, 0, 0, 0, - 34, 0, 28, 34, 0, 34, 0, 28, 932, 34, + 34, 0, 28, 34, 0, 34, 0, 28, 920, 34, 0, 28, 0, 0, 28, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 28, 28, 0, 34, 33, 28, 28, 0, 33, 34, 34, 28, 0, 28, @@ -9724,7 +9861,7 @@ void case_956() 33, 0, 33, 33, 33, 33, 0, 0, 48, 0, 33, 0, 28, 48, 33, 0, 33, 48, 28, 28, 48, 0, 0, 0, 0, 0, 33, 0, 0, 33, - 0, 33, 48, 48, 0, 33, 931, 48, 48, 0, + 0, 33, 48, 48, 0, 33, 919, 48, 48, 0, 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, 48, 0, 48, 0, 33, 48, 48, 0, 48, 48, 0, 33, 48, 0, 0, 0, 0, 0, 48, @@ -9739,7 +9876,7 @@ void case_956() 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, 48, 49, 49, 0, 48, 0, 49, 49, 0, 0, 0, 0, 49, 0, 49, 49, 49, 49, 0, 0, - 0, 0, 49, 0, 48, 932, 49, 0, 49, 48, + 0, 0, 49, 0, 48, 920, 49, 0, 49, 48, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0, 48, 49, 0, 49, 0, 48, 0, 49, 0, 48, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, @@ -9756,552 +9893,539 @@ void case_956() 0, 74, 0, 37, 0, 38, 75, 0, 0, 39, 0, 76, 77, 78, 79, 80, 81, 40, 41, 82, 83, 42, 84, 0, 85, 0, 0, 86, 87, 0, - 346, 88, 89, 0, 0, 0, 346, 0, 0, 0, + 332, 88, 89, 0, 0, 0, 332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, 95, 0, 0, 0, 96, 0, 0, 0, 0, 97, 98, 99, 100, 101, 0, 0, - 0, 102, 346, 103, 0, 0, 0, 0, 0, 104, + 0, 102, 332, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 346, 0, 0, 0, - 0, 0, 346, 0, 106, 107, 108, 109, 0, 0, - 0, 0, 0, 346, 0, 0, 199, 0, 346, 0, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 0, 0, 0, 0, 0, 0, 346, 0, - 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 0, 346, 346, 0, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 0, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 0, 515, - 0, 0, 346, 0, 346, 515, 0, 346, 0, 0, - 0, 0, 0, 346, 0, 0, 0, 0, 346, 0, - 0, 346, 0, 346, 346, 0, 0, 0, 346, 346, - 0, 0, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 515, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 346, 346, 0, 0, 0, 0, 0, 0, - 346, 346, 0, 346, 0, 0, 0, 0, 0, 346, - 0, 0, 515, 0, 0, 0, 0, 515, 0, 515, - 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, - 0, 0, 0, 0, 0, 0, 0, 346, 0, 0, - 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, - 0, 515, 515, 0, 515, 515, 515, 515, 515, 515, - 515, 515, 515, 515, 0, 515, 515, 515, 515, 515, - 515, 515, 515, 515, 515, 515, 515, 515, 515, 515, - 515, 515, 515, 515, 515, 515, 515, 0, 511, 0, - 0, 0, 0, 515, 511, 0, 346, 0, 0, 0, - 0, 0, 515, 0, 0, 0, 0, 0, 346, 0, - 346, 0, 346, 0, 0, 346, 0, 346, 346, 0, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 511, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 0, 0, 0, 0, 346, 0, 346, - 403, 0, 346, 0, 0, 0, 0, 0, 346, 0, - 0, 511, 0, 0, 0, 0, 511, 0, 511, 511, - 511, 511, 511, 511, 511, 511, 511, 511, 511, 0, - 0, 0, 0, 0, 0, 0, 403, 0, 0, 511, - 511, 0, 511, 511, 511, 511, 511, 511, 511, 0, - 511, 511, 0, 511, 511, 511, 511, 511, 511, 511, - 511, 511, 511, 0, 511, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 511, 511, 511, 511, 511, 511, - 511, 511, 511, 511, 511, 511, 0, 519, 0, 0, - 0, 0, 511, 519, 0, 511, 0, 0, 0, 0, - 0, 511, 0, 0, 0, 0, 0, 339, 0, 403, - 403, 403, 403, 0, 403, 0, 403, 403, 0, 403, - 403, 403, 403, 403, 0, 403, 403, 403, 403, 519, - 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, - 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, - 403, 403, 0, 0, 0, 0, 339, 0, 403, 346, - 0, 403, 0, 0, 0, 0, 0, 403, 0, 0, - 519, 0, 0, 0, 0, 519, 0, 519, 519, 519, - 519, 519, 519, 519, 519, 519, 519, 519, 0, 0, - 0, 0, 0, 0, 0, 346, 0, 0, 0, 519, - 0, 519, 519, 519, 519, 519, 519, 519, 0, 519, - 519, 0, 519, 519, 519, 519, 519, 519, 519, 519, - 519, 519, 0, 519, 519, 519, 519, 519, 519, 519, - 519, 519, 519, 519, 519, 519, 519, 519, 519, 519, - 519, 519, 519, 519, 519, 0, 346, 0, 0, 0, - 0, 519, 346, 0, 519, 0, 0, 0, 0, 0, - 519, 0, 0, 0, 0, 0, 0, 346, 346, 346, - 346, 346, 0, 0, 0, 346, 346, 0, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 0, 0, 0, 0, 0, 0, 346, 0, 0, - 346, 0, 0, 0, 0, 0, 346, 0, 0, 346, - 0, 0, 0, 0, 346, 0, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 346, 0, - 346, 346, 346, 346, 346, 346, 346, 0, 346, 346, - 0, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 0, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 0, 446, 738, 0, 0, 0, - 346, 446, 0, 346, 0, 25, 0, 26, 0, 346, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 389, 0, 106, 107, 108, 109, 0, 0, + 0, 0, 0, 332, 0, 0, 199, 0, 332, 0, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 0, 0, 0, 0, 0, 0, 389, 0, + 0, 0, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 0, 332, 332, 0, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 0, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 0, 501, + 0, 0, 332, 0, 332, 501, 0, 332, 0, 0, + 0, 0, 0, 332, 0, 0, 0, 0, 0, 325, + 0, 389, 389, 389, 389, 0, 389, 0, 389, 389, + 0, 389, 389, 389, 389, 389, 0, 389, 389, 389, + 389, 501, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 389, 389, 389, 389, 389, 389, + 389, 389, 389, 389, 0, 0, 0, 0, 325, 0, + 389, 332, 0, 389, 0, 0, 0, 0, 0, 389, + 0, 0, 501, 0, 0, 0, 0, 501, 0, 501, + 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, + 0, 0, 0, 0, 0, 0, 0, 332, 0, 0, + 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, + 0, 501, 501, 0, 501, 501, 501, 501, 501, 501, + 501, 501, 501, 501, 0, 501, 501, 501, 501, 501, + 501, 501, 501, 501, 501, 501, 501, 501, 501, 501, + 501, 501, 501, 501, 501, 501, 501, 0, 497, 0, + 0, 0, 0, 501, 497, 0, 332, 0, 0, 0, + 0, 0, 501, 0, 0, 0, 0, 0, 332, 0, + 332, 0, 332, 0, 0, 332, 0, 332, 332, 0, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 497, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 0, 0, 0, 0, 332, 0, 332, + 332, 0, 332, 0, 0, 0, 0, 0, 332, 0, + 0, 497, 0, 0, 0, 0, 497, 0, 497, 497, + 497, 497, 497, 497, 497, 497, 497, 497, 497, 0, + 0, 0, 0, 0, 0, 0, 332, 0, 0, 497, + 497, 0, 497, 497, 497, 497, 497, 497, 497, 0, + 497, 497, 0, 497, 497, 497, 497, 497, 497, 497, + 497, 497, 497, 0, 497, 497, 497, 497, 497, 497, + 497, 497, 497, 497, 497, 497, 497, 497, 497, 497, + 497, 497, 497, 497, 497, 497, 0, 505, 0, 0, + 0, 0, 497, 505, 0, 497, 0, 0, 0, 0, + 0, 497, 0, 0, 0, 0, 0, 0, 332, 332, + 332, 332, 332, 0, 0, 0, 332, 332, 0, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 505, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 0, 0, 0, 0, 0, 0, 332, 0, + 0, 332, 0, 0, 0, 0, 0, 332, 0, 0, + 505, 0, 0, 0, 0, 505, 0, 505, 505, 505, + 505, 505, 505, 505, 505, 505, 505, 505, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 505, + 0, 505, 505, 505, 505, 505, 505, 505, 0, 505, + 505, 0, 505, 505, 505, 505, 505, 505, 505, 505, + 505, 505, 0, 505, 505, 505, 505, 505, 505, 505, + 505, 505, 505, 505, 505, 505, 505, 505, 505, 505, + 505, 505, 505, 505, 505, 0, 332, 876, 0, 0, + 0, 505, 332, 0, 505, 0, 25, 0, 26, 0, + 505, 27, 0, 0, 0, 0, 28, 0, 0, 0, + 29, 0, 0, 0, 0, 0, 0, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 332, 0, + 0, 34, 0, 0, 0, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, + 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, + 0, 40, 41, 0, 0, 42, 0, 0, 319, 332, + 0, 0, 0, 0, 332, 0, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 332, 0, + 332, 332, 332, 332, 332, 332, 332, 0, 332, 332, + 0, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 0, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 0, 432, 1071, 0, 0, 354, + 332, 432, 0, 332, 0, 25, 0, 26, 0, 332, 27, 0, 0, 0, 0, 28, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, - 0, 0, 0, 0, 0, 33, 0, 446, 0, 0, + 0, 0, 0, 0, 0, 33, 0, 432, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, - 40, 41, 0, 0, 42, 0, 0, 739, 446, 0, - 0, 0, 0, 446, 0, 446, 446, 446, 446, 446, - 446, 446, 446, 446, 446, 446, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 446, 0, 446, - 446, 446, 446, 446, 446, 446, 0, 446, 446, 0, - 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, - 0, 446, 446, 446, 446, 446, 446, 446, 446, 446, - 446, 446, 446, 446, 446, 446, 446, 446, 446, 446, - 446, 446, 446, 0, 406, 876, 0, 0, 740, 446, - 406, 0, 446, 0, 25, 0, 26, 0, 446, 27, + 40, 41, 0, 0, 42, 0, 0, 319, 432, 0, + 0, 0, 0, 432, 0, 432, 432, 432, 432, 432, + 432, 432, 432, 432, 432, 432, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 432, 0, 432, + 432, 432, 432, 432, 432, 432, 0, 432, 432, 0, + 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, + 0, 432, 432, 432, 432, 432, 432, 432, 432, 432, + 432, 432, 432, 432, 432, 432, 432, 432, 432, 432, + 432, 432, 432, 0, 392, 1137, 0, 0, 354, 432, + 392, 0, 432, 0, 25, 0, 26, 0, 432, 27, 0, 0, 0, 0, 28, 0, 0, 0, 29, 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, - 0, 0, 0, 0, 33, 0, 406, 0, 0, 34, + 0, 0, 0, 0, 33, 0, 392, 0, 0, 34, 0, 0, 0, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 0, 0, 0, 39, 0, 0, 0, 0, 0, 0, 0, 40, - 41, 0, 0, 42, 0, 0, 319, 406, 0, 0, - 0, 0, 406, 0, 406, 406, 406, 406, 406, 406, - 406, 406, 406, 406, 406, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 406, 0, 406, 406, - 406, 406, 406, 406, 406, 0, 406, 0, 0, 406, - 406, 406, 406, 406, 406, 406, 406, 406, 406, 0, - 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, - 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, - 406, 406, 0, 550, 0, 492, 0, 354, 406, 550, - 0, 406, 0, 57, 25, 0, 26, 406, 0, 27, + 41, 0, 0, 42, 0, 0, 319, 392, 0, 0, + 0, 0, 392, 0, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 392, 0, 392, 392, + 392, 392, 392, 392, 392, 0, 392, 0, 0, 392, + 392, 392, 392, 392, 392, 392, 392, 392, 392, 0, + 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 392, 392, 392, 392, 392, 392, 392, 392, + 392, 392, 0, 536, 0, 492, 0, 354, 392, 536, + 0, 392, 0, 57, 25, 0, 26, 392, 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, 0, 0, 0, 0, 65, 0, 0, 31, 0, 0, - 0, 0, 0, 0, 33, 550, 0, 0, 0, 34, + 0, 0, 0, 0, 33, 536, 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, - 41, 257, 0, 42, 0, 0, 550, 0, 0, 0, - 0, 550, 0, 550, 550, 550, 550, 550, 550, 550, - 550, 550, 550, 550, 0, 0, 0, 0, 90, 91, - 92, 258, 0, 0, 0, 550, 0, 550, 0, 550, - 96, 550, 550, 550, 0, 550, 550, 0, 550, 550, - 550, 550, 550, 550, 550, 550, 550, 550, 368, 0, - 0, 550, 550, 550, 550, 550, 550, 550, 550, 550, - 550, 550, 550, 550, 550, 550, 550, 550, 550, 564, - 550, 368, 0, 0, 0, 564, 106, 493, 0, 0, - 0, 0, 0, 0, 368, 0, 550, 0, 0, 368, - 0, 0, 245, 0, 368, 0, 368, 368, 368, 368, - 0, 0, 0, 0, 368, 0, 0, 0, 368, 0, - 0, 564, 368, 0, 0, 0, 0, 0, 0, 0, - 368, 0, 0, 368, 0, 368, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 568, 0, 0, - 0, 0, 0, 568, 0, 0, 0, 0, 0, 368, - 0, 0, 564, 0, 0, 0, 0, 564, 0, 564, - 564, 564, 564, 564, 564, 564, 564, 564, 564, 564, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 568, - 0, 564, 0, 564, 0, 564, 0, 564, 564, 564, - 0, 564, 564, 0, 0, 564, 564, 564, 564, 564, - 564, 564, 564, 564, 0, 368, 0, 564, 564, 564, - 564, 564, 564, 564, 564, 0, 0, 0, 0, 0, - 568, 0, 0, 0, 0, 568, 564, 568, 568, 568, - 568, 568, 568, 568, 568, 568, 568, 568, 0, 0, - 0, 571, 564, 0, 0, 0, 0, 571, 0, 568, - 0, 568, 0, 568, 0, 568, 568, 568, 0, 568, - 568, 0, 0, 568, 568, 568, 568, 0, 0, 0, - 568, 568, 0, 0, 0, 568, 568, 568, 568, 568, - 568, 568, 568, 571, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 568, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 569, - 568, 0, 0, 0, 0, 569, 0, 0, 0, 0, - 0, 0, 0, 0, 571, 0, 0, 0, 0, 571, - 0, 571, 571, 571, 571, 571, 571, 571, 571, 571, - 571, 571, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 569, 0, 571, 0, 571, 0, 571, 0, 571, - 571, 571, 0, 571, 571, 0, 0, 571, 571, 571, - 571, 0, 0, 0, 571, 571, 0, 0, 0, 571, - 571, 571, 571, 571, 571, 571, 571, 0, 0, 0, - 0, 0, 569, 0, 0, 0, 0, 569, 571, 569, - 569, 569, 569, 569, 569, 569, 569, 569, 569, 569, - 0, 0, 0, 570, 571, 0, 0, 0, 0, 570, - 0, 569, 0, 569, 0, 569, 0, 569, 569, 569, - 0, 569, 569, 0, 0, 569, 569, 569, 569, 0, - 0, 0, 569, 569, 0, 0, 0, 569, 569, 569, - 569, 569, 569, 569, 569, 570, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 569, 0, 0, 0, + 41, 257, 0, 42, 0, 0, 536, 0, 0, 0, + 0, 536, 0, 536, 536, 536, 536, 536, 536, 536, + 536, 536, 536, 536, 0, 0, 0, 0, 90, 91, + 92, 258, 0, 0, 0, 536, 0, 536, 0, 536, + 96, 536, 536, 536, 0, 536, 536, 0, 536, 536, + 536, 536, 536, 536, 536, 536, 536, 536, 354, 0, + 0, 536, 536, 536, 536, 536, 536, 536, 536, 536, + 536, 536, 536, 536, 536, 536, 536, 536, 536, 550, + 536, 354, 0, 0, 0, 550, 106, 493, 0, 0, + 0, 0, 0, 0, 354, 0, 536, 0, 0, 354, + 0, 0, 230, 0, 354, 0, 354, 354, 354, 354, + 0, 0, 0, 0, 354, 0, 0, 0, 354, 0, + 0, 550, 354, 0, 0, 0, 0, 0, 0, 0, + 354, 0, 0, 354, 0, 354, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 554, 0, 0, + 0, 0, 0, 554, 0, 0, 0, 0, 0, 354, + 0, 0, 550, 0, 0, 0, 0, 550, 0, 550, + 550, 550, 550, 550, 550, 550, 550, 550, 550, 550, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 554, + 0, 550, 0, 550, 0, 550, 0, 550, 550, 550, + 0, 550, 550, 0, 0, 550, 550, 550, 550, 550, + 550, 550, 550, 550, 0, 354, 0, 550, 550, 550, + 550, 550, 550, 550, 550, 0, 0, 0, 0, 0, + 554, 0, 0, 0, 0, 554, 550, 554, 554, 554, + 554, 554, 554, 554, 554, 554, 554, 554, 0, 0, + 0, 557, 550, 0, 0, 0, 0, 557, 0, 554, + 0, 554, 0, 554, 0, 554, 554, 554, 0, 554, + 554, 0, 0, 554, 554, 554, 554, 0, 0, 0, + 554, 554, 0, 0, 0, 554, 554, 554, 554, 554, + 554, 554, 554, 557, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 554, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 555, + 554, 0, 0, 0, 0, 555, 0, 0, 0, 0, + 0, 0, 0, 0, 557, 0, 0, 0, 0, 557, + 0, 557, 557, 557, 557, 557, 557, 557, 557, 557, + 557, 557, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 555, 0, 557, 0, 557, 0, 557, 0, 557, + 557, 557, 0, 557, 557, 0, 0, 557, 557, 557, + 557, 0, 0, 0, 557, 557, 204, 0, 0, 557, + 557, 557, 557, 557, 557, 557, 557, 0, 0, 0, + 0, 0, 555, 0, 0, 0, 0, 555, 557, 555, + 555, 555, 555, 555, 555, 555, 555, 555, 555, 555, + 0, 0, 0, 556, 557, 0, 0, 0, 205, 556, + 0, 555, 0, 555, 0, 555, 0, 555, 555, 555, + 0, 555, 555, 0, 0, 555, 555, 555, 555, 0, + 0, 0, 555, 555, 0, 0, 0, 555, 555, 555, + 555, 555, 555, 555, 555, 556, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 555, 0, 206, 207, + 208, 209, 0, 210, 211, 212, 213, 214, 215, 216, + 217, 560, 555, 218, 219, 220, 221, 222, 223, 224, + 225, 0, 0, 0, 0, 0, 556, 0, 0, 0, + 0, 556, 0, 556, 556, 556, 556, 556, 556, 556, + 556, 556, 556, 556, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 556, 0, 556, 0, 556, + 0, 556, 556, 556, 0, 556, 556, 0, 0, 556, + 556, 556, 556, 0, 0, 0, 556, 556, 0, 561, + 0, 556, 556, 556, 556, 556, 556, 556, 556, 0, + 0, 0, 0, 0, 560, 0, 0, 0, 0, 560, + 556, 560, 560, 560, 560, 560, 560, 560, 560, 560, + 560, 560, 0, 0, 0, 0, 556, 0, 0, 0, + 0, 0, 0, 560, 0, 560, 0, 560, 0, 560, + 560, 560, 0, 0, 0, 0, 0, 560, 560, 560, + 560, 0, 0, 0, 560, 560, 0, 562, 0, 560, + 560, 560, 560, 560, 560, 560, 560, 0, 0, 0, + 0, 0, 561, 0, 0, 0, 0, 561, 560, 561, + 561, 561, 561, 561, 561, 561, 561, 561, 561, 561, + 0, 0, 0, 0, 560, 0, 0, 0, 0, 0, + 0, 561, 0, 561, 0, 561, 0, 561, 561, 561, + 0, 0, 0, 0, 0, 561, 561, 561, 561, 0, + 0, 0, 561, 561, 0, 563, 0, 561, 561, 561, + 561, 561, 561, 561, 561, 0, 0, 0, 0, 0, + 562, 0, 0, 0, 0, 562, 561, 562, 562, 562, + 562, 562, 562, 562, 562, 562, 562, 562, 0, 0, + 0, 0, 561, 0, 0, 0, 0, 0, 0, 562, + 0, 562, 0, 562, 0, 562, 562, 562, 0, 0, + 0, 0, 0, 562, 562, 562, 562, 0, 0, 0, + 562, 562, 0, 564, 0, 562, 562, 562, 562, 562, + 562, 562, 562, 0, 0, 0, 0, 0, 563, 0, + 0, 0, 0, 563, 562, 563, 563, 563, 563, 563, + 563, 563, 563, 563, 563, 563, 0, 0, 0, 0, + 562, 0, 0, 0, 0, 0, 0, 563, 0, 563, + 0, 563, 0, 563, 563, 563, 0, 0, 0, 0, + 0, 563, 563, 563, 563, 0, 0, 0, 563, 563, + 0, 565, 0, 0, 0, 563, 563, 563, 563, 563, + 563, 0, 0, 0, 0, 0, 564, 0, 0, 0, + 0, 564, 563, 564, 564, 564, 564, 564, 564, 564, + 564, 564, 564, 564, 0, 0, 0, 0, 563, 0, + 0, 0, 0, 0, 0, 564, 0, 564, 0, 564, + 0, 564, 564, 564, 0, 0, 0, 0, 0, 564, + 564, 564, 564, 0, 0, 0, 564, 564, 0, 566, + 0, 0, 0, 564, 564, 564, 564, 564, 564, 0, + 0, 0, 0, 0, 565, 0, 0, 0, 0, 565, + 564, 565, 565, 565, 565, 565, 565, 565, 565, 565, + 565, 565, 0, 0, 0, 0, 564, 0, 0, 0, + 0, 0, 0, 565, 0, 565, 0, 565, 0, 565, + 565, 565, 0, 0, 0, 0, 0, 565, 565, 565, + 565, 0, 0, 0, 565, 565, 0, 567, 0, 0, + 0, 565, 565, 565, 565, 565, 565, 0, 0, 0, + 0, 0, 566, 0, 0, 0, 0, 566, 565, 566, + 566, 566, 566, 566, 566, 566, 566, 566, 566, 566, + 0, 0, 0, 0, 565, 0, 0, 0, 0, 0, + 0, 566, 0, 566, 0, 566, 0, 566, 566, 566, + 0, 0, 0, 0, 0, 566, 566, 566, 566, 0, + 0, 0, 566, 566, 0, 568, 0, 0, 0, 566, + 566, 566, 566, 566, 566, 0, 0, 0, 0, 0, + 567, 0, 0, 0, 0, 567, 566, 567, 567, 567, + 567, 567, 567, 567, 567, 567, 567, 567, 0, 0, + 0, 0, 566, 0, 0, 0, 0, 0, 0, 567, + 0, 567, 0, 567, 0, 567, 567, 567, 0, 0, + 0, 0, 0, 567, 567, 567, 567, 0, 0, 0, + 567, 567, 0, 569, 0, 0, 0, 567, 567, 567, + 567, 567, 567, 0, 0, 0, 0, 0, 568, 0, + 0, 0, 0, 568, 567, 568, 568, 568, 568, 568, + 568, 568, 568, 568, 568, 568, 0, 0, 0, 0, + 567, 0, 0, 0, 0, 0, 0, 568, 0, 568, + 0, 568, 0, 568, 568, 568, 0, 0, 0, 0, + 0, 0, 0, 568, 568, 0, 0, 0, 568, 568, + 0, 570, 0, 0, 0, 0, 0, 568, 568, 568, + 568, 0, 0, 0, 0, 0, 569, 0, 0, 0, + 0, 569, 568, 569, 569, 569, 569, 569, 569, 569, + 569, 569, 569, 569, 0, 0, 0, 0, 568, 0, + 0, 0, 0, 0, 0, 569, 0, 569, 0, 569, + 0, 569, 569, 569, 0, 0, 0, 0, 0, 0, + 0, 569, 569, 0, 0, 0, 569, 569, 0, 571, + 0, 0, 0, 0, 0, 569, 569, 569, 569, 0, + 0, 0, 0, 0, 570, 0, 0, 0, 0, 570, + 569, 570, 570, 570, 570, 570, 570, 570, 570, 570, + 570, 570, 0, 0, 0, 0, 569, 0, 0, 0, + 0, 0, 0, 570, 0, 570, 0, 570, 0, 570, + 570, 570, 0, 0, 0, 0, 0, 0, 0, 570, + 570, 0, 0, 0, 570, 570, 0, 572, 0, 0, + 0, 0, 0, 570, 570, 570, 570, 0, 0, 0, + 0, 0, 571, 0, 0, 0, 0, 571, 570, 571, + 571, 571, 571, 571, 571, 571, 571, 571, 571, 571, + 0, 0, 0, 0, 570, 0, 0, 0, 0, 0, + 0, 571, 0, 571, 0, 571, 0, 571, 571, 571, + 0, 0, 0, 0, 0, 0, 0, 571, 571, 0, + 0, 0, 571, 571, 0, 573, 0, 0, 0, 0, + 0, 0, 0, 571, 571, 0, 0, 0, 0, 0, + 572, 0, 0, 0, 0, 572, 571, 572, 572, 572, + 572, 572, 572, 572, 572, 572, 572, 572, 0, 0, + 0, 0, 571, 0, 0, 0, 0, 0, 0, 572, + 0, 572, 0, 572, 0, 572, 572, 572, 0, 0, + 0, 0, 0, 0, 0, 572, 572, 0, 0, 0, + 572, 572, 0, 574, 0, 0, 0, 0, 0, 0, + 0, 572, 572, 0, 0, 0, 0, 0, 573, 0, + 0, 0, 0, 573, 572, 573, 573, 573, 573, 573, + 573, 573, 573, 573, 573, 573, 0, 0, 0, 0, + 572, 0, 0, 0, 0, 0, 0, 573, 0, 573, + 0, 573, 0, 573, 573, 573, 0, 0, 0, 0, + 0, 0, 0, 0, 573, 0, 0, 0, 573, 573, + 0, 575, 0, 0, 0, 0, 0, 0, 0, 573, + 573, 0, 0, 0, 0, 0, 574, 0, 0, 0, + 0, 574, 573, 574, 574, 574, 574, 574, 574, 574, + 574, 574, 574, 574, 0, 0, 0, 0, 573, 0, + 0, 0, 0, 0, 0, 574, 0, 574, 0, 574, + 0, 574, 574, 574, 0, 0, 0, 0, 0, 0, + 0, 0, 574, 0, 0, 0, 574, 574, 0, 576, + 0, 0, 0, 0, 0, 0, 0, 574, 574, 0, + 0, 0, 0, 0, 575, 0, 0, 0, 0, 575, + 574, 575, 575, 575, 575, 575, 575, 575, 575, 575, + 575, 575, 0, 0, 0, 0, 574, 0, 0, 0, + 0, 0, 0, 575, 0, 575, 0, 575, 0, 575, + 575, 575, 0, 0, 0, 0, 0, 0, 0, 0, + 575, 0, 0, 0, 0, 575, 0, 577, 0, 0, + 0, 0, 0, 0, 0, 575, 575, 0, 0, 0, + 0, 0, 576, 0, 0, 0, 0, 576, 575, 576, + 576, 576, 576, 576, 576, 576, 576, 576, 576, 576, + 0, 0, 0, 0, 575, 0, 0, 0, 0, 0, + 0, 576, 0, 576, 0, 576, 0, 576, 576, 576, + 0, 0, 0, 0, 0, 0, 0, 0, 576, 0, + 0, 0, 0, 576, 0, 578, 0, 0, 0, 0, + 0, 0, 0, 576, 576, 0, 0, 0, 0, 0, + 577, 0, 0, 0, 0, 577, 576, 577, 577, 577, + 577, 577, 577, 577, 577, 577, 577, 577, 0, 0, + 0, 0, 576, 0, 0, 0, 0, 0, 0, 577, + 0, 577, 0, 577, 0, 577, 577, 577, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 574, 569, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 570, 0, 0, 0, - 0, 570, 0, 570, 570, 570, 570, 570, 570, 570, - 570, 570, 570, 570, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 570, 0, 570, 0, 570, - 0, 570, 570, 570, 0, 570, 570, 0, 0, 570, - 570, 570, 570, 0, 0, 0, 570, 570, 0, 575, - 0, 570, 570, 570, 570, 570, 570, 570, 570, 0, - 0, 0, 0, 0, 574, 0, 0, 0, 0, 574, - 570, 574, 574, 574, 574, 574, 574, 574, 574, 574, - 574, 574, 0, 0, 0, 0, 570, 0, 0, 0, - 0, 0, 0, 574, 0, 574, 0, 574, 0, 574, - 574, 574, 0, 0, 0, 0, 0, 574, 574, 574, - 574, 0, 0, 0, 574, 574, 0, 576, 0, 574, - 574, 574, 574, 574, 574, 574, 574, 0, 0, 0, - 0, 0, 575, 0, 0, 0, 0, 575, 574, 575, - 575, 575, 575, 575, 575, 575, 575, 575, 575, 575, - 0, 0, 0, 0, 574, 0, 0, 0, 0, 0, - 0, 575, 0, 575, 0, 575, 0, 575, 575, 575, - 0, 0, 0, 0, 0, 575, 575, 575, 575, 0, - 0, 0, 575, 575, 0, 577, 0, 575, 575, 575, - 575, 575, 575, 575, 575, 0, 0, 0, 0, 0, - 576, 0, 0, 0, 0, 576, 575, 576, 576, 576, - 576, 576, 576, 576, 576, 576, 576, 576, 0, 0, - 0, 0, 575, 0, 0, 0, 0, 0, 0, 576, - 0, 576, 0, 576, 0, 576, 576, 576, 0, 0, - 0, 0, 0, 576, 576, 576, 576, 0, 0, 0, - 576, 576, 0, 578, 0, 576, 576, 576, 576, 576, - 576, 576, 576, 0, 0, 0, 0, 0, 577, 0, - 0, 0, 0, 577, 576, 577, 577, 577, 577, 577, - 577, 577, 577, 577, 577, 577, 0, 0, 0, 0, - 576, 0, 0, 0, 0, 0, 0, 577, 0, 577, - 0, 577, 0, 577, 577, 577, 0, 0, 0, 0, - 0, 577, 577, 577, 577, 0, 0, 0, 577, 577, - 0, 579, 0, 0, 0, 577, 577, 577, 577, 577, - 577, 0, 0, 0, 0, 0, 578, 0, 0, 0, - 0, 578, 577, 578, 578, 578, 578, 578, 578, 578, - 578, 578, 578, 578, 0, 0, 0, 0, 577, 0, - 0, 0, 0, 0, 0, 578, 0, 578, 0, 578, - 0, 578, 578, 578, 0, 0, 0, 0, 0, 578, - 578, 578, 578, 0, 0, 0, 578, 578, 0, 580, - 0, 0, 0, 578, 578, 578, 578, 578, 578, 0, - 0, 0, 0, 0, 579, 0, 0, 0, 0, 579, - 578, 579, 579, 579, 579, 579, 579, 579, 579, 579, - 579, 579, 0, 0, 0, 0, 578, 0, 0, 0, - 0, 0, 0, 579, 0, 579, 0, 579, 0, 579, - 579, 579, 0, 0, 0, 0, 0, 579, 579, 579, - 579, 0, 0, 0, 579, 579, 0, 581, 0, 0, - 0, 579, 579, 579, 579, 579, 579, 0, 0, 0, + 0, 577, 0, 579, 0, 0, 0, 0, 0, 0, + 0, 577, 577, 0, 0, 0, 0, 0, 578, 0, + 0, 0, 0, 578, 577, 578, 578, 578, 578, 578, + 578, 578, 578, 578, 578, 578, 0, 0, 0, 0, + 577, 0, 0, 0, 0, 0, 0, 578, 0, 578, + 0, 578, 0, 578, 578, 578, 0, 0, 0, 580, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 578, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 578, + 578, 0, 0, 0, 0, 0, 579, 0, 0, 0, + 0, 579, 578, 579, 579, 579, 579, 579, 579, 579, + 579, 579, 579, 579, 0, 0, 0, 0, 578, 0, + 0, 0, 0, 0, 0, 579, 0, 579, 0, 579, + 0, 579, 579, 579, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 579, 0, 0, 0, 0, 580, 0, 0, 0, 0, 580, 579, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, 580, - 0, 0, 0, 0, 579, 0, 0, 0, 0, 0, - 0, 580, 0, 580, 0, 580, 0, 580, 580, 580, - 0, 0, 0, 0, 0, 580, 580, 580, 580, 0, - 0, 0, 580, 580, 0, 582, 0, 0, 0, 580, - 580, 580, 580, 580, 580, 0, 0, 0, 0, 0, - 581, 0, 0, 0, 0, 581, 580, 581, 581, 581, - 581, 581, 581, 581, 581, 581, 581, 581, 0, 0, - 0, 0, 580, 0, 0, 0, 0, 0, 0, 581, - 0, 581, 0, 581, 0, 581, 581, 581, 0, 0, - 0, 0, 0, 581, 581, 581, 581, 0, 0, 0, - 581, 581, 0, 583, 0, 0, 0, 581, 581, 581, - 581, 581, 581, 0, 0, 0, 0, 0, 582, 0, - 0, 0, 0, 582, 581, 582, 582, 582, 582, 582, - 582, 582, 582, 582, 582, 582, 0, 0, 0, 0, - 581, 0, 0, 0, 0, 0, 0, 582, 0, 582, - 0, 582, 0, 582, 582, 582, 0, 0, 0, 0, - 0, 0, 0, 582, 582, 0, 0, 0, 582, 582, - 0, 584, 0, 0, 0, 0, 0, 582, 582, 582, - 582, 0, 0, 0, 0, 0, 583, 0, 0, 0, - 0, 583, 582, 583, 583, 583, 583, 583, 583, 583, - 583, 583, 583, 583, 0, 0, 0, 0, 582, 0, - 0, 0, 0, 0, 0, 583, 0, 583, 0, 583, - 0, 583, 583, 583, 0, 0, 0, 0, 0, 0, - 0, 583, 583, 0, 0, 0, 583, 583, 0, 586, - 0, 0, 0, 0, 0, 583, 583, 583, 583, 0, - 0, 0, 0, 0, 584, 0, 0, 0, 0, 584, - 583, 584, 584, 584, 584, 584, 584, 584, 584, 584, - 584, 584, 0, 0, 0, 0, 583, 0, 0, 0, - 0, 0, 0, 584, 0, 584, 0, 584, 0, 584, - 584, 584, 0, 0, 0, 0, 0, 0, 0, 584, - 584, 0, 0, 0, 584, 584, 0, 587, 0, 0, - 0, 0, 0, 584, 584, 584, 584, 0, 0, 0, - 0, 0, 586, 0, 0, 0, 0, 586, 584, 586, - 586, 586, 586, 586, 586, 586, 586, 586, 586, 586, - 0, 0, 0, 0, 584, 0, 0, 0, 0, 0, - 0, 586, 0, 586, 0, 586, 0, 586, 586, 586, - 0, 0, 0, 0, 0, 0, 0, 586, 586, 0, - 0, 0, 586, 586, 0, 588, 0, 0, 0, 0, - 0, 0, 0, 586, 586, 0, 0, 0, 0, 0, - 587, 0, 0, 0, 0, 587, 586, 587, 587, 587, - 587, 587, 587, 587, 587, 587, 587, 587, 0, 0, - 0, 0, 586, 0, 0, 0, 0, 0, 0, 587, - 0, 587, 0, 587, 0, 587, 587, 587, 0, 0, - 0, 0, 0, 0, 0, 0, 587, 0, 0, 0, - 587, 587, 0, 589, 0, 0, 0, 0, 0, 0, - 0, 587, 587, 0, 0, 0, 0, 0, 588, 0, - 0, 0, 0, 588, 587, 588, 588, 588, 588, 588, - 588, 588, 588, 588, 588, 588, 0, 0, 0, 0, - 587, 0, 0, 0, 0, 0, 0, 588, 0, 588, - 0, 588, 0, 588, 588, 588, 0, 0, 0, 0, - 0, 0, 0, 0, 588, 0, 0, 0, 588, 588, - 0, 590, 0, 0, 0, 0, 0, 0, 0, 588, - 588, 0, 0, 0, 0, 0, 589, 0, 0, 0, - 0, 589, 588, 589, 589, 589, 589, 589, 589, 589, - 589, 589, 589, 589, 0, 0, 0, 0, 588, 0, - 0, 0, 0, 0, 0, 589, 0, 589, 0, 589, - 0, 589, 589, 589, 0, 0, 0, 0, 0, 0, - 0, 0, 589, 0, 0, 0, 0, 589, 0, 591, - 0, 0, 0, 0, 0, 0, 0, 589, 589, 0, - 0, 0, 0, 0, 590, 0, 0, 0, 0, 590, - 589, 590, 590, 590, 590, 590, 590, 590, 590, 590, - 590, 590, 0, 0, 0, 0, 589, 0, 0, 0, - 0, 0, 0, 590, 0, 590, 0, 590, 0, 590, - 590, 590, 0, 0, 0, 0, 0, 0, 0, 0, - 590, 0, 0, 0, 0, 590, 0, 592, 0, 0, - 0, 0, 0, 0, 0, 590, 590, 0, 0, 0, - 0, 0, 591, 0, 0, 0, 0, 591, 590, 591, - 591, 591, 591, 591, 591, 591, 591, 591, 591, 591, - 0, 0, 0, 0, 590, 0, 0, 0, 0, 0, - 0, 591, 0, 591, 0, 591, 0, 591, 591, 591, + 579, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 580, 0, 580, 0, 580, 579, 580, 580, 580, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 591, 0, 593, 0, 0, 0, 0, - 0, 0, 0, 591, 591, 0, 0, 0, 0, 0, - 592, 0, 0, 0, 0, 592, 591, 592, 592, 592, - 592, 592, 592, 592, 592, 592, 592, 592, 0, 0, - 0, 0, 591, 0, 0, 0, 0, 0, 0, 592, - 0, 592, 0, 592, 0, 592, 592, 592, 0, 0, - 0, 594, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 592, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 592, 592, 0, 0, 0, 0, 0, 593, 0, - 0, 0, 0, 593, 592, 593, 593, 593, 593, 593, - 593, 593, 593, 593, 593, 593, 0, 0, 0, 0, - 592, 0, 0, 0, 0, 0, 0, 593, 0, 593, - 0, 593, 0, 593, 593, 593, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 593, - 0, 0, 0, 0, 594, 0, 0, 0, 0, 594, - 593, 594, 594, 594, 594, 594, 594, 594, 594, 594, - 594, 594, 593, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 594, 0, 594, 0, 594, 593, 594, - 594, 594, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 56, 0, 594, 0, 0, 0, 0, - 0, 57, 25, 58, 26, 0, 594, 27, 59, 0, - 60, 61, 28, 62, 63, 64, 29, 0, 594, 0, - 0, 0, 65, 0, 66, 31, 67, 68, 69, 70, - 0, 0, 33, 0, 594, 0, 71, 34, 0, 72, - 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 74, 0, 37, 0, 38, 75, 0, 0, 39, - 0, 76, 77, 78, 79, 80, 81, 40, 41, 82, - 83, 42, 84, 0, 85, 0, 0, 86, 87, 0, - 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, - 94, 0, 0, 0, 95, 0, 0, 0, 96, 0, - 0, 0, 0, 97, 98, 99, 100, 101, 0, 0, - 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, - 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 56, 0, 580, 0, 0, 0, 0, 0, 57, + 25, 58, 26, 0, 580, 27, 59, 0, 60, 61, + 28, 62, 63, 64, 29, 0, 580, 0, 0, 0, + 65, 0, 66, 31, 67, 68, 69, 70, 0, 0, + 33, 0, 580, 0, 71, 34, 0, 72, 73, 35, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 74, + 0, 37, 0, 38, 75, 0, 0, 39, 0, 76, + 77, 78, 79, 80, 81, 40, 41, 82, 83, 42, + 84, 0, 85, 0, 0, 86, 87, 0, 0, 88, + 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, + 0, 0, 95, 0, 0, 0, 96, 0, 0, 0, + 0, 97, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 268, 0, 0, 0, 106, 107, 108, 109, 57, 25, - 58, 26, 0, 0, 27, 59, 0, 60, 61, 28, - 62, 63, 64, 29, 0, 0, 0, 0, 0, 65, - 0, 66, 31, 67, 68, 69, 70, 0, 0, 33, - 0, 0, 0, 71, 34, 0, 72, 73, 35, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 74, 0, - 37, 0, 38, 75, 0, 0, 39, 0, 76, 77, - 78, 79, 80, 81, 40, 41, 82, 83, 42, 84, - 0, 85, 0, 0, 86, 87, 0, 0, 88, 89, + 0, 0, 0, 0, 0, 0, 0, 0, 268, 0, + 0, 0, 106, 107, 108, 109, 57, 25, 58, 26, + 0, 0, 27, 59, 0, 60, 61, 28, 62, 63, + 64, 29, 0, 0, 0, 0, 0, 65, 0, 66, + 31, 67, 68, 69, 70, 0, 0, 33, 0, 0, + 0, 71, 34, 0, 72, 73, 35, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 74, 0, 37, 0, + 38, 75, 0, 0, 39, 0, 76, 77, 78, 79, + 80, 81, 40, 41, 82, 83, 42, 84, 0, 85, + 0, 0, 86, 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, - 0, 95, 0, 0, 0, 96, 0, 0, 0, 0, - 97, 98, 99, 100, 101, 0, 0, 0, 102, 0, - 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, + 0, 90, 91, 92, 93, 94, 0, 0, 0, 95, + 0, 0, 0, 96, 0, 0, 0, 0, 97, 98, + 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, + 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 547, 0, 0, 0, 106, + 107, 108, 109, 57, 25, 58, 26, 0, 0, 27, + 59, 0, 60, 61, 28, 62, 63, 64, 29, 0, + 0, 0, 0, 0, 65, 0, 66, 31, 67, 68, + 69, 70, 0, 0, 33, 0, 0, 0, 71, 34, + 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 74, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 76, 77, 78, 79, 80, 81, 40, + 41, 82, 83, 42, 84, 0, 85, 0, 0, 86, + 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, + 92, 93, 94, 0, 0, 0, 95, 0, 0, 0, + 96, 0, 0, 0, 0, 97, 98, 99, 100, 101, + 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, + 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 547, 0, 0, - 0, 106, 107, 108, 109, 57, 25, 58, 26, 0, - 0, 27, 59, 0, 60, 61, 28, 62, 63, 64, - 29, 0, 0, 0, 0, 0, 65, 0, 66, 31, - 67, 68, 69, 70, 0, 0, 33, 0, 0, 0, - 71, 34, 0, 72, 73, 35, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 74, 0, 37, 0, 38, - 75, 0, 0, 39, 0, 76, 77, 78, 79, 80, - 81, 40, 41, 82, 83, 42, 84, 0, 85, 0, - 0, 86, 87, 0, 0, 88, 89, 0, 0, 0, + 0, 0, 916, 0, 0, 0, 106, 107, 108, 109, + 916, 916, 916, 916, 0, 0, 916, 916, 0, 916, + 916, 916, 916, 916, 916, 916, 0, 0, 0, 0, + 0, 916, 0, 916, 916, 916, 916, 916, 916, 0, + 0, 916, 0, 0, 0, 916, 916, 0, 916, 916, + 916, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 916, 0, 916, 0, 916, 916, 0, 0, 916, 0, + 916, 916, 916, 916, 916, 916, 916, 916, 916, 916, + 916, 916, 0, 916, 0, 0, 916, 916, 0, 0, + 916, 916, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 916, 916, 916, 916, 916, + 0, 0, 0, 916, 0, 0, 0, 916, 0, 0, + 0, 0, 916, 916, 916, 916, 916, 0, 0, 0, + 916, 0, 916, 0, 0, 0, 0, 0, 916, 916, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 90, 91, 92, 93, 94, 0, 0, 0, 95, 0, - 0, 0, 96, 0, 0, 0, 0, 97, 98, 99, - 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, - 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 780, + 0, 0, 0, 916, 916, 916, 916, 780, 780, 780, + 780, 0, 0, 780, 780, 0, 780, 780, 780, 780, + 780, 780, 780, 0, 0, 0, 0, 0, 780, 0, + 780, 780, 780, 780, 780, 780, 0, 0, 780, 0, + 0, 0, 780, 780, 0, 780, 780, 780, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 780, 0, 780, + 0, 780, 780, 0, 0, 780, 0, 780, 780, 780, + 780, 780, 780, 780, 780, 780, 780, 780, 780, 0, + 780, 0, 0, 780, 780, 0, 0, 780, 780, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 780, 780, 780, 780, 780, 0, 0, 0, + 780, 0, 0, 0, 780, 0, 0, 0, 0, 780, + 780, 780, 780, 780, 0, 0, 0, 780, 0, 780, + 0, 0, 0, 0, 0, 780, 780, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 725, 0, 0, 0, + 780, 780, 780, 780, 57, 25, 0, 26, 0, 0, + 27, 256, 0, 0, 0, 28, 62, 63, 0, 29, + 0, 0, 172, 0, 172, 65, 0, 172, 31, 0, + 0, 0, 172, 0, 0, 33, 172, 0, 0, 0, + 34, 0, 72, 73, 35, 172, 0, 0, 0, 0, + 0, 0, 172, 0, 0, 0, 37, 172, 38, 75, + 0, 172, 39, 0, 0, 77, 0, 79, 0, 81, + 40, 41, 257, 172, 42, 172, 0, 0, 0, 172, + 0, 87, 0, 0, 88, 89, 0, 172, 172, 0, + 0, 172, 0, 0, 172, 0, 0, 0, 0, 90, + 91, 92, 93, 94, 0, 0, 0, 509, 726, 0, + 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, + 101, 0, 0, 0, 102, 0, 103, 0, 0, 940, + 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 928, 0, 0, 0, 106, 107, - 108, 109, 928, 928, 928, 928, 0, 0, 928, 928, - 0, 928, 928, 928, 928, 928, 928, 928, 0, 0, - 0, 0, 0, 928, 0, 928, 928, 928, 928, 928, - 928, 0, 0, 928, 0, 0, 0, 928, 928, 0, - 928, 928, 928, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 928, 0, 928, 0, 928, 928, 0, 0, - 928, 0, 928, 928, 928, 928, 928, 928, 928, 928, - 928, 928, 928, 928, 0, 928, 0, 0, 928, 928, - 0, 0, 928, 928, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 928, 928, 928, - 928, 928, 0, 0, 0, 928, 0, 0, 0, 928, - 0, 0, 0, 0, 928, 928, 928, 928, 928, 0, - 0, 0, 928, 0, 928, 0, 0, 0, 0, 0, - 928, 928, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 725, 0, 0, 0, 106, 301, 108, + 109, 57, 25, 0, 26, 0, 0, 27, 256, 0, + 0, 0, 28, 62, 63, 172, 29, 0, 0, 172, + 0, 172, 65, 0, 172, 31, 0, 0, 0, 172, + 0, 0, 33, 172, 0, 0, 0, 34, 0, 72, + 73, 35, 172, 0, 0, 0, 0, 0, 0, 172, + 0, 0, 0, 37, 172, 38, 75, 906, 172, 39, + 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, + 172, 42, 172, 0, 0, 0, 172, 0, 87, 0, + 0, 88, 89, 0, 172, 172, 0, 0, 172, 0, + 0, 172, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 509, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 940, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, + 26, 0, 0, 27, 256, 0, 0, 0, 28, 62, + 63, 0, 29, 0, 106, 301, 108, 109, 65, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 0, 172, 34, 0, 72, 73, 35, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, + 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, + 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, + 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 792, 0, 0, 0, 928, 928, 928, 928, 792, - 792, 792, 792, 0, 0, 792, 792, 0, 792, 792, - 792, 792, 792, 792, 792, 0, 0, 0, 0, 0, - 792, 0, 792, 792, 792, 792, 792, 792, 0, 0, - 792, 0, 0, 0, 792, 792, 0, 792, 792, 792, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 792, - 0, 792, 0, 792, 792, 0, 0, 792, 0, 792, - 792, 792, 792, 792, 792, 792, 792, 792, 792, 792, - 792, 0, 792, 0, 0, 792, 792, 0, 0, 792, - 792, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 792, 792, 792, 792, 792, 0, - 0, 0, 792, 0, 0, 0, 792, 0, 0, 0, - 0, 792, 792, 792, 792, 792, 0, 0, 0, 792, - 0, 792, 0, 0, 0, 0, 0, 792, 792, 0, + 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, + 712, 974, 0, 0, 96, 0, 0, 0, 0, 0, + 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, + 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 725, 0, - 0, 0, 792, 792, 792, 792, 57, 25, 0, 26, - 0, 0, 27, 256, 0, 1018, 0, 28, 62, 63, + 0, 0, 0, 0, 0, 0, 0, 0, 695, 0, + 106, 713, 108, 109, 0, 0, 57, 25, 0, 26, + 0, 714, 27, 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, 0, 25, 0, 26, 65, 0, 27, 31, 0, 0, 0, 28, 0, 0, 33, 29, 0, 0, 0, 34, 0, 72, 73, 35, 31, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 37, 34, 38, 75, 0, 35, 39, 0, 0, 77, 0, 79, - 0, 81, 40, 41, 257, 37, 42, 38, 0, 0, + 0, 81, 40, 41, 257, 37, 42, 38, 0, 85, 0, 39, 0, 87, 0, 0, 88, 89, 0, 40, 41, 0, 0, 42, 0, 0, 319, 0, 0, 0, - 0, 90, 91, 92, 93, 94, 0, 0, 0, 509, - 726, 0, 0, 96, 0, 0, 0, 0, 0, 98, + 0, 90, 91, 92, 93, 94, 0, 0, 0, 0, + 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, + 0, 0, 57, 25, 0, 26, 0, 0, 27, 256, + 0, 0, 0, 28, 62, 63, 0, 29, 0, 106, + 301, 108, 109, 65, 0, 0, 31, 0, 0, 0, + 0, 0, 0, 33, 0, 0, 0, 320, 34, 0, + 72, 73, 35, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 37, 0, 38, 75, 0, 0, + 39, 0, 0, 77, 0, 79, 0, 81, 40, 41, + 257, 0, 42, 0, 0, 0, 0, 0, 0, 87, + 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, + 93, 94, 0, 0, 0, 712, 0, 0, 0, 96, + 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, + 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, + 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 725, 0, 0, 0, 106, - 301, 108, 109, 57, 25, 0, 26, 0, 0, 27, - 256, 0, 1139, 0, 28, 62, 63, 354, 29, 0, - 0, 25, 0, 26, 65, 0, 27, 31, 0, 0, - 0, 28, 0, 0, 33, 29, 0, 0, 0, 34, - 0, 72, 73, 35, 31, 0, 0, 0, 0, 0, - 0, 33, 0, 0, 0, 37, 34, 38, 75, 906, - 35, 39, 0, 0, 77, 0, 79, 0, 81, 40, - 41, 257, 37, 42, 38, 0, 0, 0, 39, 0, - 87, 0, 0, 88, 89, 0, 40, 41, 0, 0, - 42, 0, 0, 319, 0, 0, 0, 0, 90, 91, - 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, - 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, - 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, - 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, - 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, - 28, 62, 63, 0, 29, 0, 106, 301, 108, 109, - 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, - 33, 0, 0, 0, 354, 34, 0, 72, 73, 35, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, - 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, - 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, - 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, - 0, 0, 712, 975, 0, 0, 96, 0, 0, 0, - 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, - 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 725, 0, 106, 713, 108, 109, 0, + 0, 57, 25, 0, 26, 0, 714, 27, 256, 0, + 0, 0, 28, 62, 63, 0, 29, 0, 0, 25, + 0, 26, 65, 0, 27, 31, 0, 0, 0, 28, + 0, 0, 33, 29, 0, 0, 0, 34, 0, 72, + 73, 35, 31, 0, 0, 0, 0, 0, 0, 33, + 0, 0, 0, 37, 34, 38, 75, 0, 35, 39, + 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, + 37, 42, 38, 0, 0, 0, 39, 0, 87, 0, + 0, 88, 89, 0, 40, 41, 0, 0, 42, 0, + 0, 319, 0, 0, 0, 0, 90, 91, 92, 93, + 94, 0, 0, 0, 509, 0, 0, 0, 96, 0, + 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 695, 0, 106, 713, 108, 109, 0, 0, 57, 25, - 0, 26, 0, 714, 27, 256, 0, 0, 0, 28, - 62, 63, 0, 29, 0, 0, 187, 0, 187, 65, - 0, 187, 31, 0, 0, 0, 187, 0, 0, 33, - 187, 0, 0, 0, 34, 0, 72, 73, 35, 187, - 0, 0, 0, 0, 0, 0, 187, 0, 0, 0, - 37, 187, 38, 75, 0, 187, 39, 0, 0, 77, - 0, 79, 0, 81, 40, 41, 257, 187, 42, 187, - 0, 85, 0, 187, 0, 87, 0, 0, 88, 89, - 0, 187, 187, 0, 0, 187, 0, 0, 187, 0, + 894, 0, 0, 0, 106, 301, 108, 109, 57, 25, + 0, 26, 0, 0, 27, 256, 0, 0, 0, 28, + 62, 63, 326, 29, 0, 0, 25, 0, 26, 65, + 0, 27, 31, 0, 0, 0, 28, 0, 0, 33, + 29, 0, 0, 0, 34, 0, 72, 73, 35, 31, + 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, + 37, 34, 38, 75, 0, 35, 39, 0, 0, 77, + 0, 79, 0, 81, 40, 41, 257, 37, 42, 38, + 0, 0, 0, 39, 0, 87, 0, 0, 88, 89, + 0, 40, 41, 0, 0, 42, 0, 0, 319, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, - 103, 0, 0, 952, 0, 0, 104, 105, 0, 0, - 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, - 27, 256, 0, 0, 0, 28, 62, 63, 0, 29, - 0, 106, 301, 108, 109, 65, 0, 0, 31, 0, - 0, 0, 0, 0, 0, 33, 0, 0, 0, 187, - 34, 0, 72, 73, 35, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 37, 0, 38, 75, - 0, 0, 39, 0, 0, 77, 0, 79, 0, 81, - 40, 41, 257, 0, 42, 0, 0, 0, 0, 0, - 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, - 91, 92, 93, 94, 0, 0, 0, 712, 0, 0, - 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, - 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, - 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 725, 0, 106, 713, 108, - 109, 0, 0, 57, 25, 0, 26, 0, 714, 27, - 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, - 0, 187, 0, 187, 65, 0, 187, 31, 0, 0, - 0, 187, 0, 0, 33, 187, 0, 0, 0, 34, - 0, 72, 73, 35, 187, 0, 0, 0, 0, 0, - 0, 187, 0, 0, 0, 37, 187, 38, 75, 0, - 187, 39, 0, 0, 77, 0, 79, 0, 81, 40, - 41, 257, 187, 42, 187, 0, 0, 0, 187, 0, - 87, 0, 0, 88, 89, 0, 187, 187, 0, 0, - 187, 0, 0, 187, 0, 0, 0, 0, 90, 91, - 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, - 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, - 0, 0, 0, 102, 0, 103, 952, 0, 0, 0, - 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 894, 0, 0, 0, 106, 301, 108, 109, - 57, 25, 0, 26, 0, 0, 27, 256, 0, 0, - 0, 28, 62, 63, 187, 29, 0, 0, 25, 0, - 26, 65, 0, 27, 31, 0, 0, 0, 28, 0, - 0, 33, 29, 0, 0, 0, 34, 0, 72, 73, - 35, 31, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 37, 34, 38, 75, 0, 35, 39, 0, - 0, 77, 0, 79, 0, 81, 40, 41, 257, 37, - 42, 38, 0, 0, 0, 39, 0, 87, 0, 0, - 88, 89, 0, 40, 41, 0, 0, 42, 0, 0, - 319, 0, 0, 0, 0, 90, 91, 92, 93, 94, - 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, - 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, - 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 619, - 0, 0, 0, 106, 301, 108, 109, 619, 619, 0, - 619, 0, 0, 619, 619, 0, 0, 0, 619, 619, - 619, 320, 619, 0, 0, 0, 0, 0, 619, 0, - 0, 619, 0, 0, 0, 0, 0, 0, 619, 0, - 0, 0, 0, 619, 0, 619, 619, 619, 0, 0, - 0, 0, 0, 0, 0, 346, 0, 0, 0, 619, - 0, 619, 619, 0, 0, 619, 0, 0, 619, 0, - 619, 0, 619, 619, 619, 619, 0, 619, 0, 0, - 0, 0, 0, 0, 619, 0, 0, 619, 619, 0, - 0, 346, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 619, 619, 619, 619, 619, 0, 0, 0, - 0, 0, 0, 0, 619, 0, 0, 0, 0, 0, - 619, 619, 619, 619, 0, 0, 0, 619, 0, 619, - 0, 0, 0, 0, 0, 619, 619, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 619, 619, 619, 619, 346, 346, 346, 346, 0, 0, - 0, 346, 346, 0, 0, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 0, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 346, 346, 346, - 346, 346, 346, 346, 346, 346, 346, 0, 48, 0, - 0, 0, 48, 346, 48, 0, 346, 48, 0, 48, - 48, 0, 48, 0, 48, 0, 48, 0, 48, 48, - 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, - 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, - 0, 48, 0, 0, 48, 0, 48, 48, 48, 48, - 0, 0, 0, 48, 48, 48, 0, 0, 48, 48, - 48, 0, 0, 0, 0, 0, 0, 48, 48, 0, - 48, 48, 0, 48, 48, 48, 0, 0, 0, 48, + 0, 0, 0, 0, 0, 0, 0, 605, 0, 0, + 0, 106, 301, 108, 109, 605, 605, 0, 605, 0, + 0, 605, 605, 0, 0, 0, 605, 605, 605, 354, + 605, 0, 0, 0, 0, 0, 605, 0, 0, 605, + 0, 0, 0, 0, 0, 0, 605, 0, 0, 0, + 0, 605, 0, 605, 605, 605, 0, 0, 0, 0, + 0, 0, 0, 332, 0, 0, 0, 605, 0, 605, + 605, 0, 0, 605, 0, 0, 605, 0, 605, 0, + 605, 605, 605, 605, 0, 605, 0, 0, 0, 0, + 0, 0, 605, 0, 0, 605, 605, 0, 0, 332, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, - 0, 48, 0, 48, 0, 81, 48, 0, 48, 48, - 0, 48, 0, 48, 48, 48, 0, 48, 48, 48, - 48, 0, 0, 48, 48, 0, 0, 0, 0, 48, - 0, 48, 48, 48, 0, 0, 48, 0, 48, 0, - 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, - 0, 0, 48, 48, 48, 48, 0, 48, 48, 48, - 0, 0, 0, 0, 0, 0, 48, 48, 0, 48, - 48, 0, 48, 48, 48, 0, 0, 0, 48, 0, + 605, 605, 605, 605, 605, 0, 0, 0, 0, 0, + 0, 0, 605, 0, 0, 0, 0, 0, 605, 605, + 605, 605, 0, 0, 0, 605, 0, 605, 0, 0, + 0, 0, 0, 605, 605, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, - 48, 0, 48, 0, 82, 48, 0, 48, 48, 0, - 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, + 0, 0, 0, 0, 0, 0, 0, 0, 605, 605, + 605, 605, 332, 332, 332, 332, 0, 0, 0, 332, + 332, 0, 0, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 0, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 332, 332, 332, 332, 332, + 332, 332, 332, 332, 332, 0, 48, 0, 0, 0, + 48, 332, 48, 0, 332, 48, 0, 48, 48, 0, + 48, 0, 48, 0, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, 0, 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, - 0, 48, 48, 48, 48, 0, 48, 48, 48, 0, + 0, 48, 48, 48, 0, 0, 48, 48, 48, 0, 0, 0, 0, 0, 0, 48, 48, 0, 48, 48, 0, 48, 48, 48, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, 48, - 0, 48, 0, 104, 48, 0, 48, 48, 0, 48, + 0, 48, 0, 81, 48, 0, 48, 48, 0, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, 0, 48, 0, @@ -10311,7 +10435,7 @@ void case_956() 48, 48, 48, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 48, 0, 48, 0, - 48, 0, 105, 48, 0, 48, 48, 0, 48, 0, + 48, 0, 82, 48, 0, 48, 48, 0, 48, 0, 48, 48, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, 0, 48, 0, 0, @@ -10321,35 +10445,51 @@ void case_956() 48, 48, 0, 0, 0, 48, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, 0, 0, 0, 48, 0, 48, 48, 0, 48, 0, 48, - 48, 227, 48, 0, 48, 0, 48, 0, 48, 48, + 48, 212, 48, 0, 48, 0, 48, 0, 48, 48, 48, 48, 0, 0, 48, 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, 0, 0, 48, 0, 48, - 346, 48, 0, 0, 48, 0, 48, 48, 48, 48, + 332, 48, 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, 0, 48, 48, 48, 0, 0, 48, 48, - 48, 48, 0, 346, 0, 0, 0, 48, 48, 0, - 48, 48, 447, 48, 48, 48, 346, 0, 0, 48, - 0, 346, 0, 0, 346, 0, 346, 0, 346, 346, - 346, 346, 0, 0, 0, 448, 346, 0, 0, 48, - 346, 0, 0, 0, 346, 228, 0, 0, 449, 0, - 367, 0, 346, 451, 0, 346, 0, 346, 452, 0, + 48, 48, 0, 332, 0, 0, 0, 48, 48, 0, + 48, 48, 447, 48, 48, 48, 332, 0, 0, 48, + 0, 332, 0, 0, 332, 0, 332, 0, 332, 332, + 332, 332, 0, 0, 0, 448, 332, 0, 0, 48, + 332, 0, 0, 0, 332, 213, 0, 0, 449, 0, + 353, 0, 332, 451, 0, 332, 0, 332, 452, 0, 453, 454, 455, 456, 0, 0, 0, 0, 457, 0, - 0, 0, 458, 367, 0, 0, 346, 0, 0, 0, - 0, 346, 0, 0, 459, 0, 367, 460, 346, 461, - 278, 367, 346, 0, 244, 48, 367, 0, 367, 367, - 367, 367, 0, 0, 0, 346, 367, 0, 0, 0, - 367, 0, 0, 462, 367, 0, 0, 0, 0, 0, - 0, 0, 367, 57, 25, 367, 26, 367, 0, 27, - 256, 0, 0, 0, 28, 62, 63, 346, 29, 0, - 0, 0, 0, 0, 65, 0, 0, 31, 0, 0, - 0, 367, 0, 0, 33, 0, 0, 0, 0, 34, - 0, 72, 73, 35, 0, 582, 0, 0, 0, 1308, + 0, 0, 458, 353, 0, 0, 332, 0, 0, 0, + 447, 332, 0, 0, 459, 0, 353, 460, 332, 461, + 263, 353, 332, 0, 229, 48, 353, 0, 353, 353, + 353, 353, 0, 448, 0, 332, 353, 0, 0, 0, + 353, 0, 0, 462, 353, 0, 449, 0, 0, 0, + 0, 451, 353, 0, 0, 353, 452, 353, 453, 454, + 455, 456, 0, 0, 0, 0, 457, 332, 0, 0, + 458, 0, 0, 0, 1280, 0, 0, 57, 25, 0, + 26, 353, 459, 27, 256, 460, 0, 461, 28, 62, + 63, 0, 29, 0, 0, 0, 0, 0, 65, 0, + 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, + 0, 462, 0, 34, 0, 72, 73, 35, 0, 582, + 0, 0, 0, 0, 0, 0, 583, 0, 0, 37, + 0, 38, 75, 0, 0, 39, 0, 353, 77, 0, + 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, + 0, 0, 0, 0, 584, 0, 0, 88, 89, 0, + 0, 0, 0, 0, 0, 0, 0, 1281, 0, 0, + 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, + 0, 0, 0, 0, 96, 901, 0, 585, 0, 0, + 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, + 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, + 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, + 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, + 106, 469, 108, 109, 65, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 33, 0, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 582, 0, 0, 0, 0, 0, 0, 583, 0, 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, 0, 0, 0, 0, - 584, 0, 0, 88, 89, 0, 0, 367, 0, 0, + 584, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, 0, 0, - 96, 901, 0, 585, 0, 0, 98, 99, 100, 101, + 96, 0, 0, 585, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, @@ -10362,34 +10502,34 @@ void case_956() 0, 0, 0, 0, 0, 0, 584, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, - 0, 0, 0, 0, 0, 0, 96, 0, 0, 585, + 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, 29, 0, 106, 469, 108, 109, 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, - 0, 34, 0, 72, 73, 35, 0, 582, 0, 0, - 0, 0, 0, 0, 583, 0, 0, 37, 0, 38, + 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, - 81, 40, 41, 257, 0, 42, 0, 0, 0, 0, - 0, 0, 584, 0, 0, 88, 89, 0, 0, 0, + 81, 40, 41, 257, 0, 42, 0, 0, 85, 0, + 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, - 0, 0, 28, 62, 63, 0, 29, 0, 106, 469, + 0, 0, 28, 62, 63, 0, 29, 0, 106, 301, 108, 109, 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, 41, 257, - 0, 42, 0, 0, 85, 0, 0, 0, 87, 0, + 0, 42, 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, - 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, + 94, 0, 0, 0, 0, 859, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, @@ -10403,7 +10543,7 @@ void case_956() 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, - 0, 859, 0, 0, 96, 0, 0, 0, 0, 0, + 509, 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, @@ -10416,7 +10556,7 @@ void case_956() 41, 257, 0, 42, 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, - 92, 93, 94, 0, 0, 0, 509, 0, 0, 0, + 92, 93, 94, 0, 0, 0, 503, 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, @@ -10430,7 +10570,7 @@ void case_956() 0, 0, 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, - 0, 0, 503, 0, 0, 0, 96, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, @@ -10448,7 +10588,7 @@ void case_956() 100, 101, 0, 0, 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, 0, 27, 256, 0, - 0, 0, 28, 62, 63, 0, 29, 0, 106, 301, + 0, 0, 28, 62, 63, 0, 29, 0, 106, 469, 108, 109, 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, @@ -10459,427 +10599,411 @@ void case_956() 0, 0, 0, 0, 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, 98, 99, 100, 101, 0, 0, - 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, - 105, 0, 0, 0, 0, 0, 0, 57, 25, 0, - 26, 0, 0, 27, 256, 0, 0, 0, 28, 62, - 63, 0, 29, 0, 106, 469, 108, 109, 65, 0, - 0, 31, 0, 0, 0, 0, 0, 0, 33, 0, - 0, 0, 0, 34, 0, 72, 73, 35, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 37, - 0, 38, 75, 0, 0, 39, 0, 0, 77, 0, - 79, 0, 81, 40, 41, 257, 0, 42, 0, 0, - 0, 0, 0, 0, 87, 0, 0, 88, 89, 0, + 0, 102, 0, 103, 0, 0, 0, 0, 0, 104, + 105, 0, 0, 0, 0, 0, 0, 78, 78, 0, + 78, 0, 0, 78, 78, 0, 0, 0, 78, 78, + 78, 0, 78, 0, 106, 1009, 108, 109, 78, 0, + 0, 78, 0, 0, 0, 0, 0, 0, 78, 0, + 0, 0, 0, 78, 0, 78, 78, 78, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 78, + 0, 78, 78, 0, 0, 78, 0, 0, 78, 0, + 78, 0, 78, 78, 78, 78, 0, 78, 0, 0, + 0, 0, 0, 0, 78, 0, 0, 78, 78, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 90, 91, 92, 93, 94, 0, 0, 0, - 0, 0, 0, 0, 96, 0, 0, 0, 0, 0, - 98, 99, 100, 101, 0, 0, 0, 102, 0, 103, - 0, 0, 0, 0, 0, 104, 105, 0, 0, 0, - 0, 0, 0, 78, 78, 0, 78, 0, 0, 78, - 78, 0, 0, 0, 78, 78, 78, 0, 78, 0, - 106, 1010, 108, 109, 78, 0, 0, 78, 0, 0, - 0, 0, 0, 0, 78, 0, 0, 0, 0, 78, - 0, 78, 78, 78, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 78, 0, 78, 78, 0, - 0, 78, 0, 0, 78, 0, 78, 0, 78, 78, - 78, 78, 0, 78, 0, 0, 0, 0, 0, 0, - 78, 0, 0, 78, 78, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 78, 78, - 78, 78, 78, 0, 0, 0, 0, 0, 0, 0, - 78, 0, 0, 0, 0, 0, 78, 78, 78, 78, - 0, 0, 0, 78, 0, 78, 0, 0, 0, 0, - 0, 78, 78, 0, 0, 0, 0, 0, 0, 150, - 150, 0, 150, 0, 0, 150, 150, 0, 0, 0, - 150, 150, 150, 0, 150, 0, 78, 78, 78, 78, - 150, 0, 0, 150, 0, 0, 0, 0, 0, 0, - 150, 0, 0, 0, 0, 150, 0, 150, 150, 150, + 0, 0, 78, 78, 78, 78, 78, 0, 0, 0, + 0, 0, 0, 0, 78, 0, 0, 0, 0, 0, + 78, 78, 78, 78, 0, 0, 0, 78, 0, 78, + 0, 0, 0, 0, 0, 78, 78, 0, 0, 0, + 0, 0, 0, 135, 135, 0, 135, 0, 0, 135, + 135, 0, 0, 0, 135, 135, 135, 0, 135, 0, + 78, 78, 78, 78, 135, 0, 0, 135, 0, 0, + 0, 0, 0, 0, 135, 0, 0, 0, 0, 135, + 0, 135, 135, 135, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 135, 0, 135, 135, 0, + 0, 135, 0, 0, 135, 0, 135, 0, 135, 135, + 135, 135, 0, 135, 0, 0, 0, 0, 0, 0, + 135, 0, 0, 135, 135, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 135, 135, + 135, 135, 135, 0, 0, 0, 0, 0, 0, 0, + 135, 0, 0, 0, 0, 0, 135, 135, 135, 135, + 0, 0, 0, 135, 0, 135, 0, 0, 0, 0, + 0, 135, 135, 0, 0, 0, 0, 0, 0, 57, + 25, 0, 26, 0, 0, 27, 256, 0, 0, 0, + 28, 62, 63, 0, 29, 0, 135, 135, 135, 135, + 65, 0, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 0, 28, 0, 28, 34, 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 150, 0, 150, 150, 0, 0, 150, 0, 0, - 150, 0, 150, 0, 150, 150, 150, 150, 0, 150, - 0, 0, 0, 0, 0, 0, 150, 0, 0, 150, - 150, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 150, 150, 150, 150, 150, 0, - 0, 0, 0, 0, 0, 0, 150, 0, 0, 0, - 0, 0, 150, 150, 150, 150, 0, 0, 0, 150, - 0, 150, 0, 0, 0, 0, 0, 150, 150, 0, - 0, 0, 0, 0, 0, 57, 25, 0, 26, 0, - 0, 27, 256, 0, 0, 0, 28, 62, 63, 0, - 29, 0, 150, 150, 150, 150, 65, 0, 0, 31, - 0, 0, 0, 0, 0, 0, 33, 0, 28, 0, - 0, 34, 0, 72, 73, 35, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 37, 0, 38, - 75, 28, 0, 39, 0, 0, 77, 0, 79, 0, - 81, 40, 41, 257, 28, 42, 0, 0, 0, 28, - 0, 0, 0, 0, 28, 0, 28, 28, 28, 28, - 0, 0, 28, 0, 28, 0, 0, 0, 28, 0, - 90, 91, 92, 258, 94, 0, 0, 0, 0, 0, - 28, 0, 96, 28, 0, 28, 0, 0, 98, 99, - 100, 101, 0, 0, 0, 102, 0, 103, 0, 57, - 25, 0, 26, 104, 105, 27, 256, 0, 0, 28, - 28, 62, 63, 0, 29, 28, 28, 0, 0, 0, - 65, 0, 0, 31, 0, 0, 0, 48, 106, 259, - 33, 109, 0, 0, 0, 34, 0, 72, 73, 35, + 0, 37, 0, 38, 75, 28, 0, 39, 0, 0, + 77, 0, 79, 0, 81, 40, 41, 257, 28, 42, + 0, 0, 0, 28, 0, 0, 0, 0, 28, 0, + 28, 28, 28, 28, 0, 0, 0, 0, 28, 0, + 0, 0, 28, 0, 90, 91, 92, 258, 94, 0, + 0, 0, 0, 0, 28, 0, 96, 28, 0, 28, + 0, 0, 98, 99, 100, 101, 0, 0, 0, 102, + 0, 103, 0, 57, 25, 0, 26, 104, 105, 27, + 256, 0, 0, 28, 28, 62, 63, 0, 29, 28, + 28, 0, 0, 0, 65, 0, 0, 31, 0, 0, + 0, 0, 106, 259, 33, 109, 0, 0, 0, 34, + 0, 72, 73, 35, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 37, 0, 38, 75, 0, + 0, 39, 0, 0, 77, 0, 79, 0, 81, 40, + 41, 257, 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 48, 37, 0, 38, 75, 0, 0, 39, 0, 0, - 77, 0, 79, 48, 81, 40, 41, 257, 48, 42, - 0, 0, 0, 48, 0, 48, 48, 48, 48, 0, - 0, 48, 0, 48, 0, 0, 0, 48, 0, 0, - 0, 0, 0, 0, 90, 91, 92, 258, 94, 48, - 0, 0, 48, 0, 48, 0, 96, 652, 0, 652, - 0, 652, 98, 0, 652, 101, 652, 652, 0, 652, - 0, 652, 0, 652, 0, 652, 652, 652, 48, 0, - 0, 652, 652, 0, 311, 0, 0, 652, 0, 652, - 652, 0, 0, 0, 652, 0, 0, 0, 652, 0, - 0, 0, 106, 259, 0, 109, 0, 0, 0, 652, - 652, 0, 652, 0, 0, 0, 652, 652, 0, 0, - 0, 0, 0, 0, 652, 652, 57, 25, 652, 26, - 0, 652, 27, 256, 0, 0, 652, 28, 62, 63, - 0, 29, 0, 0, 0, 0, 0, 65, 0, 0, - 31, 0, 0, 0, 0, 0, 0, 33, 652, 652, - 0, 0, 34, 0, 72, 73, 35, 0, 0, 0, - 0, 652, 0, 0, 0, 0, 0, 0, 37, 0, - 38, 75, 0, 0, 39, 0, 0, 77, 0, 79, - 0, 81, 40, 41, 257, 0, 42, 0, 0, 85, - 0, 0, 0, 0, 0, 0, 25, 0, 26, 0, - 0, 27, 652, 1190, 0, 0, 28, 0, 0, 0, - 29, 90, 91, 92, 258, 0, 0, 0, 0, 31, - 651, 0, 651, 96, 0, 651, 33, 651, 651, 0, - 651, 34, 651, 1191, 651, 35, 651, 651, 651, 0, - 0, 0, 651, 651, 0, 0, 0, 37, 651, 38, - 651, 651, 0, 39, 1192, 651, 0, 0, 0, 651, - 0, 40, 41, 0, 0, 42, 0, 0, 319, 106, - 259, 651, 0, 651, 0, 0, 0, 651, 651, 0, - 0, 0, 0, 0, 0, 651, 651, 0, 651, 651, - 651, 0, 651, 651, 0, 651, 651, 651, 651, 0, - 651, 0, 651, 0, 651, 651, 651, 0, 0, 0, - 651, 651, 0, 0, 0, 0, 651, 0, 651, 651, - 0, 0, 0, 651, 0, 0, 0, 651, 0, 0, - 0, 0, 651, 0, 0, 0, 0, 0, 0, 651, - 0, 651, 0, 0, 0, 651, 651, 0, 0, 354, - 0, 0, 0, 651, 651, 0, 0, 651, 0, 0, - 651, 0, 25, 0, 26, 651, 0, 27, 0, 0, - 1263, 0, 28, 651, 671, 0, 29, 0, 672, 1264, - 1265, 0, 0, 0, 1266, 31, 0, 0, 0, 0, - 1267, 0, 33, 0, 25, 0, 26, 34, 0, 27, - 0, 35, 1263, 0, 28, 0, 671, 0, 29, 0, - 672, 1264, 1265, 37, 0, 38, 1266, 31, 0, 39, - 0, 0, 1267, 0, 33, 0, 0, 40, 41, 34, - 0, 42, 0, 35, 1268, 0, 0, 0, 48, 1269, - 48, 651, 0, 48, 0, 37, 0, 38, 48, 0, - 0, 39, 48, 0, 0, 0, 0, 0, 0, 40, - 41, 48, 0, 42, 0, 0, 1268, 0, 48, 0, - 48, 1269, 48, 48, 1270, 48, 0, 48, 0, 48, - 48, 48, 0, 0, 48, 0, 48, 0, 0, 48, - 0, 48, 0, 48, 0, 48, 0, 0, 48, 0, - 48, 0, 0, 48, 48, 48, 0, 48, 0, 48, - 48, 48, 0, 48, 48, 1271, 48, 0, 48, 48, - 0, 48, 0, 48, 48, 0, 0, 48, 48, 0, - 48, 0, 0, 0, 0, 48, 48, 48, 0, 48, - 0, 0, 48, 0, 48, 168, 25, 1271, 26, 48, - 0, 27, 0, 48, 0, 48, 28, 48, 0, 0, - 29, 0, 48, 0, 0, 48, 0, 48, 0, 31, - 0, 48, 0, 0, 48, 168, 33, 0, 0, 48, - 48, 34, 0, 48, 0, 35, 48, 563, 0, 0, - 0, 48, 0, 0, 564, 0, 0, 37, 0, 38, - 0, 0, 0, 39, 0, 0, 565, 0, 0, 0, - 0, 40, 41, 0, 0, 42, 0, 25, 566, 26, - 0, 0, 27, 48, 0, 0, 0, 28, 0, 0, - 0, 29, 0, 0, 0, 30, 25, 0, 26, 0, - 31, 27, 0, 0, 0, 32, 28, 33, 0, 0, - 29, 0, 34, 0, 0, 0, 35, 36, 0, 31, - 0, 0, 0, 0, 0, 0, 33, 48, 37, 0, - 38, 34, 0, 0, 39, 35, 0, 0, 0, 0, - 0, 0, 40, 41, 0, 0, 42, 37, 0, 38, - 25, 0, 26, 39, 0, 27, 0, 0, 0, 567, - 28, 40, 41, 0, 29, 42, 0, 25, 319, 26, - 0, 0, 27, 31, 0, 0, 0, 28, 0, 0, - 33, 29, 0, 0, 0, 34, 0, 0, 0, 35, - 31, 0, 0, 0, 0, 0, 0, 33, 0, 0, - 0, 37, 34, 38, 0, 0, 35, 39, 0, 0, - 0, 0, 0, 0, 0, 40, 41, 0, 37, 42, - 38, 25, 319, 26, 39, 0, 27, 0, 0, 0, - 43, 28, 40, 41, 0, 29, 42, 0, 0, 511, - 0, 0, 0, 0, 31, 25, 0, 26, 0, 326, - 27, 33, 0, 0, 0, 28, 34, 0, 0, 29, - 35, 0, 0, 0, 0, 0, 0, 0, 31, 0, - 0, 0, 37, 0, 38, 33, 0, 0, 39, 0, - 34, 0, 0, 0, 35, 0, 40, 41, 0, 0, - 42, 0, 0, 319, 0, 25, 37, 26, 38, 0, - 27, 0, 39, 354, 0, 28, 0, 0, 0, 29, - 40, 41, 0, 0, 42, 0, 0, 319, 31, 25, - 354, 26, 0, 0, 27, 33, 0, 0, 0, 28, + 0, 0, 0, 0, 0, 0, 0, 0, 90, 91, + 92, 258, 94, 0, 0, 0, 0, 0, 0, 0, + 96, 638, 0, 638, 0, 638, 98, 0, 638, 101, + 638, 638, 0, 638, 0, 638, 0, 638, 0, 638, + 638, 638, 0, 0, 0, 638, 638, 0, 0, 0, + 0, 638, 0, 638, 638, 0, 0, 0, 638, 0, + 0, 0, 638, 0, 0, 0, 106, 259, 0, 109, + 0, 0, 0, 638, 638, 0, 638, 0, 0, 0, + 638, 638, 0, 0, 0, 0, 0, 0, 638, 638, + 57, 25, 638, 26, 0, 638, 27, 256, 0, 0, + 638, 28, 62, 63, 0, 29, 0, 0, 0, 0, + 0, 65, 0, 0, 31, 0, 0, 0, 0, 0, + 0, 33, 638, 638, 0, 0, 34, 0, 72, 73, + 35, 0, 0, 0, 0, 638, 0, 0, 0, 0, + 0, 0, 37, 0, 38, 75, 0, 0, 39, 0, + 0, 77, 0, 79, 0, 81, 40, 41, 257, 0, + 42, 0, 0, 85, 0, 0, 0, 0, 0, 0, + 25, 0, 26, 0, 0, 27, 638, 1189, 0, 0, + 28, 0, 0, 0, 29, 90, 91, 92, 258, 0, + 0, 0, 0, 31, 637, 0, 637, 96, 0, 637, + 33, 637, 637, 0, 637, 34, 637, 1190, 637, 35, + 637, 637, 637, 0, 0, 0, 637, 637, 0, 0, + 0, 37, 637, 38, 637, 637, 0, 39, 1191, 637, + 0, 0, 0, 637, 0, 40, 41, 0, 0, 42, + 0, 0, 319, 106, 259, 637, 0, 637, 0, 0, + 0, 637, 637, 0, 0, 0, 0, 0, 0, 637, + 637, 0, 637, 637, 637, 0, 637, 637, 0, 637, + 637, 637, 637, 0, 637, 0, 637, 0, 637, 637, + 637, 0, 0, 0, 637, 637, 0, 0, 0, 0, + 637, 0, 637, 637, 0, 0, 0, 637, 0, 0, + 0, 637, 0, 0, 0, 0, 637, 0, 0, 0, + 0, 0, 0, 637, 0, 637, 0, 0, 0, 637, + 637, 0, 0, 354, 0, 0, 0, 637, 637, 0, + 0, 637, 0, 0, 637, 0, 25, 0, 26, 637, + 0, 27, 0, 0, 1250, 0, 28, 637, 671, 0, + 29, 0, 672, 1251, 1252, 0, 0, 0, 1253, 31, + 0, 0, 0, 0, 1254, 0, 33, 0, 25, 0, + 26, 34, 0, 27, 0, 35, 1250, 0, 28, 0, + 671, 0, 29, 0, 672, 1251, 1252, 37, 0, 38, + 1253, 31, 0, 39, 0, 0, 1254, 0, 33, 0, + 0, 40, 41, 34, 0, 42, 0, 35, 1255, 0, + 0, 0, 48, 1256, 48, 637, 0, 48, 0, 37, + 0, 38, 48, 0, 0, 39, 48, 0, 0, 0, + 0, 0, 0, 40, 41, 48, 0, 42, 0, 0, + 1255, 0, 48, 0, 48, 1256, 48, 48, 1257, 48, + 0, 48, 0, 48, 48, 48, 0, 0, 48, 0, + 48, 0, 0, 48, 0, 48, 0, 48, 0, 48, + 0, 0, 48, 0, 48, 0, 0, 48, 48, 48, + 0, 48, 0, 48, 48, 48, 0, 48, 48, 1258, + 48, 0, 48, 48, 0, 48, 0, 48, 48, 0, + 0, 48, 48, 0, 48, 0, 0, 0, 0, 48, + 48, 48, 0, 48, 0, 0, 48, 0, 48, 153, + 25, 1258, 26, 48, 0, 27, 0, 48, 0, 48, + 28, 48, 0, 0, 29, 0, 48, 0, 0, 48, + 0, 48, 0, 31, 0, 48, 0, 0, 48, 153, + 33, 0, 0, 48, 48, 34, 0, 48, 0, 35, + 48, 563, 0, 0, 0, 48, 0, 0, 564, 0, + 0, 37, 0, 38, 0, 0, 0, 39, 0, 0, + 565, 0, 0, 0, 0, 40, 41, 0, 0, 42, + 0, 25, 566, 26, 0, 0, 27, 48, 0, 0, + 0, 28, 0, 0, 0, 29, 0, 0, 0, 30, + 25, 0, 26, 0, 31, 27, 0, 0, 0, 32, + 28, 33, 0, 0, 29, 0, 34, 0, 0, 0, + 35, 36, 0, 31, 0, 0, 0, 0, 0, 0, + 33, 48, 37, 0, 38, 34, 0, 0, 39, 35, + 0, 0, 0, 0, 0, 0, 40, 41, 0, 0, + 42, 37, 0, 38, 25, 0, 26, 39, 0, 27, + 0, 0, 0, 567, 28, 40, 41, 0, 29, 42, + 0, 25, 511, 26, 0, 0, 27, 31, 0, 0, + 0, 28, 0, 0, 33, 29, 0, 0, 0, 34, + 0, 0, 0, 35, 31, 0, 0, 0, 0, 0, + 0, 33, 0, 0, 0, 37, 34, 38, 0, 0, + 35, 39, 0, 0, 0, 0, 0, 0, 0, 40, + 41, 0, 37, 42, 38, 25, 319, 26, 39, 0, + 27, 0, 0, 0, 43, 28, 40, 41, 0, 29, + 42, 0, 0, 319, 0, 0, 0, 0, 31, 25, + 0, 26, 0, 354, 27, 33, 0, 0, 0, 28, 34, 0, 0, 29, 35, 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, 37, 0, 38, 33, 0, 0, 39, 0, 34, 0, 0, 0, 35, 0, - 40, 41, 0, 0, 42, 0, 0, 566, 0, 0, - 37, 0, 38, 498, 630, 498, 39, 0, 498, 0, - 0, 0, 0, 498, 40, 41, 0, 498, 42, 0, - 188, 739, 188, 0, 0, 188, 498, 0, 632, 0, - 188, 0, 0, 498, 188, 0, 0, 0, 498, 0, - 0, 0, 498, 188, 0, 0, 0, 0, 0, 0, - 188, 0, 0, 0, 498, 188, 498, 0, 0, 188, - 498, 0, 0, 0, 0, 0, 0, 0, 498, 498, - 0, 188, 498, 188, 187, 498, 187, 188, 354, 187, - 0, 0, 0, 0, 187, 188, 188, 0, 187, 188, - 0, 0, 188, 0, 0, 0, 0, 187, 197, 0, - 197, 0, 354, 197, 187, 0, 0, 0, 197, 187, - 0, 0, 197, 187, 0, 0, 0, 0, 0, 0, - 0, 197, 0, 0, 0, 187, 0, 187, 197, 0, - 0, 187, 0, 197, 0, 0, 0, 197, 0, 187, - 187, 0, 35, 187, 0, 0, 187, 0, 0, 197, - 0, 197, 0, 35, 0, 197, 498, 0, 35, 0, - 0, 0, 35, 197, 197, 35, 0, 197, 0, 0, - 197, 0, 0, 188, 0, 0, 0, 35, 35, 0, - 0, 0, 35, 35, 0, 33, 0, 0, 35, 0, - 35, 35, 35, 35, 0, 0, 33, 0, 35, 0, - 0, 33, 35, 0, 35, 33, 0, 0, 33, 0, - 0, 0, 0, 0, 35, 0, 35, 35, 0, 35, - 33, 33, 0, 35, 0, 33, 33, 187, 0, 0, - 0, 33, 0, 33, 33, 33, 33, 0, 0, 0, - 0, 33, 0, 35, 0, 33, 0, 33, 0, 35, - 35, 197, 0, 28, 0, 28, 0, 33, 0, 0, - 33, 0, 33, 0, 0, 0, 33, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 28, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 33, 0, 0, 28, - 0, 0, 33, 33, 28, 0, 48, 0, 0, 28, - 0, 28, 28, 28, 28, 0, 0, 48, 0, 28, - 0, 0, 48, 28, 0, 0, 48, 0, 0, 48, - 0, 0, 0, 0, 0, 28, 0, 0, 28, 0, - 28, 48, 48, 0, 0, 0, 48, 48, 0, 48, + 40, 41, 0, 0, 42, 0, 0, 566, 0, 484, + 37, 484, 38, 0, 484, 0, 39, 630, 0, 484, + 0, 0, 0, 484, 40, 41, 0, 0, 42, 0, + 0, 739, 484, 173, 632, 173, 0, 0, 173, 484, + 0, 0, 0, 173, 484, 0, 0, 173, 484, 0, + 0, 0, 0, 0, 0, 0, 173, 0, 0, 0, + 484, 0, 484, 173, 0, 0, 484, 0, 173, 0, + 0, 0, 173, 0, 484, 484, 0, 0, 484, 0, + 0, 484, 0, 0, 173, 0, 173, 172, 354, 172, + 173, 0, 172, 0, 0, 0, 0, 172, 173, 173, + 0, 172, 173, 0, 182, 173, 182, 0, 0, 182, + 172, 0, 354, 0, 182, 0, 0, 172, 182, 0, + 0, 0, 172, 0, 0, 0, 172, 182, 0, 0, + 0, 35, 0, 0, 182, 0, 0, 0, 172, 182, + 172, 0, 35, 182, 172, 0, 0, 35, 0, 0, + 0, 35, 172, 172, 35, 182, 172, 182, 0, 172, + 0, 182, 484, 0, 0, 0, 35, 35, 0, 182, + 182, 35, 35, 182, 33, 0, 182, 35, 0, 35, + 35, 35, 35, 0, 0, 33, 173, 35, 0, 0, + 33, 35, 0, 35, 33, 0, 0, 33, 0, 0, + 0, 0, 0, 35, 0, 35, 35, 0, 35, 33, + 33, 0, 35, 0, 33, 33, 0, 0, 0, 0, + 33, 0, 33, 33, 33, 33, 0, 0, 0, 0, + 33, 0, 35, 0, 33, 0, 33, 0, 35, 35, + 172, 0, 0, 48, 0, 0, 33, 0, 0, 33, + 0, 33, 0, 0, 48, 33, 0, 182, 0, 48, + 0, 0, 0, 48, 0, 0, 48, 0, 0, 0, + 0, 0, 0, 0, 0, 33, 0, 0, 48, 48, + 0, 33, 33, 48, 48, 0, 48, 0, 0, 48, + 0, 48, 48, 48, 48, 0, 0, 48, 0, 48, + 0, 0, 48, 48, 0, 48, 48, 0, 0, 48, + 0, 0, 0, 0, 0, 48, 0, 0, 48, 0, + 48, 48, 48, 0, 48, 0, 48, 48, 48, 0, 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, - 48, 0, 48, 0, 28, 48, 48, 0, 48, 48, - 28, 28, 48, 0, 0, 0, 0, 0, 48, 0, - 0, 48, 0, 48, 48, 48, 0, 48, 0, 48, - 48, 48, 0, 0, 0, 48, 0, 48, 48, 48, - 48, 0, 0, 0, 0, 48, 0, 48, 0, 48, - 0, 48, 0, 37, 48, 0, 0, 0, 0, 0, - 0, 48, 0, 0, 48, 0, 48, 48, 0, 48, - 48, 0, 48, 0, 0, 0, 0, 48, 0, 48, - 48, 48, 48, 0, 0, 0, 0, 48, 0, 0, - 48, 48, 48, 0, 0, 0, 38, 0, 0, 0, - 0, 0, 0, 48, 0, 48, 48, 48, 48, 48, - 48, 0, 0, 0, 0, 48, 0, 48, 48, 48, - 48, 0, 0, 0, 0, 48, 0, 0, 0, 48, - 48, 0, 48, 0, 48, 48, 0, 0, 209, 0, - 0, 48, 0, 48, 48, 48, 48, 0, 48, 0, - 0, 0, 0, 48, 0, 48, 48, 48, 48, 0, - 0, 0, 0, 48, 0, 0, 0, 48, 48, 0, - 48, 0, 48, 48, 0, 447, 211, 0, 0, 48, - 0, 48, 48, 0, 48, 0, 48, 0, 0, 0, - 0, 48, 0, 48, 48, 48, 48, 0, 448, 0, - 0, 48, 0, 0, 0, 48, 0, 0, 48, 0, - 0, 449, 0, 0, 312, 450, 451, 48, 447, 0, - 48, 452, 48, 453, 454, 455, 456, 0, 0, 0, - 0, 457, 0, 0, 0, 458, 0, 0, 0, 0, - 0, 448, 0, 0, 0, 0, 48, 459, 48, 48, - 460, 0, 461, 0, 449, 0, 0, 0, 0, 451, - 0, 0, 0, 0, 452, 0, 453, 454, 455, 456, - 0, 0, 0, 0, 457, 0, 462, 0, 458, 0, + 0, 0, 48, 0, 48, 0, 48, 0, 48, 0, + 37, 48, 0, 0, 0, 0, 0, 0, 48, 0, + 0, 48, 0, 48, 48, 0, 48, 48, 0, 48, + 0, 0, 0, 0, 48, 0, 48, 48, 48, 48, + 0, 0, 0, 0, 48, 0, 0, 48, 48, 48, + 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, + 48, 0, 48, 48, 48, 48, 48, 48, 0, 0, + 0, 0, 48, 0, 48, 48, 48, 48, 0, 0, + 0, 0, 48, 0, 0, 0, 48, 48, 0, 48, + 0, 48, 48, 0, 0, 194, 0, 0, 48, 0, + 48, 48, 48, 48, 0, 48, 0, 0, 0, 0, + 48, 0, 48, 48, 48, 48, 0, 0, 0, 0, + 48, 0, 0, 0, 48, 48, 0, 48, 0, 48, + 48, 0, 48, 196, 48, 0, 48, 0, 48, 48, + 0, 48, 0, 48, 0, 0, 0, 0, 48, 0, + 48, 48, 48, 48, 0, 48, 0, 0, 48, 0, + 0, 0, 48, 0, 0, 48, 0, 0, 48, 0, + 0, 297, 447, 48, 48, 0, 0, 48, 48, 48, + 48, 48, 48, 48, 0, 0, 48, 0, 48, 0, + 0, 0, 48, 0, 0, 448, 0, 0, 0, 0, + 0, 0, 0, 48, 48, 48, 48, 48, 449, 48, + 0, 0, 450, 451, 0, 0, 0, 0, 452, 0, + 453, 454, 455, 456, 0, 0, 0, 0, 457, 0, + 0, 0, 458, 48, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 459, 0, 0, 460, 0, 461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 459, 0, 0, 460, 0, 461, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 462, + 0, 0, 0, 462, }; protected static readonly short [] yyCheck = { 17, - 17, 4, 507, 17, 20, 299, 6, 18, 300, 52, - 235, 191, 353, 20, 291, 107, 509, 464, 85, 250, - 190, 60, 549, 298, 159, 483, 296, 335, 17, 328, - 318, 353, 559, 48, 60, 730, 1076, 705, 706, 1113, - 1114, 0, 906, 237, 0, 59, 113, 569, 115, 324, - 759, 78, 256, 113, 256, 115, 74, 256, 256, 256, - 78, 256, 1181, 256, 268, 1197, 80, 256, 82, 256, - 256, 256, 88, 89, 256, 325, 268, 368, 96, 368, - 748, 1213, 750, 282, 17, 1159, 368, 374, 294, 268, - 376, 256, 268, 109, 339, 1285, 357, 335, 256, 306, - 276, 391, 17, 21, 367, 1224, 313, 1226, 1298, 1226, - 368, 367, 373, 376, 277, 314, 374, 17, 325, 257, - 376, 17, 367, 381, 414, 386, 1316, 418, 650, 416, - 17, 376, 407, 17, 365, 53, 1071, 1256, 17, 1256, - 429, 159, 159, 429, 339, 159, 294, 429, 191, 344, - 256, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 266, 17, 17, 17, 17, 259, 418, 256, - 159, 294, 370, 368, 372, 370, 374, 372, 256, 374, - 375, 376, 523, 306, 370, 391, 202, 203, 374, 368, - 256, 429, 235, 62, 381, 390, 381, 66, 67, 68, - 358, 70, 71, 428, 503, 546, 75, 76, 414, 301, - 314, 226, 506, 82, 707, 84, 418, 86, 422, 418, - 418, 418, 91, 92, 546, 418, 159, 0, 569, 418, - 422, 231, 250, 339, 429, 429, 418, 255, 344, 343, - 346, 549, 418, 422, 159, 114, 352, 353, 264, 288, - 317, 559, 1384, 418, 321, 418, 419, 296, 325, 159, - 88, 89, 288, 159, 356, 325, 424, 425, 426, 427, - 418, 375, 159, 291, 290, 159, 294, 295, 325, 1411, - 159, 109, 369, 264, 300, 994, 256, 391, 314, 307, - 306, 1423, 294, 1425, 312, 418, 314, 375, 257, 313, - 318, 257, 970, 369, 256, 159, 159, 159, 159, 650, - 414, 329, 330, 256, 1009, 372, 272, 256, 335, 346, - 842, 277, 256, 429, 428, 281, 256, 262, 346, 651, - 671, 1158, 256, 418, 350, 372, 372, 353, 1378, 358, - 296, 371, 434, 428, 325, 1054, 335, 365, 366, 1176, - 256, 372, 370, 371, 372, 373, 374, 375, 376, 377, - 378, 379, 380, 298, 256, 256, 882, 323, 384, 385, - 1444, 418, 429, 294, 202, 203, 468, 469, 335, 256, - 873, 349, 350, 1318, 402, 428, 342, 963, 257, 391, - 420, 260, 429, 429, 852, 438, 412, 413, 368, 1473, - 1227, 493, 1266, 305, 374, 693, 294, 341, 429, 339, - 1345, 1346, 414, 1348, 430, 991, 368, 1413, 1414, 1087, - 435, 436, 374, 430, 1359, 256, 441, 1362, 444, 298, - 369, 374, 368, 339, 775, 369, 264, 444, 344, 709, - 346, 310, 1377, 378, 379, 369, 352, 353, 679, 376, - 1277, 1119, 1120, 775, 1281, 369, 6, 483, 1126, 373, - 1036, 429, 290, 371, 478, 373, 1401, 17, 341, 962, - 391, 256, 988, 1469, 990, 367, 367, 369, 306, 371, - 256, 263, 418, 256, 576, 376, 578, 505, 580, 507, - 367, 509, 369, 414, 371, 372, 369, 374, 372, 376, - 374, 842, 429, 391, 257, 519, 520, 523, 339, 423, - 60, 277, 368, 531, 64, 281, 523, 349, 350, 841, - 538, 418, 350, 429, 349, 350, 414, 305, 420, 305, - 546, 423, 549, 315, 17, 269, 367, 401, 88, 89, - 861, 418, 559, 420, 558, 839, 423, 263, 256, 413, - 642, 872, 286, 569, 339, 429, 384, 385, 368, 109, - 549, 792, 1181, 851, 582, 583, 339, 866, 368, 368, - 559, 256, 373, 429, 369, 376, 342, 60, 343, 1037, - 343, 64, 367, 718, 412, 413, 98, 99, 100, 101, - 102, 103, 104, 105, 367, 870, 1123, 429, 371, 315, - 373, 374, 375, 376, 429, 1224, 343, 1226, 381, 159, - 479, 629, 375, 256, 906, 374, 381, 635, 381, 429, - 305, 713, 372, 418, 374, 372, 391, 369, 391, 429, - 429, 339, 272, 376, 650, 272, 344, 1256, 346, 347, - 348, 349, 350, 351, 352, 353, 354, 355, 356, 414, - 519, 414, 202, 203, 391, 671, 296, 416, 357, 296, - 368, 679, 370, 428, 372, 428, 374, 375, 376, 376, - 709, 418, 672, 272, 741, 693, 159, 414, 277, 429, - 418, 369, 281, 323, 702, 979, 323, 386, 414, 707, - 428, 428, 1181, 376, 712, 370, 339, 296, 371, 374, - 931, 344, 428, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 356, 264, 386, 256, 367, 734, 367, - 1181, 429, 736, 371, 323, 368, 376, 370, 272, 372, - 418, 374, 375, 376, 752, 1224, 754, 1226, 288, 755, - 290, 384, 385, 342, 758, 759, 389, 390, 1180, 1181, - 300, 769, 296, 1181, 367, 771, 306, 400, 401, 775, - 371, 343, 414, 1224, 314, 1226, 1043, 1256, 1200, 787, - 413, 256, 420, 816, 792, 793, 428, 795, 367, 323, - 418, 381, 1076, 1091, 269, 335, 429, 376, 806, 807, - 882, 391, 1224, 375, 1226, 1256, 1224, 381, 1226, 339, - 350, 286, 1079, 353, 344, 288, 346, 391, 824, 391, - 294, 367, 352, 353, 414, 1123, 328, 824, 391, 837, - 376, 839, 306, 1181, 1256, 379, 842, 843, 1256, 829, - 414, 314, 414, 851, 384, 385, 854, 1007, 1069, 384, - 1117, 414, 369, 861, 428, 1153, 428, 306, 421, 369, - 389, 1298, 335, 871, 313, 873, 367, 369, 367, 386, - 387, 381, 412, 413, 385, 376, 1224, 376, 1226, 381, - 382, 383, 1181, 1366, 386, 387, 388, 389, 390, 391, - 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, - 906, 394, 395, 357, 1235, 913, 988, 915, 1256, 917, - 261, 1242, 391, 357, 400, 369, 734, 1132, 372, 373, - 374, 1188, 928, 931, 371, 1224, 373, 1226, 1010, 373, - 936, 928, 386, 284, 374, 414, 376, 755, 1108, 357, - 370, 381, 386, 483, 374, 1428, 297, 390, 938, 428, - 940, 302, 942, 771, 962, 373, 307, 1256, 309, 310, - 311, 312, 339, 367, 418, 369, 317, 344, 386, 346, - 321, 1181, 349, 350, 325, 352, 353, 373, 369, 414, - 376, 1464, 333, 523, 1266, 336, 421, 338, 373, 339, - 994, 1486, 1487, 1001, 344, 1003, 346, 1005, 418, 349, - 350, 503, 352, 353, 398, 399, 546, 382, 383, 549, - 483, 362, 376, 372, 1224, 374, 1226, 376, 372, 559, - 374, 396, 397, 1016, 374, 843, 306, 339, 308, 569, - 354, 355, 344, 313, 346, 1043, 369, 349, 350, 372, - 352, 353, 418, 370, 371, 325, 1256, 374, 1056, 1057, - 1054, 372, 429, 374, 371, 376, 1064, 415, 357, 370, - 370, 1069, 374, 374, 374, 354, 355, 418, 1076, 1070, - 369, 1079, 574, 418, 373, 1108, 549, 1110, 339, 429, - 386, 387, 388, 344, 1091, 346, 559, 386, 349, 350, - 1098, 352, 353, 339, 1378, 256, 60, 1105, 344, 1132, - 346, 414, 415, 349, 350, 1111, 352, 353, 368, 1117, - 650, 371, 1091, 373, 374, 418, 1123, 429, 936, 418, - 277, 1129, 1130, 370, 371, 418, 373, 374, 375, 1162, - 94, 671, 392, 393, 98, 99, 100, 101, 102, 103, - 104, 105, 376, 372, 1123, 374, 1153, 1180, 1181, 370, - 340, 372, 412, 374, 370, 367, 372, 1163, 374, 0, - 420, 376, 1170, 423, 373, 705, 706, 1200, 429, 374, - 357, 376, 370, 1179, 1153, 371, 374, 373, 1186, 370, - 1188, 372, 369, 429, 370, 372, 373, 370, 374, 372, - 374, 1224, 376, 1226, 734, 368, 392, 393, 371, 386, - 373, 374, 372, 370, 339, 372, 376, 376, 748, 344, - 750, 346, 370, 1295, 372, 755, 412, 352, 353, 392, - 393, 364, 365, 1256, 420, 376, 1308, 423, 1234, 1235, - 418, 771, 705, 706, 1238, 775, 1242, 418, 372, 412, - 374, 372, 367, 1325, 343, 1327, 371, 420, 373, 374, - 423, 376, 372, 256, 374, 376, 381, 1263, 1264, 370, - 1266, 372, 414, 370, 367, 372, 1272, 372, 371, 418, - 373, 374, 374, 376, 376, 748, 418, 750, 381, 1285, - 418, 1287, 367, 374, 1290, 376, 371, 369, 373, 374, - 415, 376, 1298, 374, 418, 376, 381, 349, 350, 1303, - 285, 372, 842, 843, 390, 391, 392, 393, 418, 374, - 1316, 376, 415, 372, 373, 364, 365, 1074, 1075, 388, - 389, 394, 395, 1356, 288, 376, 372, 372, 368, 372, - 374, 372, 296, 372, 372, 418, 339, 372, 294, 294, - 1373, 344, 327, 346, 347, 348, 349, 350, 351, 352, - 353, 354, 355, 1386, 1387, 374, 372, 372, 1366, 376, - 1364, 1179, 418, 374, 866, 368, 906, 370, 372, 372, - 1378, 374, 375, 376, 371, 256, 374, 356, 372, 375, - 1413, 1414, 418, 374, 418, 375, 381, 1395, 374, 373, - 418, 372, 377, 378, 379, 380, 936, 382, 383, 384, - 385, 386, 387, 388, 389, 369, 381, 392, 393, 394, - 395, 396, 397, 398, 399, 256, 1234, 381, 382, 383, - 1428, 262, 386, 387, 374, 374, 429, 374, 376, 418, - 970, 0, 374, 294, 372, 423, 1469, 429, 374, 367, - 418, 372, 418, 373, 343, 1263, 1264, 372, 374, 294, - 294, 374, 418, 294, 370, 418, 1464, 298, 371, 381, - 418, 367, 256, 375, 256, 374, 1470, 1471, 256, 1287, - 256, 372, 1290, 1477, 1478, 372, 381, 280, 1486, 1487, - 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 256, 367, 372, 368, 418, 343, 374, 970, 339, 418, - 418, 418, 376, 344, 370, 346, 347, 348, 349, 350, - 351, 352, 353, 354, 355, 356, 371, 376, 418, 376, - 374, 372, 372, 376, 370, 421, 367, 368, 423, 370, - 371, 372, 381, 374, 375, 376, 347, 378, 379, 351, - 367, 382, 383, 384, 385, 381, 381, 1087, 389, 390, - 256, 1091, 256, 394, 395, 396, 397, 398, 399, 400, - 401, 368, 372, 372, 347, 370, 374, 367, 370, 375, - 348, 1111, 413, 372, 375, 416, 372, 418, 368, 1119, - 1120, 370, 339, 1123, 418, 418, 1126, 374, 429, 256, - 374, 376, 348, 368, 375, 367, 367, 367, 265, 0, - 267, 368, 381, 270, 356, 418, 371, 376, 275, 368, - 574, 374, 279, 1153, 1087, 368, 337, 372, 1091, 368, - 305, 288, 376, 1163, 371, 418, 371, 418, 295, 369, - 367, 381, 371, 300, 367, 371, 418, 304, 418, 1179, - 371, 418, 371, 373, 371, 369, 1119, 1120, 371, 316, - 1123, 318, 372, 1126, 372, 322, 381, 374, 373, 373, - 261, 374, 263, 330, 331, 374, 256, 334, 376, 374, - 337, 372, 418, 372, 370, 418, 376, 418, 376, 372, - 1153, 376, 372, 284, 418, 367, 372, 256, 368, 381, - 381, 370, 261, 262, 1234, 1235, 297, 372, 368, 315, - 263, 302, 1242, 371, 368, 371, 307, 372, 309, 310, - 311, 312, 372, 0, 315, 284, 317, 0, 367, 376, - 321, 418, 376, 1263, 1264, 294, 1266, 368, 297, 298, - 372, 0, 333, 302, 368, 336, 305, 338, 307, 376, - 309, 310, 311, 312, 372, 709, 372, 1287, 317, 418, - 1290, 418, 321, 370, 367, 376, 325, 368, 368, 367, - 372, 362, 376, 370, 333, 418, 0, 336, 418, 338, - 339, 376, 376, 368, 372, 344, 376, 346, 347, 348, - 349, 350, 351, 352, 353, 354, 355, 356, 372, 368, - 372, 368, 372, 362, 367, 376, 368, 368, 367, 368, - 367, 370, 371, 372, 373, 374, 375, 376, 373, 378, - 379, 315, 381, 382, 383, 384, 385, 386, 387, 388, - 389, 390, 376, 392, 393, 394, 395, 396, 397, 398, + 17, 52, 4, 17, 20, 18, 300, 299, 507, 17, + 291, 191, 235, 353, 250, 509, 20, 6, 464, 190, + 85, 60, 549, 298, 159, 483, 353, 318, 328, 335, + 1077, 60, 559, 296, 906, 759, 730, 78, 237, 107, + 705, 706, 256, 268, 569, 59, 0, 256, 113, 324, + 115, 0, 1114, 1115, 268, 1196, 74, 277, 17, 113, + 78, 115, 268, 256, 256, 256, 80, 17, 82, 17, + 256, 1212, 88, 89, 256, 325, 17, 256, 96, 88, + 89, 256, 256, 748, 256, 750, 48, 335, 256, 282, + 911, 294, 17, 109, 256, 1157, 349, 350, 371, 256, + 109, 268, 256, 256, 294, 17, 368, 21, 277, 276, + 256, 256, 281, 372, 263, 60, 306, 256, 367, 374, + 17, 314, 367, 357, 17, 650, 17, 376, 257, 365, + 339, 376, 407, 256, 0, 344, 358, 346, 17, 53, + 191, 159, 159, 352, 353, 159, 256, 420, 256, 94, + 17, 159, 386, 98, 99, 100, 101, 102, 103, 104, + 105, 416, 368, 257, 339, 256, 315, 429, 418, 344, + 429, 346, 358, 342, 17, 256, 429, 352, 353, 341, + 256, 429, 305, 523, 235, 339, 202, 203, 370, 381, + 372, 259, 374, 202, 203, 305, 256, 422, 418, 419, + 159, 294, 381, 503, 256, 428, 546, 369, 422, 159, + 294, 159, 1033, 707, 506, 418, 422, 60, 159, 546, + 429, 64, 367, 369, 369, 418, 371, 418, 418, 569, + 429, 1372, 250, 301, 159, 374, 418, 255, 424, 425, + 426, 427, 231, 549, 418, 294, 418, 159, 264, 288, + 418, 418, 317, 559, 429, 264, 321, 296, 1399, 288, + 325, 418, 159, 1070, 226, 418, 159, 375, 159, 993, + 1411, 325, 1413, 291, 290, 420, 294, 295, 423, 370, + 159, 290, 256, 374, 300, 314, 367, 339, 356, 307, + 306, 418, 159, 369, 312, 376, 314, 306, 391, 313, + 318, 428, 256, 372, 969, 346, 368, 391, 257, 369, + 650, 329, 330, 294, 1008, 367, 159, 842, 335, 1366, + 335, 414, 1401, 1402, 651, 325, 401, 335, 346, 1053, + 414, 671, 369, 369, 350, 266, 373, 353, 413, 272, + 256, 350, 391, 288, 882, 418, 264, 365, 366, 418, + 305, 296, 370, 371, 372, 373, 374, 375, 376, 377, + 378, 379, 380, 296, 256, 414, 434, 429, 384, 385, + 1432, 368, 256, 368, 1156, 384, 385, 428, 1457, 873, + 376, 1253, 418, 314, 402, 339, 423, 438, 349, 350, + 323, 257, 349, 350, 852, 369, 412, 413, 368, 1461, + 468, 469, 693, 412, 413, 1187, 272, 325, 368, 372, + 391, 277, 343, 367, 430, 281, 305, 371, 418, 373, + 374, 375, 376, 1088, 369, 493, 430, 381, 444, 262, + 296, 368, 429, 414, 429, 775, 381, 382, 383, 256, + 444, 386, 387, 679, 375, 288, 709, 339, 775, 987, + 376, 989, 368, 343, 483, 1120, 1121, 323, 374, 429, + 391, 372, 1127, 374, 478, 298, 429, 961, 429, 429, + 376, 314, 429, 435, 436, 367, 342, 372, 376, 441, + 256, 418, 1264, 414, 368, 375, 1268, 505, 357, 507, + 374, 509, 335, 1180, 1180, 367, 369, 428, 1305, 371, + 369, 391, 842, 429, 373, 519, 520, 523, 576, 306, + 578, 1293, 580, 531, 841, 372, 313, 386, 429, 523, + 538, 368, 376, 429, 414, 343, 1333, 1334, 263, 1336, + 546, 343, 549, 372, 429, 374, 1223, 1223, 428, 369, + 1347, 549, 559, 1350, 558, 378, 379, 839, 420, 418, + 367, 559, 369, 569, 371, 372, 792, 374, 1365, 376, + 851, 343, 1180, 339, 582, 583, 866, 272, 344, 381, + 346, 418, 429, 391, 642, 256, 352, 353, 1036, 391, + 315, 861, 1389, 718, 265, 1180, 267, 1180, 418, 270, + 429, 296, 872, 375, 275, 870, 414, 1124, 279, 381, + 371, 418, 414, 420, 1180, 1223, 423, 288, 1180, 391, + 428, 629, 906, 386, 295, 272, 428, 635, 323, 300, + 374, 381, 371, 304, 373, 391, 1180, 6, 1223, 574, + 1223, 391, 414, 367, 650, 316, 962, 318, 17, 296, + 483, 322, 261, 392, 393, 713, 428, 1223, 414, 330, + 331, 1223, 414, 334, 414, 671, 337, 418, 371, 421, + 373, 679, 416, 412, 990, 284, 323, 428, 428, 1223, + 709, 420, 341, 367, 423, 693, 741, 371, 297, 373, + 374, 60, 376, 302, 702, 64, 978, 381, 307, 707, + 309, 310, 311, 312, 712, 931, 315, 357, 317, 371, + 369, 391, 321, 272, 306, 371, 549, 373, 277, 88, + 89, 313, 281, 373, 333, 1271, 559, 336, 734, 338, + 367, 415, 736, 325, 414, 734, 386, 296, 1284, 376, + 109, 269, 1179, 1180, 752, 339, 754, 418, 428, 755, + 367, 357, 369, 362, 758, 759, 755, 1303, 286, 368, + 369, 769, 1199, 369, 323, 771, 372, 373, 374, 775, + 391, 1042, 771, 367, 709, 816, 394, 395, 414, 787, + 386, 381, 376, 342, 792, 793, 1223, 795, 1225, 414, + 159, 391, 428, 414, 256, 1077, 1092, 379, 806, 807, + 421, 367, 372, 428, 374, 371, 339, 373, 374, 1080, + 376, 344, 418, 346, 414, 381, 349, 350, 824, 352, + 353, 418, 357, 294, 882, 374, 256, 376, 1124, 837, + 824, 839, 381, 202, 203, 306, 842, 843, 373, 269, + 384, 374, 1068, 851, 843, 1006, 854, 1118, 1284, 415, + 829, 386, 831, 861, 400, 1151, 286, 306, 389, 308, + 367, 369, 368, 871, 313, 873, 382, 383, 374, 376, + 1354, 369, 705, 706, 385, 381, 325, 339, 386, 387, + 396, 397, 344, 381, 346, 347, 348, 349, 350, 351, + 352, 353, 354, 355, 356, 264, 429, 390, 370, 371, + 906, 373, 374, 375, 1234, 913, 368, 915, 370, 917, + 372, 1241, 374, 375, 376, 748, 367, 750, 418, 288, + 1133, 290, 928, 931, 367, 376, 357, 373, 390, 987, + 376, 300, 1416, 376, 928, 367, 339, 306, 372, 1109, + 374, 344, 373, 346, 376, 314, 349, 350, 369, 352, + 353, 1009, 261, 961, 373, 386, 373, 376, 937, 1230, + 939, 357, 941, 398, 399, 339, 335, 429, 1452, 1253, + 344, 374, 346, 369, 376, 284, 372, 373, 352, 353, + 374, 350, 376, 370, 353, 1474, 1475, 374, 297, 993, + 386, 418, 1000, 302, 1002, 372, 1004, 374, 307, 376, + 309, 310, 311, 312, 371, 370, 371, 415, 317, 374, + 370, 1017, 321, 418, 374, 384, 385, 372, 1017, 374, + 370, 376, 372, 1015, 333, 339, 429, 336, 369, 338, + 344, 372, 346, 370, 1042, 349, 350, 374, 352, 353, + 256, 370, 370, 412, 413, 374, 374, 1055, 1056, 1053, + 370, 339, 372, 362, 374, 1063, 344, 418, 346, 370, + 1068, 349, 350, 374, 352, 353, 1069, 277, 1109, 1077, + 418, 370, 1080, 372, 340, 374, 339, 390, 391, 392, + 393, 344, 376, 346, 1366, 1092, 349, 350, 373, 352, + 353, 1099, 1133, 367, 1092, 1136, 368, 376, 1106, 371, + 376, 373, 374, 386, 387, 388, 1112, 354, 355, 418, + 1118, 370, 376, 372, 483, 429, 374, 1124, 376, 376, + 392, 393, 1130, 1131, 343, 370, 1124, 372, 370, 372, + 372, 374, 372, 372, 374, 1176, 969, 418, 1179, 1180, + 412, 429, 369, 367, 1151, 354, 355, 371, 420, 373, + 374, 423, 376, 1151, 523, 372, 1162, 381, 1199, 414, + 415, 1169, 368, 349, 350, 371, 429, 373, 374, 370, + 418, 372, 1178, 370, 418, 372, 1184, 546, 414, 1178, + 549, 374, 1223, 376, 1225, 418, 392, 393, 418, 374, + 559, 376, 98, 99, 100, 101, 102, 103, 104, 105, + 569, 374, 374, 376, 376, 418, 412, 364, 365, 372, + 373, 364, 365, 372, 420, 1075, 1076, 423, 388, 389, + 394, 395, 1230, 1281, 418, 376, 372, 1233, 1234, 372, + 368, 256, 374, 1237, 1233, 1241, 372, 1295, 372, 372, + 372, 418, 372, 294, 1250, 1251, 294, 1253, 374, 372, + 372, 1250, 1251, 1259, 1312, 1088, 1314, 376, 418, 1092, + 374, 372, 371, 256, 374, 1271, 418, 1273, 375, 418, + 1276, 356, 372, 381, 1273, 374, 373, 1276, 1284, 375, + 374, 650, 0, 381, 372, 1289, 381, 1120, 1121, 418, + 374, 1124, 374, 374, 1127, 374, 376, 1303, 294, 423, + 372, 429, 671, 1344, 402, 403, 404, 405, 406, 407, + 408, 409, 410, 411, 339, 374, 418, 367, 1151, 344, + 1361, 346, 347, 348, 349, 350, 351, 352, 353, 354, + 355, 356, 372, 1374, 1375, 373, 705, 706, 372, 343, + 418, 374, 294, 368, 294, 370, 1354, 372, 1352, 374, + 375, 376, 374, 418, 418, 370, 418, 371, 1366, 367, + 1401, 1402, 418, 62, 256, 734, 256, 66, 67, 68, + 256, 70, 71, 374, 256, 1383, 75, 76, 372, 748, + 372, 750, 381, 82, 280, 84, 755, 86, 256, 256, + 367, 418, 91, 92, 368, 262, 372, 418, 418, 343, + 418, 376, 771, 370, 429, 371, 775, 375, 1416, 418, + 374, 376, 374, 376, 372, 114, 1457, 376, 372, 370, + 423, 421, 328, 347, 381, 351, 381, 256, 381, 256, + 372, 298, 368, 372, 347, 370, 374, 367, 375, 370, + 372, 375, 367, 370, 1452, 348, 368, 418, 339, 372, + 348, 368, 381, 374, 1458, 1459, 376, 418, 374, 367, + 375, 1465, 1466, 369, 368, 367, 1474, 1475, 367, 356, + 371, 376, 418, 842, 843, 381, 382, 383, 372, 374, + 386, 387, 388, 389, 390, 391, 392, 393, 394, 395, + 396, 397, 398, 399, 400, 401, 256, 368, 368, 368, + 337, 368, 305, 367, 371, 371, 373, 374, 418, 418, + 371, 378, 379, 369, 371, 382, 383, 384, 385, 386, + 387, 388, 389, 390, 376, 392, 393, 394, 395, 396, + 397, 398, 399, 400, 401, 418, 371, 906, 256, 418, + 418, 0, 381, 371, 262, 412, 413, 373, 371, 367, + 371, 381, 369, 420, 374, 371, 423, 372, 257, 372, + 374, 260, 429, 373, 373, 256, 374, 374, 418, 418, + 376, 372, 372, 370, 376, 418, 294, 376, 372, 339, + 298, 376, 418, 372, 344, 381, 346, 347, 348, 349, + 350, 351, 352, 353, 354, 355, 367, 503, 372, 298, + 969, 368, 381, 372, 370, 368, 315, 263, 368, 371, + 370, 310, 372, 371, 374, 375, 376, 368, 372, 372, + 0, 339, 0, 367, 376, 418, 344, 376, 346, 347, + 348, 349, 350, 351, 352, 353, 354, 355, 356, 368, + 372, 0, 376, 368, 372, 372, 418, 370, 1017, 367, + 368, 367, 370, 371, 372, 376, 374, 375, 376, 372, + 378, 379, 368, 368, 382, 383, 384, 385, 574, 429, + 370, 389, 390, 376, 376, 418, 394, 395, 396, 397, + 398, 399, 400, 401, 376, 418, 368, 372, 376, 367, + 376, 372, 368, 372, 256, 413, 368, 372, 416, 367, + 418, 368, 376, 265, 368, 267, 367, 373, 270, 0, + 315, 429, 263, 275, 376, 51, 376, 279, 376, 1088, + 52, 376, 376, 1092, 376, 376, 288, 376, 12, 5, + 928, 824, 1068, 295, 1068, 1225, 1199, 1406, 300, 1369, + 261, 1422, 304, 1112, 1357, 1386, 1259, 1352, 1271, 841, + 1466, 1120, 1121, 671, 316, 1124, 318, 685, 1127, 845, + 322, 1290, 845, 284, 1223, 1379, 1211, 1460, 330, 331, + 845, 1375, 334, 1374, 1459, 337, 297, 1176, 1314, 1259, + 479, 302, 1151, 523, 816, 787, 307, 1162, 309, 310, + 311, 312, 866, 1162, 315, 792, 317, 256, 712, 583, + 321, 365, 261, 262, 679, 72, 331, 978, 94, 1178, + 396, 398, 333, 397, 399, 336, 709, 338, 400, 775, + 519, 401, 546, 1144, 1233, 284, 1151, 1092, 159, 990, + 1035, 1056, 963, 948, 1045, 294, 1036, 521, 297, 298, + 1047, 362, 886, 302, 420, 1228, 305, 368, 307, 1131, + 309, 310, 311, 312, -1, -1, 418, -1, 317, -1, + -1, 821, 321, -1, 1233, 1234, 325, -1, -1, -1, + -1, -1, 1241, 822, 333, -1, 0, 336, -1, 338, + 339, 1250, 1251, -1, 1253, 344, -1, 346, 347, 348, + 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, + -1, -1, -1, 362, 1273, -1, -1, 1276, 367, 368, + -1, 370, 371, 372, 373, 374, 375, 376, -1, 378, + 379, -1, 381, 382, 383, 384, 385, 386, 387, 388, + 389, 390, -1, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, 376, 376, 416, 376, 418, - 376, 420, 376, 376, 423, 256, 257, 376, 263, 51, - 429, 52, 12, 264, 265, 266, 267, 268, 5, 270, - 271, 928, 273, 274, 275, 276, 277, 278, 279, 280, - 824, 1200, 1256, 1381, 285, 1418, 287, 288, 289, 290, - 291, 292, 1069, 1069, 295, 0, 1434, 671, 299, 300, - 1369, 302, 303, 304, 1398, 1364, 1272, 1285, 845, 685, - 845, 845, 841, 314, 1478, 316, 1224, 318, 319, 1472, - 1304, 322, 1212, 324, 325, 326, 327, 328, 329, 330, - 331, 332, 333, 334, 335, 1391, 337, 1387, 1386, 340, - 341, 1327, 1162, 344, 345, 1471, 1272, 816, 523, 1163, - 712, 866, 792, 583, 365, 787, 979, 679, 359, 360, - 361, 362, 363, 72, 331, 709, 367, 368, 94, 396, - 371, 397, 400, 398, 1146, 376, 377, 378, 379, 380, - 399, 401, 546, 384, 1234, 386, 159, 1153, 949, 1057, - 1091, 392, 393, 964, 1048, 1037, 1046, 911, 886, 521, - 1230, 1130, 775, 420, 822, 821, -1, -1, -1, -1, + 409, 410, 411, 412, 413, -1, -1, 416, -1, 418, + 866, 420, -1, -1, 423, 256, 257, -1, -1, -1, + 429, -1, -1, 264, 265, 266, 267, 268, -1, 270, + 271, -1, 273, 274, 275, 276, 277, 278, 279, 280, + -1, -1, -1, -1, 285, -1, 287, 288, 289, 290, + 291, 292, -1, -1, 295, 0, -1, -1, 299, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 314, -1, 316, -1, 318, 319, -1, + -1, 322, -1, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, -1, -1, 340, + 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, 367, 368, -1, -1, + 371, -1, -1, -1, -1, 376, 377, 378, 379, 380, + -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, + -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 417, 418, 419, 420, -1, 422, 256, 257, -1, -1, -1, -1, 429, -1, 264, 265, 266, 267, 268, -1, 270, 271, -1, 273, @@ -11052,7 +11176,7 @@ void case_956() -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, -1, 384, 298, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 256, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 262, -1, 417, 418, 419, 420, -1, -1, -1, -1, -1, 339, -1, -1, 429, -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, @@ -11063,12 +11187,12 @@ void case_956() 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, -1, 256, -1, -1, 418, -1, 420, 262, -1, 423, -1, -1, - -1, -1, -1, 429, -1, -1, -1, -1, 368, -1, - -1, 371, -1, 373, 374, -1, -1, -1, 378, 379, - -1, -1, 382, 383, 384, 385, 386, 387, 388, 389, + -1, -1, -1, 429, -1, -1, -1, -1, -1, 369, + -1, 371, 372, 373, 374, -1, 376, -1, 378, 379, + -1, 381, 382, 383, 384, 385, -1, 387, 388, 389, 390, 298, 392, 393, 394, 395, 396, 397, 398, 399, - 400, 401, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 412, 413, -1, -1, -1, -1, -1, -1, + 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, + 410, 411, 412, 413, -1, -1, -1, -1, 418, -1, 420, 262, -1, 423, -1, -1, -1, -1, -1, 429, -1, -1, 339, -1, -1, -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, @@ -11095,29 +11219,29 @@ void case_956() 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, 413, -1, 256, -1, -1, -1, -1, 420, 262, -1, 423, -1, -1, -1, -1, - -1, 429, -1, -1, -1, -1, -1, 369, -1, 371, - 372, 373, 374, -1, 376, -1, 378, 379, -1, 381, - 382, 383, 384, 385, -1, 387, 388, 389, 390, 298, + -1, 429, -1, -1, -1, -1, -1, -1, 370, 371, + 372, 373, 374, -1, -1, -1, 378, 379, -1, 381, + 382, 383, 384, 385, 386, 387, 388, 389, 390, 298, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, 410, 411, - 412, 413, -1, -1, -1, -1, 418, -1, 420, 262, + 412, 413, -1, -1, -1, -1, -1, -1, 420, -1, -1, 423, -1, -1, -1, -1, -1, 429, -1, -1, 339, -1, -1, -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, - -1, -1, -1, -1, -1, 298, -1, -1, -1, 368, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, -1, 370, 371, 372, 373, 374, 375, 376, -1, 378, 379, -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, -1, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, - 409, 410, 411, 412, 413, -1, 256, -1, -1, -1, - -1, 420, 262, -1, 423, -1, -1, -1, -1, -1, - 429, -1, -1, -1, -1, -1, -1, 370, 371, 372, - 373, 374, -1, -1, -1, 378, 379, -1, 381, 382, - 383, 384, 385, 386, 387, 388, 389, 390, 298, 392, - 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, - 403, 404, 405, 406, 407, 408, 409, 410, 411, 412, - 413, -1, -1, -1, -1, -1, -1, 420, -1, -1, - 423, -1, -1, -1, -1, -1, 429, -1, -1, 339, + 409, 410, 411, 412, 413, -1, 256, 256, -1, -1, + -1, 420, 262, -1, 423, -1, 265, -1, 267, -1, + 429, 270, -1, -1, -1, -1, 275, -1, -1, -1, + 279, -1, -1, -1, -1, -1, -1, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, 298, -1, + -1, 300, -1, -1, -1, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, + -1, -1, -1, 322, -1, -1, -1, -1, -1, -1, + -1, 330, 331, -1, -1, 334, -1, -1, 337, 339, -1, -1, -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, -1, @@ -11125,7 +11249,7 @@ void case_956() -1, 381, 382, 383, 384, 385, 386, 387, 388, 389, 390, -1, 392, 393, 394, 395, 396, 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, 409, - 410, 411, 412, 413, -1, 256, 256, -1, -1, -1, + 410, 411, 412, 413, -1, 256, 256, -1, -1, 418, 420, 262, -1, 423, -1, 265, -1, 267, -1, 429, 270, -1, -1, -1, -1, 275, -1, -1, -1, 279, -1, -1, -1, -1, -1, -1, -1, -1, 288, -1, @@ -11203,19 +11327,19 @@ void case_956() 355, 356, -1, -1, -1, -1, -1, -1, -1, -1, -1, 298, -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, -1, 378, 379, -1, -1, 382, 383, 384, - 385, -1, -1, -1, 389, 390, -1, -1, -1, 394, + 385, -1, -1, -1, 389, 390, 285, -1, -1, 394, 395, 396, 397, 398, 399, 400, 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, - -1, -1, -1, 256, 429, -1, -1, -1, -1, 262, + -1, -1, -1, 256, 429, -1, -1, -1, 327, 262, -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, -1, 378, 379, -1, -1, 382, 383, 384, 385, -1, -1, -1, 389, 390, -1, -1, -1, 394, 395, 396, 397, 398, 399, 400, 401, 298, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 413, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 256, 429, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 413, -1, 377, 378, + 379, 380, -1, 382, 383, 384, 385, 386, 387, 388, + 389, 256, 429, 392, 393, 394, 395, 396, 397, 398, + 399, -1, -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, -1, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, @@ -11308,7 +11432,7 @@ void case_956() 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, - -1, -1, -1, -1, -1, -1, 385, -1, -1, -1, + -1, -1, -1, -1, -1, 384, 385, -1, -1, -1, 389, 390, -1, 256, -1, -1, -1, -1, -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, @@ -11322,7 +11446,7 @@ void case_956() 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, -1, -1, - -1, -1, 385, -1, -1, -1, -1, 390, -1, 256, + -1, -1, 385, -1, -1, -1, 389, 390, -1, 256, -1, -1, -1, -1, -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, @@ -11335,94 +11459,38 @@ void case_956() 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 385, -1, -1, -1, -1, 390, -1, 256, -1, -1, -1, -1, -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, -1, 374, 375, 376, -1, -1, - -1, 256, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 390, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 390, -1, 256, -1, -1, -1, -1, -1, -1, -1, 400, 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, -1, -1, -1, -1, -1, 368, -1, 370, - -1, 372, -1, 374, 375, 376, -1, -1, -1, -1, + -1, 372, -1, 374, 375, 376, -1, -1, -1, 256, -1, -1, -1, -1, -1, -1, -1, -1, -1, 390, - -1, -1, -1, -1, 339, -1, -1, -1, -1, 344, - 401, 346, 347, 348, 349, 350, 351, 352, 353, 354, - 355, 356, 413, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 368, -1, 370, -1, 372, 429, 374, - 375, 376, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 256, -1, 390, -1, -1, -1, -1, - -1, 264, 265, 266, 267, -1, 401, 270, 271, -1, - 273, 274, 275, 276, 277, 278, 279, -1, 413, -1, - -1, -1, 285, -1, 287, 288, 289, 290, 291, 292, - -1, -1, 295, -1, 429, -1, 299, 300, -1, 302, - 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 314, -1, 316, -1, 318, 319, -1, -1, 322, - -1, 324, 325, 326, 327, 328, 329, 330, 331, 332, - 333, 334, 335, -1, 337, -1, -1, 340, 341, -1, - -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, - 363, -1, -1, -1, 367, -1, -1, -1, 371, -1, - -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, - -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, - 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 256, -1, -1, -1, 417, 418, 419, 420, 264, 265, - 266, 267, -1, -1, 270, 271, -1, 273, 274, 275, - 276, 277, 278, 279, -1, -1, -1, -1, -1, 285, - -1, 287, 288, 289, 290, 291, 292, -1, -1, 295, - -1, -1, -1, 299, 300, -1, 302, 303, 304, -1, - -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, - 316, -1, 318, 319, -1, -1, 322, -1, 324, 325, - 326, 327, 328, 329, 330, 331, 332, 333, 334, 335, - -1, 337, -1, -1, 340, 341, -1, -1, 344, 345, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, - -1, 367, -1, -1, -1, 371, -1, -1, -1, -1, - 376, 377, 378, 379, 380, -1, -1, -1, 384, -1, - 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, - -1, 417, 418, 419, 420, 264, 265, 266, 267, -1, - -1, 270, 271, -1, 273, 274, 275, 276, 277, 278, - 279, -1, -1, -1, -1, -1, 285, -1, 287, 288, - 289, 290, 291, 292, -1, -1, 295, -1, -1, -1, - 299, 300, -1, 302, 303, 304, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 314, -1, 316, -1, 318, - 319, -1, -1, 322, -1, 324, 325, 326, 327, 328, - 329, 330, 331, 332, 333, 334, 335, -1, 337, -1, - -1, 340, 341, -1, -1, 344, 345, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 359, 360, 361, 362, 363, -1, -1, -1, 367, -1, - -1, -1, 371, -1, -1, -1, -1, 376, 377, 378, - 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, - -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 256, -1, -1, -1, 417, 418, - 419, 420, 264, 265, 266, 267, -1, -1, 270, 271, - -1, 273, 274, 275, 276, 277, 278, 279, -1, -1, - -1, -1, -1, 285, -1, 287, 288, 289, 290, 291, - 292, -1, -1, 295, -1, -1, -1, 299, 300, -1, - 302, 303, 304, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 314, -1, 316, -1, 318, 319, -1, -1, - 322, -1, 324, 325, 326, 327, 328, 329, 330, 331, - 332, 333, 334, 335, -1, 337, -1, -1, 340, 341, - -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, - 362, 363, -1, -1, -1, 367, -1, -1, -1, 371, - -1, -1, -1, -1, 376, 377, 378, 379, 380, -1, - -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, - 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 400, + 401, -1, -1, -1, -1, -1, 339, -1, -1, -1, + -1, 344, 413, 346, 347, 348, 349, 350, 351, 352, + 353, 354, 355, 356, -1, -1, -1, -1, 429, -1, + -1, -1, -1, -1, -1, 368, -1, 370, -1, 372, + -1, 374, 375, 376, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 390, -1, -1, + -1, -1, 339, -1, -1, -1, -1, 344, 401, 346, + 347, 348, 349, 350, 351, 352, 353, 354, 355, 356, + 413, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 368, -1, 370, -1, 372, 429, 374, 375, 376, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 256, -1, -1, -1, 417, 418, 419, 420, 264, - 265, 266, 267, -1, -1, 270, 271, -1, 273, 274, - 275, 276, 277, 278, 279, -1, -1, -1, -1, -1, + -1, 256, -1, 390, -1, -1, -1, -1, -1, 264, + 265, 266, 267, -1, 401, 270, 271, -1, 273, 274, + 275, 276, 277, 278, 279, -1, 413, -1, -1, -1, 285, -1, 287, 288, 289, 290, 291, 292, -1, -1, - 295, -1, -1, -1, 299, 300, -1, 302, 303, 304, + 295, -1, 429, -1, 299, 300, -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, -1, 314, -1, 316, -1, 318, 319, -1, -1, 322, -1, 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, 334, @@ -11434,159 +11502,202 @@ void case_956() -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, -1, - -1, -1, 417, 418, 419, 420, 264, 265, -1, 267, - -1, -1, 270, 271, -1, 256, -1, 275, 276, 277, - -1, 279, -1, -1, 265, -1, 267, 285, -1, 270, - 288, -1, -1, -1, 275, -1, -1, 295, 279, -1, - -1, -1, 300, -1, 302, 303, 304, 288, -1, -1, - -1, -1, -1, -1, 295, -1, -1, -1, 316, 300, - 318, 319, -1, 304, 322, -1, -1, 325, -1, 327, - -1, 329, 330, 331, 332, 316, 334, 318, -1, -1, - -1, 322, -1, 341, -1, -1, 344, 345, -1, 330, - 331, -1, -1, 334, -1, -1, 337, -1, -1, -1, + -1, -1, 417, 418, 419, 420, 264, 265, 266, 267, + -1, -1, 270, 271, -1, 273, 274, 275, 276, 277, + 278, 279, -1, -1, -1, -1, -1, 285, -1, 287, + 288, 289, 290, 291, 292, -1, -1, 295, -1, -1, + -1, 299, 300, -1, 302, 303, 304, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 314, -1, 316, -1, + 318, 319, -1, -1, 322, -1, 324, 325, 326, 327, + 328, 329, 330, 331, 332, 333, 334, 335, -1, 337, + -1, -1, 340, 341, -1, -1, 344, 345, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, 367, - 368, -1, -1, 371, -1, -1, -1, -1, -1, 377, + -1, -1, -1, 371, -1, -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, -1, 417, - 418, 419, 420, 264, 265, -1, 267, -1, -1, 270, - 271, -1, 256, -1, 275, 276, 277, 418, 279, -1, - -1, 265, -1, 267, 285, -1, 270, 288, -1, -1, - -1, 275, -1, -1, 295, 279, -1, -1, -1, 300, - -1, 302, 303, 304, 288, -1, -1, -1, -1, -1, - -1, 295, -1, -1, -1, 316, 300, 318, 319, 320, - 304, 322, -1, -1, 325, -1, 327, -1, 329, 330, - 331, 332, 316, 334, 318, -1, -1, -1, 322, -1, - 341, -1, -1, 344, 345, -1, 330, 331, -1, -1, - 334, -1, -1, 337, -1, -1, -1, -1, 359, 360, + 418, 419, 420, 264, 265, 266, 267, -1, -1, 270, + 271, -1, 273, 274, 275, 276, 277, 278, 279, -1, + -1, -1, -1, -1, 285, -1, 287, 288, 289, 290, + 291, 292, -1, -1, 295, -1, -1, -1, 299, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 314, -1, 316, -1, 318, 319, -1, + -1, 322, -1, 324, 325, 326, 327, 328, 329, 330, + 331, 332, 333, 334, 335, -1, 337, -1, -1, 340, + 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, - 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, + 371, -1, -1, -1, -1, 376, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, - -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, - 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, - 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, - 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, - 295, -1, -1, -1, 418, 300, -1, 302, 303, 304, + -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, - 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, - -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, - 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, - -1, -1, 367, 368, -1, -1, 371, -1, -1, -1, - -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, - -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, + -1, -1, 256, -1, -1, -1, 417, 418, 419, 420, + 264, 265, 266, 267, -1, -1, 270, 271, -1, 273, + 274, 275, 276, 277, 278, 279, -1, -1, -1, -1, + -1, 285, -1, 287, 288, 289, 290, 291, 292, -1, + -1, 295, -1, -1, -1, 299, 300, -1, 302, 303, + 304, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 314, -1, 316, -1, 318, 319, -1, -1, 322, -1, + 324, 325, 326, 327, 328, 329, 330, 331, 332, 333, + 334, 335, -1, 337, -1, -1, 340, 341, -1, -1, + 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, + -1, -1, -1, 367, -1, -1, -1, 371, -1, -1, + -1, -1, 376, 377, 378, 379, 380, -1, -1, -1, + 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, + -1, -1, -1, 417, 418, 419, 420, 264, 265, 266, + 267, -1, -1, 270, 271, -1, 273, 274, 275, 276, + 277, 278, 279, -1, -1, -1, -1, -1, 285, -1, + 287, 288, 289, 290, 291, 292, -1, -1, 295, -1, + -1, -1, 299, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 314, -1, 316, + -1, 318, 319, -1, -1, 322, -1, 324, 325, 326, + 327, 328, 329, 330, 331, 332, 333, 334, 335, -1, + 337, -1, -1, 340, 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 256, -1, 417, 418, 419, 420, -1, -1, 264, 265, - -1, 267, -1, 428, 270, 271, -1, -1, -1, 275, - 276, 277, -1, 279, -1, -1, 265, -1, 267, 285, - -1, 270, 288, -1, -1, -1, 275, -1, -1, 295, - 279, -1, -1, -1, 300, -1, 302, 303, 304, 288, - -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, - 316, 300, 318, 319, -1, 304, 322, -1, -1, 325, - -1, 327, -1, 329, 330, 331, 332, 316, 334, 318, - -1, 337, -1, 322, -1, 341, -1, -1, 344, 345, - -1, 330, 331, -1, -1, 334, -1, -1, 337, -1, - -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, - -1, -1, -1, -1, -1, 371, -1, -1, -1, -1, - -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, - 386, -1, -1, 372, -1, -1, 392, 393, -1, -1, - -1, -1, -1, -1, 264, 265, -1, 267, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + 367, -1, -1, -1, 371, -1, -1, -1, -1, 376, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 256, -1, -1, -1, + 417, 418, 419, 420, 264, 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, 279, - -1, 417, 418, 419, 420, 285, -1, -1, 288, -1, - -1, -1, -1, -1, -1, 295, -1, -1, -1, 418, - 300, -1, 302, 303, 304, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 316, -1, 318, 319, - -1, -1, 322, -1, -1, 325, -1, 327, -1, 329, - 330, 331, 332, -1, 334, -1, -1, -1, -1, -1, - -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, - 360, 361, 362, 363, -1, -1, -1, 367, -1, -1, + -1, -1, 265, -1, 267, 285, -1, 270, 288, -1, + -1, -1, 275, -1, -1, 295, 279, -1, -1, -1, + 300, -1, 302, 303, 304, 288, -1, -1, -1, -1, + -1, -1, 295, -1, -1, -1, 316, 300, 318, 319, + -1, 304, 322, -1, -1, 325, -1, 327, -1, 329, + 330, 331, 332, 316, 334, 318, -1, -1, -1, 322, + -1, 341, -1, -1, 344, 345, -1, 330, 331, -1, + -1, 334, -1, -1, 337, -1, -1, -1, -1, 359, + 360, 361, 362, 363, -1, -1, -1, 367, 368, -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, - 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, + 380, -1, -1, -1, 384, -1, 386, -1, -1, 372, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 256, -1, 417, 418, 419, - 420, -1, -1, 264, 265, -1, 267, -1, 428, 270, - 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, - -1, 265, -1, 267, 285, -1, 270, 288, -1, -1, - -1, 275, -1, -1, 295, 279, -1, -1, -1, 300, - -1, 302, 303, 304, 288, -1, -1, -1, -1, -1, - -1, 295, -1, -1, -1, 316, 300, 318, 319, -1, - 304, 322, -1, -1, 325, -1, 327, -1, 329, 330, - 331, 332, 316, 334, 318, -1, -1, -1, 322, -1, - 341, -1, -1, 344, 345, -1, 330, 331, -1, -1, - 334, -1, -1, 337, -1, -1, -1, -1, 359, 360, - 361, 362, 363, -1, -1, -1, 367, -1, -1, -1, - 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, - -1, -1, -1, 384, -1, 386, 370, -1, -1, -1, - -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 256, -1, -1, -1, 417, 418, 419, 420, - 264, 265, -1, 267, -1, -1, 270, 271, -1, -1, - -1, 275, 276, 277, 418, 279, -1, -1, 265, -1, - 267, 285, -1, 270, 288, -1, -1, -1, 275, -1, - -1, 295, 279, -1, -1, -1, 300, -1, 302, 303, - 304, 288, -1, -1, -1, -1, -1, -1, 295, -1, - -1, -1, 316, 300, 318, 319, -1, 304, 322, -1, - -1, 325, -1, 327, -1, 329, 330, 331, 332, 316, - 334, 318, -1, -1, -1, 322, -1, 341, -1, -1, - 344, 345, -1, 330, 331, -1, -1, 334, -1, -1, - 337, -1, -1, -1, -1, 359, 360, 361, 362, 363, - -1, -1, -1, -1, -1, -1, -1, 371, -1, -1, - -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, - 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 256, - -1, -1, -1, 417, 418, 419, 420, 264, 265, -1, + -1, -1, -1, 256, -1, -1, -1, 417, 418, 419, + 420, 264, 265, -1, 267, -1, -1, 270, 271, -1, + -1, -1, 275, 276, 277, 418, 279, -1, -1, 265, + -1, 267, 285, -1, 270, 288, -1, -1, -1, 275, + -1, -1, 295, 279, -1, -1, -1, 300, -1, 302, + 303, 304, 288, -1, -1, -1, -1, -1, -1, 295, + -1, -1, -1, 316, 300, 318, 319, 320, 304, 322, + -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, + 316, 334, 318, -1, -1, -1, 322, -1, 341, -1, + -1, 344, 345, -1, 330, 331, -1, -1, 334, -1, + -1, 337, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, 367, -1, -1, -1, 371, -1, + -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, 370, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, - 277, 418, 279, -1, -1, -1, -1, -1, 285, -1, + 277, -1, 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, - -1, -1, -1, 300, -1, 302, 303, 304, -1, -1, - -1, -1, -1, -1, -1, 262, -1, -1, -1, 316, + -1, -1, 418, 300, -1, 302, 303, 304, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, - -1, 298, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, - -1, -1, -1, -1, 371, -1, -1, -1, -1, -1, + 367, 368, -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 256, -1, + 417, 418, 419, 420, -1, -1, 264, 265, -1, 267, + -1, 428, 270, 271, -1, -1, -1, 275, 276, 277, + -1, 279, -1, -1, 265, -1, 267, 285, -1, 270, + 288, -1, -1, -1, 275, -1, -1, 295, 279, -1, + -1, -1, 300, -1, 302, 303, 304, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, 316, 300, + 318, 319, -1, 304, 322, -1, -1, 325, -1, 327, + -1, 329, 330, 331, 332, 316, 334, 318, -1, 337, + -1, 322, -1, 341, -1, -1, 344, 345, -1, 330, + 331, -1, -1, 334, -1, -1, 337, -1, -1, -1, + -1, 359, 360, 361, 362, 363, -1, -1, -1, -1, + -1, -1, -1, 371, -1, -1, -1, -1, -1, 377, + 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, + -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, + -1, -1, 264, 265, -1, 267, -1, -1, 270, 271, + -1, -1, -1, 275, 276, 277, -1, 279, -1, 417, + 418, 419, 420, 285, -1, -1, 288, -1, -1, -1, + -1, -1, -1, 295, -1, -1, -1, 418, 300, -1, + 302, 303, 304, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 316, -1, 318, 319, -1, -1, + 322, -1, -1, 325, -1, 327, -1, 329, 330, 331, + 332, -1, 334, -1, -1, -1, -1, -1, -1, 341, + -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, + 362, 363, -1, -1, -1, 367, -1, -1, -1, 371, + -1, -1, -1, -1, -1, 377, 378, 379, 380, -1, + -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, + 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 256, -1, 417, 418, 419, 420, -1, + -1, 264, 265, -1, 267, -1, 428, 270, 271, -1, + -1, -1, 275, 276, 277, -1, 279, -1, -1, 265, + -1, 267, 285, -1, 270, 288, -1, -1, -1, 275, + -1, -1, 295, 279, -1, -1, -1, 300, -1, 302, + 303, 304, 288, -1, -1, -1, -1, -1, -1, 295, + -1, -1, -1, 316, 300, 318, 319, -1, 304, 322, + -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, + 316, 334, 318, -1, -1, -1, 322, -1, 341, -1, + -1, 344, 345, -1, 330, 331, -1, -1, 334, -1, + -1, 337, -1, -1, -1, -1, 359, 360, 361, 362, + 363, -1, -1, -1, 367, -1, -1, -1, 371, -1, + -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, + -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, + 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 417, 418, 419, 420, 371, 372, 373, 374, -1, -1, - -1, 378, 379, -1, -1, 382, 383, 384, 385, 386, - 387, 388, 389, 390, -1, 392, 393, 394, 395, 396, - 397, 398, 399, 400, 401, 402, 403, 404, 405, 406, - 407, 408, 409, 410, 411, 412, 413, -1, 261, -1, - -1, -1, 265, 420, 267, -1, 423, 270, -1, 272, - 273, -1, 275, -1, 277, -1, 279, -1, 281, 282, - 283, 284, -1, -1, 287, 288, -1, -1, -1, -1, - 293, -1, 295, 296, 297, -1, -1, 300, -1, 302, - -1, 304, -1, -1, 307, -1, 309, 310, 311, 312, - -1, -1, -1, 316, 317, 318, -1, -1, 321, 322, - 323, -1, -1, -1, -1, -1, -1, 330, 331, -1, - 333, 334, -1, 336, 337, 338, -1, -1, -1, 342, + 256, -1, -1, -1, 417, 418, 419, 420, 264, 265, + -1, 267, -1, -1, 270, 271, -1, -1, -1, 275, + 276, 277, 418, 279, -1, -1, 265, -1, 267, 285, + -1, 270, 288, -1, -1, -1, 275, -1, -1, 295, + 279, -1, -1, -1, 300, -1, 302, 303, 304, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + 316, 300, 318, 319, -1, 304, 322, -1, -1, 325, + -1, 327, -1, 329, 330, 331, 332, 316, 334, 318, + -1, -1, -1, 322, -1, 341, -1, -1, 344, 345, + -1, 330, 331, -1, -1, 334, -1, -1, 337, -1, + -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, + -1, -1, -1, -1, -1, 371, -1, -1, -1, -1, + -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, + 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 256, -1, -1, + -1, 417, 418, 419, 420, 264, 265, -1, 267, -1, + -1, 270, 271, -1, -1, -1, 275, 276, 277, 418, + 279, -1, -1, -1, -1, -1, 285, -1, -1, 288, + -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, + -1, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, 262, -1, -1, -1, 316, -1, 318, + 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, + 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, + -1, -1, 341, -1, -1, 344, 345, -1, -1, 298, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 261, -1, 362, - -1, 265, -1, 267, -1, 368, 270, -1, 272, 273, - -1, 275, -1, 277, 377, 279, -1, 281, 282, 283, - 284, -1, -1, 287, 288, -1, -1, -1, -1, 293, - -1, 295, 296, 297, -1, -1, 300, -1, 302, -1, - 304, -1, -1, 307, -1, 309, 310, 311, 312, -1, - -1, -1, 316, 317, 318, 418, -1, 321, 322, 323, - -1, -1, -1, -1, -1, -1, 330, 331, -1, 333, - 334, -1, 336, 337, 338, -1, -1, -1, 342, -1, + 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, + -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, + 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, + -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 261, -1, 362, -1, - 265, -1, 267, -1, 368, 270, -1, 272, 273, -1, - 275, -1, 277, 377, 279, -1, 281, 282, 283, 284, + -1, -1, -1, -1, -1, -1, -1, -1, 417, 418, + 419, 420, 371, 372, 373, 374, -1, -1, -1, 378, + 379, -1, -1, 382, 383, 384, 385, 386, 387, 388, + 389, 390, -1, 392, 393, 394, 395, 396, 397, 398, + 399, 400, 401, 402, 403, 404, 405, 406, 407, 408, + 409, 410, 411, 412, 413, -1, 261, -1, -1, -1, + 265, 420, 267, -1, 423, 270, -1, 272, 273, -1, + 275, -1, 277, -1, 279, -1, 281, 282, 283, 284, -1, -1, 287, 288, -1, -1, -1, -1, 293, -1, 295, 296, 297, -1, -1, 300, -1, 302, -1, 304, -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, - -1, 316, 317, 318, 418, -1, 321, 322, 323, -1, + -1, 316, 317, 318, -1, -1, 321, 322, 323, -1, -1, -1, -1, -1, -1, 330, 331, -1, 333, 334, -1, 336, 337, 338, -1, -1, -1, 342, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, @@ -11624,22 +11735,38 @@ void case_956() 261, -1, 333, 302, -1, 336, -1, 338, 307, -1, 309, 310, 311, 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, 284, -1, -1, 357, -1, -1, -1, - -1, 362, -1, -1, 333, -1, 297, 336, 369, 338, + 261, 362, -1, -1, 333, -1, 297, 336, 369, 338, 371, 302, 373, -1, 305, 418, 307, -1, 309, 310, - 311, 312, -1, -1, -1, 386, 317, -1, -1, -1, - 321, -1, -1, 362, 325, -1, -1, -1, -1, -1, - -1, -1, 333, 264, 265, 336, 267, 338, -1, 270, - 271, -1, -1, -1, 275, 276, 277, 418, 279, -1, - -1, -1, -1, -1, 285, -1, -1, 288, -1, -1, - -1, 362, -1, -1, 295, -1, -1, -1, -1, 300, - -1, 302, 303, 304, -1, 306, -1, -1, -1, 418, + 311, 312, -1, 284, -1, 386, 317, -1, -1, -1, + 321, -1, -1, 362, 325, -1, 297, -1, -1, -1, + -1, 302, 333, -1, -1, 336, 307, 338, 309, 310, + 311, 312, -1, -1, -1, -1, 317, 418, -1, -1, + 321, -1, -1, -1, 325, -1, -1, 264, 265, -1, + 267, 362, 333, 270, 271, 336, -1, 338, 275, 276, + 277, -1, 279, -1, -1, -1, -1, -1, 285, -1, + -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, + -1, 362, -1, 300, -1, 302, 303, 304, -1, 306, + -1, -1, -1, -1, -1, -1, 313, -1, -1, 316, + -1, 318, 319, -1, -1, 322, -1, 418, 325, -1, + 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, + -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, + -1, -1, -1, -1, -1, -1, -1, 418, -1, -1, + -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, + -1, -1, -1, -1, 371, 372, -1, 374, -1, -1, + 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, + -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, + -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, + 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, + 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, + -1, -1, -1, -1, 295, -1, -1, -1, -1, 300, + -1, 302, 303, 304, -1, 306, -1, -1, -1, -1, -1, -1, 313, -1, -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, - 341, -1, -1, 344, 345, -1, -1, 418, -1, -1, + 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, - 371, 372, -1, 374, -1, -1, 377, 378, 379, 380, + 371, -1, -1, 374, -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, @@ -11652,17 +11779,17 @@ void case_956() -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, - -1, -1, -1, -1, -1, -1, 371, -1, -1, 374, + -1, -1, -1, -1, -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, 295, -1, -1, -1, - -1, 300, -1, 302, 303, 304, -1, 306, -1, -1, - -1, -1, -1, -1, 313, -1, -1, 316, -1, 318, + -1, 300, -1, 302, 303, 304, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, - 329, 330, 331, 332, -1, 334, -1, -1, -1, -1, + 329, 330, 331, 332, -1, 334, -1, -1, 337, -1, -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, @@ -11676,10 +11803,10 @@ void case_956() 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, 331, 332, - -1, 334, -1, -1, 337, -1, -1, -1, 341, -1, + -1, 334, -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, - 363, -1, -1, -1, -1, -1, -1, -1, 371, -1, + 363, -1, -1, -1, -1, 368, -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, @@ -11693,7 +11820,7 @@ void case_956() -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, -1, -1, - -1, 368, -1, -1, 371, -1, -1, -1, -1, -1, + 367, -1, -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, -1, 270, @@ -11720,7 +11847,7 @@ void case_956() -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, - -1, -1, 367, -1, -1, -1, 371, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 371, -1, -1, -1, -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, @@ -11781,196 +11908,169 @@ void case_956() 265, -1, 267, -1, -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, -1, -1, -1, -1, -1, -1, - 295, -1, -1, -1, -1, 300, -1, 302, 303, 304, + 295, -1, 261, -1, 263, 300, -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 316, -1, 318, 319, -1, -1, 322, -1, -1, - 325, -1, 327, -1, 329, 330, 331, 332, -1, 334, - -1, -1, -1, -1, -1, -1, 341, -1, -1, 344, - 345, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 359, 360, 361, 362, 363, -1, - -1, -1, -1, -1, -1, -1, 371, -1, -1, -1, + -1, 316, -1, 318, 319, 284, -1, 322, -1, -1, + 325, -1, 327, -1, 329, 330, 331, 332, 297, 334, + -1, -1, -1, 302, -1, -1, -1, -1, 307, -1, + 309, 310, 311, 312, -1, -1, -1, -1, 317, -1, + -1, -1, 321, -1, 359, 360, 361, 362, 363, -1, + -1, -1, -1, -1, 333, -1, 371, 336, -1, 338, -1, -1, 377, 378, 379, 380, -1, -1, -1, 384, - -1, 386, -1, -1, -1, -1, -1, 392, 393, -1, - -1, -1, -1, -1, -1, 264, 265, -1, 267, -1, - -1, 270, 271, -1, -1, -1, 275, 276, 277, -1, - 279, -1, 417, 418, 419, 420, 285, -1, -1, 288, - -1, -1, -1, -1, -1, -1, 295, -1, 261, -1, - -1, 300, -1, 302, 303, 304, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 316, -1, 318, - 319, 284, -1, 322, -1, -1, 325, -1, 327, -1, - 329, 330, 331, 332, 297, 334, -1, -1, -1, 302, - -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, - -1, -1, 315, -1, 317, -1, -1, -1, 321, -1, - 359, 360, 361, 362, 363, -1, -1, -1, -1, -1, - 333, -1, 371, 336, -1, 338, -1, -1, 377, 378, - 379, 380, -1, -1, -1, 384, -1, 386, -1, 264, - 265, -1, 267, 392, 393, 270, 271, -1, -1, 362, - 275, 276, 277, -1, 279, 368, 369, -1, -1, -1, - 285, -1, -1, 288, -1, -1, -1, 261, 417, 418, - 295, 420, -1, -1, -1, 300, -1, 302, 303, 304, + -1, 386, -1, 264, 265, -1, 267, 392, 393, 270, + 271, -1, -1, 362, 275, 276, 277, -1, 279, 368, + 369, -1, -1, -1, 285, -1, -1, 288, -1, -1, + -1, -1, 417, 418, 295, 420, -1, -1, -1, 300, + -1, 302, 303, 304, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 316, -1, 318, 319, -1, + -1, 322, -1, -1, 325, -1, 327, -1, 329, 330, + 331, 332, -1, 334, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 284, 316, -1, 318, 319, -1, -1, 322, -1, -1, - 325, -1, 327, 297, 329, 330, 331, 332, 302, 334, - -1, -1, -1, 307, -1, 309, 310, 311, 312, -1, - -1, 315, -1, 317, -1, -1, -1, 321, -1, -1, - -1, -1, -1, -1, 359, 360, 361, 362, 363, 333, - -1, -1, 336, -1, 338, -1, 371, 263, -1, 265, - -1, 267, 377, -1, 270, 380, 272, 273, -1, 275, - -1, 277, -1, 279, -1, 281, 282, 283, 362, -1, - -1, 287, 288, -1, 368, -1, -1, 293, -1, 295, - 296, -1, -1, -1, 300, -1, -1, -1, 304, -1, - -1, -1, 417, 418, -1, 420, -1, -1, -1, 315, - 316, -1, 318, -1, -1, -1, 322, 323, -1, -1, - -1, -1, -1, -1, 330, 331, 264, 265, 334, 267, - -1, 337, 270, 271, -1, -1, 342, 275, 276, 277, - -1, 279, -1, -1, -1, -1, -1, 285, -1, -1, - 288, -1, -1, -1, -1, -1, -1, 295, 364, 365, - -1, -1, 300, -1, 302, 303, 304, -1, -1, -1, - -1, 377, -1, -1, -1, -1, -1, -1, 316, -1, - 318, 319, -1, -1, 322, -1, -1, 325, -1, 327, - -1, 329, 330, 331, 332, -1, 334, -1, -1, 337, - -1, -1, -1, -1, -1, -1, 265, -1, 267, -1, - -1, 270, 418, 272, -1, -1, 275, -1, -1, -1, - 279, 359, 360, 361, 362, -1, -1, -1, -1, 288, - 265, -1, 267, 371, -1, 270, 295, 272, 273, -1, - 275, 300, 277, 302, 279, 304, 281, 282, 283, -1, - -1, -1, 287, 288, -1, -1, -1, 316, 293, 318, - 295, 296, -1, 322, 323, 300, -1, -1, -1, 304, - -1, 330, 331, -1, -1, 334, -1, -1, 337, 417, - 418, 316, -1, 318, -1, -1, -1, 322, 323, -1, - -1, -1, -1, -1, -1, 330, 331, -1, 265, 334, - 267, -1, 337, 270, -1, 272, 273, 342, 275, -1, - 277, -1, 279, -1, 281, 282, 283, -1, -1, -1, - 287, 288, -1, -1, -1, -1, 293, -1, 295, 296, - -1, -1, -1, 300, -1, -1, -1, 304, -1, -1, - -1, -1, 377, -1, -1, -1, -1, -1, -1, 316, - -1, 318, -1, -1, -1, 322, 323, -1, -1, 418, - -1, -1, -1, 330, 331, -1, -1, 334, -1, -1, - 337, -1, 265, -1, 267, 342, -1, 270, -1, -1, - 273, -1, 275, 418, 277, -1, 279, -1, 281, 282, + -1, -1, -1, -1, -1, -1, -1, -1, 359, 360, + 361, 362, 363, -1, -1, -1, -1, -1, -1, -1, + 371, 263, -1, 265, -1, 267, 377, -1, 270, 380, + 272, 273, -1, 275, -1, 277, -1, 279, -1, 281, + 282, 283, -1, -1, -1, 287, 288, -1, -1, -1, + -1, 293, -1, 295, 296, -1, -1, -1, 300, -1, + -1, -1, 304, -1, -1, -1, 417, 418, -1, 420, + -1, -1, -1, 315, 316, -1, 318, -1, -1, -1, + 322, 323, -1, -1, -1, -1, -1, -1, 330, 331, + 264, 265, 334, 267, -1, 337, 270, 271, -1, -1, + 342, 275, 276, 277, -1, 279, -1, -1, -1, -1, + -1, 285, -1, -1, 288, -1, -1, -1, -1, -1, + -1, 295, 364, 365, -1, -1, 300, -1, 302, 303, + 304, -1, -1, -1, -1, 377, -1, -1, -1, -1, + -1, -1, 316, -1, 318, 319, -1, -1, 322, -1, + -1, 325, -1, 327, -1, 329, 330, 331, 332, -1, + 334, -1, -1, 337, -1, -1, -1, -1, -1, -1, + 265, -1, 267, -1, -1, 270, 418, 272, -1, -1, + 275, -1, -1, -1, 279, 359, 360, 361, 362, -1, + -1, -1, -1, 288, 265, -1, 267, 371, -1, 270, + 295, 272, 273, -1, 275, 300, 277, 302, 279, 304, + 281, 282, 283, -1, -1, -1, 287, 288, -1, -1, + -1, 316, 293, 318, 295, 296, -1, 322, 323, 300, + -1, -1, -1, 304, -1, 330, 331, -1, -1, 334, + -1, -1, 337, 417, 418, 316, -1, 318, -1, -1, + -1, 322, 323, -1, -1, -1, -1, -1, -1, 330, + 331, -1, 265, 334, 267, -1, 337, 270, -1, 272, + 273, 342, 275, -1, 277, -1, 279, -1, 281, 282, 283, -1, -1, -1, 287, 288, -1, -1, -1, -1, - 293, -1, 295, -1, 265, -1, 267, 300, -1, 270, - -1, 304, 273, -1, 275, -1, 277, -1, 279, -1, - 281, 282, 283, 316, -1, 318, 287, 288, -1, 322, - -1, -1, 293, -1, 295, -1, -1, 330, 331, 300, - -1, 334, -1, 304, 337, -1, -1, -1, 265, 342, - 267, 418, -1, 270, -1, 316, -1, 318, 275, -1, - -1, 322, 279, -1, -1, -1, -1, -1, -1, 330, - 331, 288, -1, 334, -1, -1, 337, -1, 295, -1, - 265, 342, 267, 300, 377, 270, -1, 304, -1, 306, + 293, -1, 295, 296, -1, -1, -1, 300, -1, -1, + -1, 304, -1, -1, -1, -1, 377, -1, -1, -1, + -1, -1, -1, 316, -1, 318, -1, -1, -1, 322, + 323, -1, -1, 418, -1, -1, -1, 330, 331, -1, + -1, 334, -1, -1, 337, -1, 265, -1, 267, 342, + -1, 270, -1, -1, 273, -1, 275, 418, 277, -1, + 279, -1, 281, 282, 283, -1, -1, -1, 287, 288, + -1, -1, -1, -1, 293, -1, 295, -1, 265, -1, + 267, 300, -1, 270, -1, 304, 273, -1, 275, -1, + 277, -1, 279, -1, 281, 282, 283, 316, -1, 318, + 287, 288, -1, 322, -1, -1, 293, -1, 295, -1, + -1, 330, 331, 300, -1, 334, -1, 304, 337, -1, + -1, -1, 265, 342, 267, 418, -1, 270, -1, 316, + -1, 318, 275, -1, -1, 322, 279, -1, -1, -1, + -1, -1, -1, 330, 331, 288, -1, 334, -1, -1, + 337, -1, 295, -1, 265, 342, 267, 300, 377, 270, + -1, 304, -1, 306, 275, 308, -1, -1, 279, -1, + 313, -1, -1, 316, -1, 318, -1, 288, -1, 322, + -1, -1, 325, -1, 295, -1, -1, 330, 331, 300, + -1, 334, -1, 304, 337, 306, -1, 308, 265, 418, + 267, -1, 313, 270, -1, 316, -1, 318, 275, -1, + -1, 322, 279, -1, 325, -1, -1, -1, -1, 330, + 331, 288, -1, 334, -1, -1, 337, -1, 295, 372, + 265, 418, 267, 300, -1, 270, -1, 304, -1, 306, 275, 308, -1, -1, 279, -1, 313, -1, -1, 316, - -1, 318, -1, 288, -1, 322, -1, -1, 325, -1, + -1, 318, -1, 288, -1, 322, -1, -1, 325, 370, 295, -1, -1, 330, 331, 300, -1, 334, -1, 304, - 337, 306, -1, 308, 265, 418, 267, -1, 313, 270, - -1, 316, -1, 318, 275, -1, -1, 322, 279, -1, - 325, -1, -1, -1, -1, 330, 331, 288, -1, 334, - -1, -1, 337, -1, 295, 372, 265, 418, 267, 300, - -1, 270, -1, 304, -1, 306, 275, 308, -1, -1, - 279, -1, 313, -1, -1, 316, -1, 318, -1, 288, - -1, 322, -1, -1, 325, 370, 295, -1, -1, 330, - 331, 300, -1, 334, -1, 304, 337, 306, -1, -1, - -1, 418, -1, -1, 313, -1, -1, 316, -1, 318, - -1, -1, -1, 322, -1, -1, 325, -1, -1, -1, - -1, 330, 331, -1, -1, 334, -1, 265, 337, 267, - -1, -1, 270, 418, -1, -1, -1, 275, -1, -1, - -1, 279, -1, -1, -1, 283, 265, -1, 267, -1, - 288, 270, -1, -1, -1, 293, 275, 295, -1, -1, - 279, -1, 300, -1, -1, -1, 304, 305, -1, 288, - -1, -1, -1, -1, -1, -1, 295, 418, 316, -1, - 318, 300, -1, -1, 322, 304, -1, -1, -1, -1, - -1, -1, 330, 331, -1, -1, 334, 316, -1, 318, - 265, -1, 267, 322, -1, 270, -1, -1, -1, 418, - 275, 330, 331, -1, 279, 334, -1, 265, 337, 267, - -1, -1, 270, 288, -1, -1, -1, 275, -1, -1, - 295, 279, -1, -1, -1, 300, -1, -1, -1, 304, - 288, -1, -1, -1, -1, -1, -1, 295, -1, -1, - -1, 316, 300, 318, -1, -1, 304, 322, -1, -1, - -1, -1, -1, -1, -1, 330, 331, -1, 316, 334, - 318, 265, 337, 267, 322, -1, 270, -1, -1, -1, - 418, 275, 330, 331, -1, 279, 334, -1, -1, 337, - -1, -1, -1, -1, 288, 265, -1, 267, -1, 418, - 270, 295, -1, -1, -1, 275, 300, -1, -1, 279, - 304, -1, -1, -1, -1, -1, -1, -1, 288, -1, - -1, -1, 316, -1, 318, 295, -1, -1, 322, -1, - 300, -1, -1, -1, 304, -1, 330, 331, -1, -1, - 334, -1, -1, 337, -1, 265, 316, 267, 318, -1, - 270, -1, 322, 418, -1, 275, -1, -1, -1, 279, - 330, 331, -1, -1, 334, -1, -1, 337, 288, 265, - 418, 267, -1, -1, 270, 295, -1, -1, -1, 275, + 337, 306, -1, -1, -1, 418, -1, -1, 313, -1, + -1, 316, -1, 318, -1, -1, -1, 322, -1, -1, + 325, -1, -1, -1, -1, 330, 331, -1, -1, 334, + -1, 265, 337, 267, -1, -1, 270, 418, -1, -1, + -1, 275, -1, -1, -1, 279, -1, -1, -1, 283, + 265, -1, 267, -1, 288, 270, -1, -1, -1, 293, + 275, 295, -1, -1, 279, -1, 300, -1, -1, -1, + 304, 305, -1, 288, -1, -1, -1, -1, -1, -1, + 295, 418, 316, -1, 318, 300, -1, -1, 322, 304, + -1, -1, -1, -1, -1, -1, 330, 331, -1, -1, + 334, 316, -1, 318, 265, -1, 267, 322, -1, 270, + -1, -1, -1, 418, 275, 330, 331, -1, 279, 334, + -1, 265, 337, 267, -1, -1, 270, 288, -1, -1, + -1, 275, -1, -1, 295, 279, -1, -1, -1, 300, + -1, -1, -1, 304, 288, -1, -1, -1, -1, -1, + -1, 295, -1, -1, -1, 316, 300, 318, -1, -1, + 304, 322, -1, -1, -1, -1, -1, -1, -1, 330, + 331, -1, 316, 334, 318, 265, 337, 267, 322, -1, + 270, -1, -1, -1, 418, 275, 330, 331, -1, 279, + 334, -1, -1, 337, -1, -1, -1, -1, 288, 265, + -1, 267, -1, 418, 270, 295, -1, -1, -1, 275, 300, -1, -1, 279, 304, -1, -1, -1, -1, -1, -1, -1, 288, -1, -1, -1, 316, -1, 318, 295, -1, -1, 322, -1, 300, -1, -1, -1, 304, -1, - 330, 331, -1, -1, 334, -1, -1, 337, -1, -1, - 316, -1, 318, 265, 418, 267, 322, -1, 270, -1, - -1, -1, -1, 275, 330, 331, -1, 279, 334, -1, - 265, 337, 267, -1, -1, 270, 288, -1, 418, -1, - 275, -1, -1, 295, 279, -1, -1, -1, 300, -1, - -1, -1, 304, 288, -1, -1, -1, -1, -1, -1, - 295, -1, -1, -1, 316, 300, 318, -1, -1, 304, - 322, -1, -1, -1, -1, -1, -1, -1, 330, 331, - -1, 316, 334, 318, 265, 337, 267, 322, 418, 270, - -1, -1, -1, -1, 275, 330, 331, -1, 279, 334, - -1, -1, 337, -1, -1, -1, -1, 288, 265, -1, - 267, -1, 418, 270, 295, -1, -1, -1, 275, 300, - -1, -1, 279, 304, -1, -1, -1, -1, -1, -1, - -1, 288, -1, -1, -1, 316, -1, 318, 295, -1, - -1, 322, -1, 300, -1, -1, -1, 304, -1, 330, - 331, -1, 261, 334, -1, -1, 337, -1, -1, 316, - -1, 318, -1, 272, -1, 322, 418, -1, 277, -1, - -1, -1, 281, 330, 331, 284, -1, 334, -1, -1, - 337, -1, -1, 418, -1, -1, -1, 296, 297, -1, - -1, -1, 301, 302, -1, 261, -1, -1, 307, -1, - 309, 310, 311, 312, -1, -1, 272, -1, 317, -1, - -1, 277, 321, -1, 323, 281, -1, -1, 284, -1, - -1, -1, -1, -1, 333, -1, 335, 336, -1, 338, - 296, 297, -1, 342, -1, 301, 302, 418, -1, -1, - -1, 307, -1, 309, 310, 311, 312, -1, -1, -1, - -1, 317, -1, 362, -1, 321, -1, 323, -1, 368, - 369, 418, -1, 261, -1, 263, -1, 333, -1, -1, - 336, -1, 338, -1, -1, -1, 342, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 284, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 362, -1, -1, 297, - -1, -1, 368, 369, 302, -1, 261, -1, -1, 307, + 330, 331, -1, -1, 334, -1, -1, 337, -1, 265, + 316, 267, 318, -1, 270, -1, 322, 418, -1, 275, + -1, -1, -1, 279, 330, 331, -1, -1, 334, -1, + -1, 337, 288, 265, 418, 267, -1, -1, 270, 295, + -1, -1, -1, 275, 300, -1, -1, 279, 304, -1, + -1, -1, -1, -1, -1, -1, 288, -1, -1, -1, + 316, -1, 318, 295, -1, -1, 322, -1, 300, -1, + -1, -1, 304, -1, 330, 331, -1, -1, 334, -1, + -1, 337, -1, -1, 316, -1, 318, 265, 418, 267, + 322, -1, 270, -1, -1, -1, -1, 275, 330, 331, + -1, 279, 334, -1, 265, 337, 267, -1, -1, 270, + 288, -1, 418, -1, 275, -1, -1, 295, 279, -1, + -1, -1, 300, -1, -1, -1, 304, 288, -1, -1, + -1, 261, -1, -1, 295, -1, -1, -1, 316, 300, + 318, -1, 272, 304, 322, -1, -1, 277, -1, -1, + -1, 281, 330, 331, 284, 316, 334, 318, -1, 337, + -1, 322, 418, -1, -1, -1, 296, 297, -1, 330, + 331, 301, 302, 334, 261, -1, 337, 307, -1, 309, + 310, 311, 312, -1, -1, 272, 418, 317, -1, -1, + 277, 321, -1, 323, 281, -1, -1, 284, -1, -1, + -1, -1, -1, 333, -1, 335, 336, -1, 338, 296, + 297, -1, 342, -1, 301, 302, -1, -1, -1, -1, + 307, -1, 309, 310, 311, 312, -1, -1, -1, -1, + 317, -1, 362, -1, 321, -1, 323, -1, 368, 369, + 418, -1, -1, 261, -1, -1, 333, -1, -1, 336, + -1, 338, -1, -1, 272, 342, -1, 418, -1, 277, + -1, -1, -1, 281, -1, -1, 284, -1, -1, -1, + -1, -1, -1, -1, -1, 362, -1, -1, 296, 297, + -1, 368, 369, 301, 302, -1, 261, -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, 272, -1, 317, - -1, -1, 277, 321, -1, -1, 281, -1, -1, 284, + -1, -1, 277, 321, -1, 323, 281, -1, -1, 284, -1, -1, -1, -1, -1, 333, -1, -1, 336, -1, - 338, 296, 297, -1, -1, -1, 301, 302, -1, 261, + 338, 296, 297, -1, 342, -1, 301, 302, 261, -1, -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, - 272, -1, 317, -1, 362, 277, 321, -1, 323, 281, - 368, 369, 284, -1, -1, -1, -1, -1, 333, -1, - -1, 336, -1, 338, 296, 297, -1, 342, -1, 301, - 302, 261, -1, -1, -1, 307, -1, 309, 310, 311, - 312, -1, -1, -1, -1, 317, -1, 362, -1, 321, - -1, 323, -1, 368, 284, -1, -1, -1, -1, -1, - -1, 333, -1, -1, 336, -1, 338, 297, -1, 261, - 342, -1, 302, -1, -1, -1, -1, 307, -1, 309, - 310, 311, 312, -1, -1, -1, -1, 317, -1, -1, - 362, 321, 284, -1, -1, -1, 368, -1, -1, -1, - -1, -1, -1, 333, -1, 297, 336, 261, 338, 263, - 302, -1, -1, -1, -1, 307, -1, 309, 310, 311, - 312, -1, -1, -1, -1, 317, -1, -1, -1, 321, - 284, -1, 362, -1, 364, 365, -1, -1, 368, -1, - -1, 333, -1, 297, 336, 261, 338, -1, 302, -1, - -1, -1, -1, 307, -1, 309, 310, 311, 312, -1, - -1, -1, -1, 317, -1, -1, -1, 321, 284, -1, - 362, -1, 364, 365, -1, 261, 368, -1, -1, 333, - -1, 297, 336, -1, 338, -1, 302, -1, -1, -1, - -1, 307, -1, 309, 310, 311, 312, -1, 284, -1, - -1, 317, -1, -1, -1, 321, -1, -1, 362, -1, - -1, 297, -1, -1, 368, 301, 302, 333, 261, -1, - 336, 307, 338, 309, 310, 311, 312, -1, -1, -1, - -1, 317, -1, -1, -1, 321, -1, -1, -1, -1, - -1, 284, -1, -1, -1, -1, 362, 333, 364, 365, - 336, -1, 338, -1, 297, -1, -1, -1, -1, 302, + -1, -1, 317, -1, 362, -1, 321, -1, 323, -1, + 368, 284, -1, -1, -1, -1, -1, -1, 333, -1, + -1, 336, -1, 338, 297, -1, 261, 342, -1, 302, -1, -1, -1, -1, 307, -1, 309, 310, 311, 312, - -1, -1, -1, -1, 317, -1, 362, -1, 321, -1, + -1, -1, -1, -1, 317, -1, -1, 362, 321, 284, + -1, -1, -1, 368, -1, -1, -1, -1, -1, -1, + 333, -1, 297, 336, 261, 338, 263, 302, -1, -1, + -1, -1, 307, -1, 309, 310, 311, 312, -1, -1, + -1, -1, 317, -1, -1, -1, 321, 284, -1, 362, + -1, 364, 365, -1, -1, 368, -1, -1, 333, -1, + 297, 336, 261, 338, -1, 302, -1, -1, -1, -1, + 307, -1, 309, 310, 311, 312, -1, -1, -1, -1, + 317, -1, -1, -1, 321, 284, -1, 362, -1, 364, + 365, -1, 261, 368, 263, -1, 333, -1, 297, 336, + -1, 338, -1, 302, -1, -1, -1, -1, 307, -1, + 309, 310, 311, 312, -1, 284, -1, -1, 317, -1, + -1, -1, 321, -1, -1, 362, -1, -1, 297, -1, + -1, 368, 261, 302, 333, -1, -1, 336, 307, 338, + 309, 310, 311, 312, -1, -1, 315, -1, 317, -1, + -1, -1, 321, -1, -1, 284, -1, -1, -1, -1, + -1, -1, -1, 362, 333, 364, 365, 336, 297, 338, + -1, -1, 301, 302, -1, -1, -1, -1, 307, -1, + 309, 310, 311, 312, -1, -1, -1, -1, 317, -1, + -1, -1, 321, 362, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 333, -1, -1, 336, -1, 338, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 333, -1, -1, 336, -1, 338, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 362, + -1, -1, -1, 362, }; -#line 6263 "cs-parser.jay" +#line 6352 "cs-parser.jay" // // A class used to hold info about an operator declarator @@ -12029,6 +12129,11 @@ void Error_NamedArgumentExpected (NamedArgument a) report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); } +void Error_MissingInitializer (Location loc) +{ + report.Error (210, loc, "You must provide an initializer in a fixed or using statement declaration"); +} + void push_current_class (TypeContainer tc, object partial_token) { if (module.Evaluator != null && current_container is ModuleContainer){ @@ -12284,6 +12389,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync oob_stack.Push (current_anonymous_method); oob_stack.Push (current_local_parameters); oob_stack.Push (current_variable); + oob_stack.Push (lexer.async_block); current_local_parameters = parameters; if (isLambda) { @@ -12298,6 +12404,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync current_anonymous_method = new AnonymousMethodExpression (isAsync, loc); } + lexer.async_block = isAsync; // Force the next block to be created as a ToplevelBlock parsing_anonymous_method = true; } @@ -12313,6 +12420,7 @@ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) current_anonymous_method.Block = anon_block; retval = current_anonymous_method; + lexer.async_block = (bool) oob_stack.Pop (); current_variable = (BlockVariableDeclaration) oob_stack.Pop (); current_local_parameters = (ParametersCompiled) oob_stack.Pop (); current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay b/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay similarity index 94% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay index 5e6f9e909..09def5b04 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-parser.jay +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-parser.jay @@ -2,14 +2,15 @@ // // cs-parser.jay: The Parser for the C# compiler // -// Authors: Miguel de Icaza (miguel@gnu.org) +// Authors: Miguel de Icaza (miguel@gnome.org) // Ravi Pratap (ravi@ximian.com) -// Marek Safar (marek.safar@gmail.com) +// Marek Safar (marek.safar@gmail.com) // // Dual Licensed under the terms of the GNU GPL and the MIT X11 license // // (C) 2001 Ximian, Inc (http://www.ximian.com) -// (C) 2004 Novell, Inc +// (C) 2004-2011 Novell, Inc +// Copyright 2011 Xamarin Inc. // // TODO: // (1) Figure out why error productions dont work. `type-declaration' is a @@ -143,8 +144,12 @@ namespace Mono.CSharp UsingsBag ubag; List> mod_locations; Location parameterModifierLocation, savedLocation, savedOpenLocation, savedCloseLocation; - Location savedAttrParenOpenLocation, savedAttrParenCloseLocation; + Location savedAttrParenOpenLocation, savedAttrParenCloseLocation, savedOperatorLocation; Stack> locationListStack = new Stack> (); // used for type parameters + List attributeCommas = new List (); + List attributeArgumentCommas = new List (); + List parameterListCommas = new List (); + List enumCommas = new List (); object lastYYVal; @@ -541,16 +546,14 @@ namespace_declaration } opt_extern_alias_directives opt_using_directives opt_namespace_or_type_declarations CLOSE_BRACE opt_semicolon { - if ($11 != null) - lbag.AddLocation (current_namespace, GetLocation ($2), GetLocation ($5), GetLocation ($10), GetLocation ($11)); - else - lbag.AddLocation (current_namespace, GetLocation ($2), GetLocation ($5), GetLocation ($10)); - current_namespace = current_namespace.Parent; current_class = current_namespace.SlaveDeclSpace; current_container = current_class.PartialContainer; ubag.CloseNamespace (GetLocation ($10)); - ubag.EndNamespace (GetLocation ($10)); + if ($11 != null) + ubag.EndNamespace (GetLocation ($11)); + else + ubag.EndNamespace (); } ; @@ -563,7 +566,9 @@ qualified_identifier | qualified_identifier DOT IDENTIFIER { var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberName ((MemberName) $1, lt.Value, lt.Location); + $$ = new MemberName ((MemberName) $1, lt.Value, lt.Location) { + DotLocation = GetLocation ($2) + }; } | error { @@ -669,17 +674,24 @@ attribute_sections { var sect = (List) $1; $$ = new Attributes (sect); - lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); + if (locationListStack.Count > 0) + lbag.AddLocation (sect, locationListStack.Pop ()); + if (attributeCommas.Count > 0) { + lbag.AppendTo (sect, attributeCommas); + attributeCommas.Clear (); + } } | attribute_sections attribute_section { Attributes attrs = $1 as Attributes; var sect = (List) $2; + + if (locationListStack.Count > 0) + lbag.AddLocation (sect, locationListStack.Pop ()); if (attrs == null) attrs = new Attributes (sect); else attrs.AddAttributes (sect); - lbag.AddLocation (sect, savedOpenLocation, savedCloseLocation); $$ = attrs; } ; @@ -715,12 +727,20 @@ attribute_section_cont current_attr_target = null; lexer.parsing_attribute_section = false; - savedCloseLocation = GetLocation ($6); + if ($5 != null) { + locationListStack.Push (new List(new [] { savedOpenLocation, savedCloseLocation, GetLocation ($2), GetLocation ($5), GetLocation ($6) })); + } else { + locationListStack.Push (new List(new [] { savedOpenLocation, savedCloseLocation, GetLocation ($2), GetLocation ($6) })); + } } | attribute_list opt_comma CLOSE_BRACKET { $$ = $1; - savedCloseLocation = GetLocation ($3); + if ($2 != null) { + locationListStack.Push (new List(new [] { savedOpenLocation, GetLocation ($2), GetLocation ($3) })); + } else { + locationListStack.Push (new List(new [] { savedOpenLocation, GetLocation ($3) })); + } } ; @@ -729,9 +749,10 @@ attribute_target { var lt = (Tokenizer.LocatedToken) $1; $$ = CheckAttributeTarget (lt.Value, lt.Location); + savedCloseLocation = GetLocation ($1); } - | EVENT { $$ = "event"; } - | RETURN { $$ = "return"; } + | EVENT { $$ = "event"; savedCloseLocation = GetLocation ($1); } + | RETURN { $$ = "return"; savedCloseLocation = GetLocation ($1); } | error { if (yyToken == Token.IDENTIFIER) { @@ -753,6 +774,7 @@ attribute_list { var attrs = (List) $1; attrs.Add ((Attribute) $3); + attributeCommas.Add (GetLocation ($2)); $$ = attrs; } @@ -776,7 +798,10 @@ attribute ATypeNameExpression expr = mname.GetTypeExpression (); $$ = new Attribute (current_attr_target, expr, arguments, mname.Location, lexer.IsEscapedIdentifier (mname)); if (arguments != null) { - lbag.AddLocation ($$, savedAttrParenOpenLocation, savedAttrParenCloseLocation); + attributeArgumentCommas.Insert (0, savedAttrParenOpenLocation); + attributeArgumentCommas.Add (savedAttrParenCloseLocation); + lbag.AddLocation ($$, attributeArgumentCommas); + attributeArgumentCommas.Clear (); } } ; @@ -823,7 +848,7 @@ attribute_arguments Error_NamedArgumentExpected ((NamedArgument) args [args.Count - 1]); args.Add ((Argument) $3); - lbag.AppendTo (args, GetLocation ($2)); + attributeArgumentCommas.Add (GetLocation ($2)); } | attribute_arguments COMMA named_attribute_argument { @@ -833,7 +858,7 @@ attribute_arguments } ((Arguments) o [1]).Add ((Argument) $3); - lbag.AppendTo (o[1], GetLocation ($2)); + attributeArgumentCommas.Add (GetLocation ($2)); } ; @@ -870,6 +895,7 @@ named_argument var lt = (Tokenizer.LocatedToken) $1; $$ = new NamedArgument (lt.Value, lt.Location, (Expression) $4, arg_mod); + lbag.AddLocation ($$, GetLocation($2)); } ; @@ -892,8 +918,13 @@ opt_class_member_declarations class_member_declarations : class_member_declaration - | class_member_declarations - class_member_declaration + { + lexer.parsing_modifiers = true; + } + | class_member_declarations class_member_declaration + { + lexer.parsing_modifiers = true; + } ; class_member_declaration @@ -928,6 +959,7 @@ struct_declaration { MemberName name = MakeName ((MemberName) $6); push_current_class (new Struct (current_namespace, current_class, name, (Modifiers) $2, (Attributes) $1), $3); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); } opt_class_base opt_type_parameter_constraints_clauses @@ -939,17 +971,25 @@ struct_declaration if (doc_support) current_container.DocComment = Lexer.consume_doc_comment (); - lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); + + lexer.parsing_modifiers = true; } - struct_body + OPEN_BRACE { - --lexer.parsing_declaration; + if (doc_support) + Lexer.doc_state = XmlCommentState.Allowed; + } + opt_class_member_declarations CLOSE_BRACE + { + lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13)); + --lexer.parsing_declaration; if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; } opt_semicolon { - lbag.AppendToMember (current_class, GetLocation ($13)); + if ($15 != null) + current_class.OptionalSemicolon = GetLocation ($15); $$ = pop_current_class (); } | opt_attributes opt_modifiers opt_partial STRUCT error @@ -957,46 +997,6 @@ struct_declaration Error_SyntaxError (yyToken); } ; - -struct_body - : OPEN_BRACE - { - if (doc_support) - Lexer.doc_state = XmlCommentState.Allowed; - } - opt_struct_member_declarations CLOSE_BRACE - { - lbag.AppendToMember (current_class, GetLocation ($1), GetLocation ($4)); - } - ; - -opt_struct_member_declarations - : /* empty */ - | struct_member_declarations - ; - -struct_member_declarations - : struct_member_declaration - | struct_member_declarations struct_member_declaration - ; - -struct_member_declaration - : constant_declaration - | field_declaration - | method_declaration - | property_declaration - | event_declaration - | indexer_declaration - | operator_declaration - | constructor_declaration - | type_declaration - - /* - * This is only included so we can flag error 575: - * destructors only allowed on class types - */ - | destructor_declaration - ; constant_declaration : opt_attributes @@ -1252,15 +1252,19 @@ method_declaration if (doc_support) Lexer.doc_state = XmlCommentState.NotAllowed; - // Add it early in the case of body being eof for full aot - current_container.AddMethod ((Method) $1); + // Add it early in the case of body being eof for full ast + Method m = (Method) $1; + lexer.async_block = (m.ModFlags & Modifiers.ASYNC) != 0; + current_container.AddMethod (m); } method_body { Method method = (Method) $1; method.Block = (ToplevelBlock) $3; + lexer.async_block = false; if (method.Block == null) { + lbag.AppendToMember (method, savedLocation); // semicolon method.ParameterInfo.CheckParameters (method); if ((method.ModFlags & Modifiers.ASYNC) != 0) { @@ -1416,7 +1420,7 @@ method_header method_body : block - | SEMICOLON { $$ = null; } + | SEMICOLON { savedLocation = GetLocation ($1); $$ = null; } ; opt_formal_parameter_list @@ -1429,20 +1433,25 @@ formal_parameter_list { var pars_list = (List) $1; $$ = new ParametersCompiled (pars_list.ToArray ()); - lbag.AddLocation ($$, lbag.GetLocations (pars_list)); + lbag.AddLocation ($$, parameterListCommas); } | fixed_parameters COMMA parameter_array { var pars_list = (List) $1; pars_list.Add ((Parameter) $3); - + parameterListCommas.Add (GetLocation ($2)); + $$ = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation ($$, parameterListCommas); } | fixed_parameters COMMA arglist_modifier { var pars_list = (List) $1; pars_list.Add (new ArglistParameter (GetLocation ($3))); + parameterListCommas.Add (GetLocation ($2)); + $$ = new ParametersCompiled (pars_list.ToArray (), true); + lbag.AddLocation ($$, parameterListCommas); } | parameter_array COMMA error { @@ -1450,6 +1459,7 @@ formal_parameter_list report.Error (231, ((Parameter) $1).Location, "A params parameter must be the last parameter in a formal parameter list"); $$ = new ParametersCompiled (new Parameter[] { (Parameter) $1 } ); + lbag.AddLocation ($$, parameterListCommas); } | fixed_parameters COMMA parameter_array COMMA error { @@ -1458,14 +1468,18 @@ formal_parameter_list var pars_list = (List) $1; pars_list.Add (new ArglistParameter (GetLocation ($3))); - + parameterListCommas.Add (GetLocation ($2)); + parameterListCommas.Add (GetLocation ($4)); + $$ = new ParametersCompiled (pars_list.ToArray (), true); + lbag.AddLocation ($$, parameterListCommas); } | arglist_modifier COMMA error { report.Error (257, GetLocation ($1), "An __arglist parameter must be the last parameter in a formal parameter list"); $$ = new ParametersCompiled (new Parameter [] { new ArglistParameter (GetLocation ($1)) }, true); + lbag.AddLocation ($$, parameterListCommas); } | fixed_parameters COMMA ARGLIST COMMA error { @@ -1473,8 +1487,11 @@ formal_parameter_list var pars_list = (List) $1; pars_list.Add (new ArglistParameter (GetLocation ($3))); + parameterListCommas.Add (GetLocation ($2)); + parameterListCommas.Add (GetLocation ($4)); $$ = new ParametersCompiled (pars_list.ToArray (), true); + lbag.AddLocation ($$, parameterListCommas); } | parameter_array { @@ -1497,7 +1514,7 @@ fixed_parameters parameters_bucket.Clear (); Parameter p = (Parameter) $1; parameters_bucket.Add (p); - + parameterListCommas.Clear (); default_parameter_used = p.HasDefaultValue; $$ = parameters_bucket; } @@ -1514,7 +1531,7 @@ fixed_parameters default_parameter_used |= p.HasDefaultValue; pars.Add (p); - lbag.AppendTo (pars, GetLocation ($2)); + parameterListCommas.Add (GetLocation ($2)); } $$ = $1; @@ -1607,7 +1624,6 @@ parameter_modifiers : parameter_modifier { $$ = $1; - parameterModifierLocation = GetLocation ($1); } | parameter_modifiers parameter_modifier { @@ -1637,14 +1653,14 @@ parameter_modifier { if ((valid_param_mod & ParameterModifierType.Ref) == 0) Error_ParameterModifierNotValid ("ref", GetLocation ($1)); - + parameterModifierLocation = GetLocation ($1); $$ = Parameter.Modifier.REF; } | OUT { if ((valid_param_mod & ParameterModifierType.Out) == 0) Error_ParameterModifierNotValid ("out", GetLocation ($1)); - + parameterModifierLocation = GetLocation ($1); $$ = Parameter.Modifier.OUT; } | THIS @@ -1654,7 +1670,7 @@ parameter_modifier if (lang_version <= LanguageVersion.ISO_2) FeatureIsNotAvailable (GetLocation ($1), "extension methods"); - + parameterModifierLocation = GetLocation ($1); $$ = Parameter.Modifier.This; } ; @@ -1664,6 +1680,7 @@ parameter_array { var lt = (Tokenizer.LocatedToken) $4; $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, savedLocation); } | opt_attributes params_modifier type IDENTIFIER ASSIGN constant_expression { @@ -1671,6 +1688,7 @@ parameter_array var lt = (Tokenizer.LocatedToken) $4; $$ = new ParamsParameter ((FullNamedExpression) $3, lt.Value, (Attributes) $1, lt.Location); + lbag.AddLocation ($$, savedLocation); } | opt_attributes params_modifier type error { @@ -1684,6 +1702,7 @@ params_modifier { if ((valid_param_mod & ParameterModifierType.Params) == 0) report.Error (1670, (GetLocation ($1)), "The `params' modifier is not allowed in current context"); + savedLocation = GetLocation ($1); } | PARAMS parameter_modifier { @@ -1693,6 +1712,7 @@ params_modifier } else { report.Error (1611, GetLocation ($1), "The params parameter cannot be declared as ref or out"); } + savedLocation = GetLocation ($1); } | PARAMS params_modifier { @@ -1833,7 +1853,6 @@ get_accessor_declaration } current_local_parameters = current_property.Get.ParameterInfo; - lbag.AddMember (current_property.Get, GetModifierLocations ()); lexer.PropertyParsing = false; } accessor_body @@ -1844,7 +1863,10 @@ get_accessor_declaration if (current_container.Kind == MemberKind.Interface) { report.Error (531, current_property.Get.Block.StartLocation, "`{0}': interface members cannot have a definition", current_property.Get.GetSignatureForError ()); - } + } + lbag.AddMember (current_property.Get, GetModifierLocations ()); + } else { + lbag.AddMember (current_property.Get, GetModifierLocations (), savedLocation); } current_local_parameters = null; @@ -1881,7 +1903,6 @@ set_accessor_declaration } current_local_parameters = current_property.Set.ParameterInfo; - lbag.AddMember (current_property.Set, GetModifierLocations ()); lexer.PropertyParsing = false; } accessor_body @@ -1893,6 +1914,9 @@ set_accessor_declaration report.Error (531, current_property.Set.Block.StartLocation, "`{0}': interface members cannot have a definition", current_property.Set.GetSignatureForError ()); } + lbag.AddMember (current_property.Set, GetModifierLocations ()); + } else { + lbag.AddMember (current_property.Set, GetModifierLocations (), savedLocation); } current_local_parameters = null; @@ -1908,7 +1932,7 @@ accessor_body : block | SEMICOLON { - lbag.AppendToMember (lbag.LastMember, GetLocation ($1)); + savedLocation = GetLocation ($1); $$ = null; } | error @@ -1943,6 +1967,8 @@ interface_declaration current_container.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } + + lexer.parsing_modifiers = true; } OPEN_BRACE opt_interface_member_declarations CLOSE_BRACE { @@ -1952,7 +1978,9 @@ interface_declaration } opt_semicolon { - lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13)); + if ($15 != null) + current_class.OptionalSemicolon = GetLocation ($15); + lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13)); $$ = pop_current_class (); } | opt_attributes opt_modifiers opt_partial INTERFACE error @@ -1968,7 +1996,13 @@ opt_interface_member_declarations interface_member_declarations : interface_member_declaration + { + lexer.parsing_modifiers = true; + } | interface_member_declarations interface_member_declaration + { + lexer.parsing_modifiers = true; + } ; interface_member_declaration @@ -2023,6 +2057,9 @@ operator_declaration current_container.AddOperator (op); lbag.AddMember (op, GetModifierLocations (), lbag.GetLocations (decl)); + if ($5 == null) { // Semicolon + lbag.AppendTo (op, savedLocation); + } } current_local_parameters = null; @@ -2031,7 +2068,7 @@ operator_declaration operator_body : block - | SEMICOLON { $$ = null; } + | SEMICOLON { savedLocation = GetLocation ($1); $$ = null; } ; operator_type @@ -2086,37 +2123,37 @@ operator_declarator } $$ = new OperatorDeclaration (op, (FullNamedExpression) $1, loc); - lbag.AddLocation ($$, GetLocation ($2), GetLocation ($3), GetLocation ($4), GetLocation ($7)); + lbag.AddLocation ($$, GetLocation ($2), savedOperatorLocation, GetLocation ($4), GetLocation ($7)); } | conversion_operator_declarator ; overloadable_operator // Unary operators: - : BANG { $$ = Operator.OpType.LogicalNot; } - | TILDE { $$ = Operator.OpType.OnesComplement; } - | OP_INC { $$ = Operator.OpType.Increment; } - | OP_DEC { $$ = Operator.OpType.Decrement; } - | TRUE { $$ = Operator.OpType.True; } - | FALSE { $$ = Operator.OpType.False; } + : BANG { $$ = Operator.OpType.LogicalNot; savedOperatorLocation = GetLocation ($1); } + | TILDE { $$ = Operator.OpType.OnesComplement; savedOperatorLocation = GetLocation ($1); } + | OP_INC { $$ = Operator.OpType.Increment; savedOperatorLocation = GetLocation ($1); } + | OP_DEC { $$ = Operator.OpType.Decrement; savedOperatorLocation = GetLocation ($1); } + | TRUE { $$ = Operator.OpType.True; savedOperatorLocation = GetLocation ($1); } + | FALSE { $$ = Operator.OpType.False; savedOperatorLocation = GetLocation ($1); } // Unary and binary: - | PLUS { $$ = Operator.OpType.Addition; } - | MINUS { $$ = Operator.OpType.Subtraction; } + | PLUS { $$ = Operator.OpType.Addition; savedOperatorLocation = GetLocation ($1); } + | MINUS { $$ = Operator.OpType.Subtraction; savedOperatorLocation = GetLocation ($1); } // Binary: - | STAR { $$ = Operator.OpType.Multiply; } - | DIV { $$ = Operator.OpType.Division; } - | PERCENT { $$ = Operator.OpType.Modulus; } - | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; } - | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; } - | CARRET { $$ = Operator.OpType.ExclusiveOr; } - | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; } - | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; } - | OP_EQ { $$ = Operator.OpType.Equality; } - | OP_NE { $$ = Operator.OpType.Inequality; } - | OP_GT { $$ = Operator.OpType.GreaterThan; } - | OP_LT { $$ = Operator.OpType.LessThan; } - | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; } - | OP_LE { $$ = Operator.OpType.LessThanOrEqual; } + | STAR { $$ = Operator.OpType.Multiply; savedOperatorLocation = GetLocation ($1); } + | DIV { $$ = Operator.OpType.Division; savedOperatorLocation = GetLocation ($1); } + | PERCENT { $$ = Operator.OpType.Modulus; savedOperatorLocation = GetLocation ($1); } + | BITWISE_AND { $$ = Operator.OpType.BitwiseAnd; savedOperatorLocation = GetLocation ($1); } + | BITWISE_OR { $$ = Operator.OpType.BitwiseOr; savedOperatorLocation = GetLocation ($1); } + | CARRET { $$ = Operator.OpType.ExclusiveOr; savedOperatorLocation = GetLocation ($1); } + | OP_SHIFT_LEFT { $$ = Operator.OpType.LeftShift; savedOperatorLocation = GetLocation ($1); } + | OP_SHIFT_RIGHT { $$ = Operator.OpType.RightShift; savedOperatorLocation = GetLocation ($1); } + | OP_EQ { $$ = Operator.OpType.Equality; savedOperatorLocation = GetLocation ($1); } + | OP_NE { $$ = Operator.OpType.Inequality; savedOperatorLocation = GetLocation ($1); } + | OP_GT { $$ = Operator.OpType.GreaterThan; savedOperatorLocation = GetLocation ($1); } + | OP_LT { $$ = Operator.OpType.LessThan; savedOperatorLocation = GetLocation ($1); } + | OP_GE { $$ = Operator.OpType.GreaterThanOrEqual; savedOperatorLocation = GetLocation ($1); } + | OP_LE { $$ = Operator.OpType.LessThanOrEqual; savedOperatorLocation = GetLocation ($1); } ; conversion_operator_declarator @@ -2526,7 +2563,11 @@ event_accessor_block enum_declaration : opt_attributes opt_modifiers - ENUM type_declaration_name + ENUM + { + enumCommas.Add (GetLocation ($3)); + } + type_declaration_name opt_enum_base { if (doc_support) @@ -2536,13 +2577,14 @@ enum_declaration { if (doc_support) Lexer.doc_state = XmlCommentState.Allowed; + enumCommas.Add (GetLocation ($8)); - MemberName name = (MemberName) $4; + MemberName name = (MemberName) $5; if (name.IsGeneric) { report.Error (1675, name.Location, "Enums cannot have type parameters"); } - push_current_class (new Enum (current_namespace, current_class, (TypeExpression) $5, (Modifiers) $2, MakeName (name), (Attributes) $1), null); + push_current_class (new Enum (current_namespace, current_class, (TypeExpression) $6, (Modifiers) $2, MakeName (name), (Attributes) $1), null); } opt_enum_member_declarations { @@ -2552,15 +2594,16 @@ enum_declaration } CLOSE_BRACE opt_semicolon { + enumCommas.Add (GetLocation ($12)); + if ($13 != null) + current_class.OptionalSemicolon = GetLocation ($13); if (doc_support) current_class.DocComment = enumTypeComment; --lexer.parsing_declaration; -// if (doc_support) -// em.DocComment = ev.DocComment; - - lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($3), GetLocation ($7), GetLocation ($11)); + lbag.AddMember (current_class, GetModifierLocations (), enumCommas); + enumCommas.Clear (); $$ = pop_current_class (); } ; @@ -2574,6 +2617,7 @@ opt_enum_base Enum.Error_1008 (GetLocation ($2), report); $$ = null; } else { + enumCommas.Add (GetLocation ($1)); $$ = $2; } } @@ -2589,7 +2633,7 @@ opt_enum_member_declarations | enum_member_declarations | enum_member_declarations COMMA { - lbag.AddLocation ($1, GetLocation ($2)); + enumCommas.Add (GetLocation ($2)); } ; @@ -2597,7 +2641,7 @@ enum_member_declarations : enum_member_declaration | enum_member_declarations COMMA enum_member_declaration { - lbag.AddLocation ($1, GetLocation ($2)); + enumCommas.Add (GetLocation ($2)); $$ = $3; } ; @@ -2714,8 +2758,9 @@ member_name | namespace_or_type_name DOT IDENTIFIER opt_type_argument_list { var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location); - lbag.AddLocation ($$, GetLocation ($2)); + $$ = new MemberName ((MemberName) $1, lt.Value, (TypeArguments) $4, lt.Location) { + DotLocation = GetLocation ($2) + }; } ; @@ -2812,7 +2857,7 @@ indexer_declaration_name | explicit_interface THIS { lexer.parsing_generic_declaration = false; - $$ = new MemberName ((MemberName) $1, TypeContainer.DefaultIndexerName, null, GetLocation ($1)); + $$ = new MemberName ((MemberName) $1, TypeContainer.DefaultIndexerName, null, GetLocation ($2)); } ; @@ -2847,7 +2892,7 @@ opt_type_parameter_list FeatureIsNotAvailable (GetLocation ($1), "generics"); $$ = $2; - lbag.AddLocation ($$, GetLocation ($1), GetLocation ($3)); + lbag.AppendTo ($$, GetLocation ($1), GetLocation ($3)); } ; @@ -2863,7 +2908,7 @@ type_parameters TypeArguments type_args = (TypeArguments) $1; type_args.Add ((FullNamedExpression)$3); $$ = type_args; - lbag.AddLocation ($3, GetLocation ($3)); + lbag.AppendTo (type_args, GetLocation ($2)); } ; @@ -2871,7 +2916,10 @@ type_parameter : opt_attributes opt_type_parameter_variance IDENTIFIER { var lt = (Tokenizer.LocatedToken)$3; - $$ = new TypeParameterName (lt.Value, (Attributes)$1, (Variance) $2, lt.Location); + var variance = (Variance) $2; + $$ = new TypeParameterName (lt.Value, (Attributes)$1, variance, lt.Location); + if (variance != Variance.None) + lbag.AddLocation ($$, savedLocation); } | error { @@ -2984,6 +3032,7 @@ type_list { var types = (List) $1; types.Add ((FullNamedExpression) $3); + lbag.AppendTo (types, GetLocation ($2)); $$ = types; } ; @@ -3118,20 +3167,23 @@ member_access : primary_expression DOT IDENTIFIER opt_type_argument_list { var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); - lbag.AddLocation ($$, GetLocation ($2)); + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location) { + DotLocation = GetLocation ($2) + }; } | builtin_types DOT IDENTIFIER opt_type_argument_list { var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location); - lbag.AddLocation ($$, GetLocation ($2)); + $$ = new MemberAccess ((Expression) $1, lt.Value, (TypeArguments) $4, lt.Location) { + DotLocation = GetLocation ($2) + }; } | BASE DOT IDENTIFIER opt_type_argument_list { var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location); - lbag.AddLocation ($$, GetLocation ($2)); + $$ = new MemberAccess (new BaseThis (GetLocation ($1)), lt.Value, (TypeArguments) $4, lt.Location) { + DotLocation = GetLocation ($2) + }; } | qualified_alias_member IDENTIFIER opt_type_argument_list { @@ -3179,13 +3231,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)); } ; @@ -3208,6 +3260,7 @@ member_initializer_list { var a = (List)$1; a.Add ((Expression) $3); + lbag.AppendTo (a, GetLocation ($2)); $$ = a; } | member_initializer_list error { @@ -3536,6 +3589,8 @@ anonymous_type_parameters { var a = (List) $1; a.Add ((AnonymousTypeParameter) $3); + lbag.AppendTo (a, GetLocation ($2)); + $$ = a; } ; @@ -3694,13 +3749,17 @@ unbound_type_name { var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location); + $$ = new MemberAccess ((Expression) $1, lt.Value, lt.Location) { + DotLocation = GetLocation ($2) + }; } | unbound_type_name DOT IDENTIFIER generic_dimension { var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberAccess ((Expression) $1, lt.Value, (int) $4, lt.Location); + $$ = new MemberAccess ((Expression) $1, lt.Value, (int) $4, lt.Location) { + DotLocation = GetLocation ($2) + }; } | namespace_or_type_name DOT IDENTIFIER generic_dimension { @@ -3709,7 +3768,9 @@ unbound_type_name Error_TypeExpected (GetLocation ($4)); var lt = (Tokenizer.LocatedToken) $3; - $$ = new MemberAccess (te, lt.Value, (int) $4, lt.Location); + $$ = new MemberAccess (te, lt.Value, (int) $4, lt.Location) { + DotLocation = GetLocation ($2) + }; } ; @@ -3847,10 +3908,10 @@ cast_expression await_expression : AWAIT unary_expression - { + { current_block.ParametersBlock.IsAsync = true; $$ = new Await ((Expression) $2, GetLocation ($1)); - } + } ; // @@ -4109,7 +4170,7 @@ lambda_parameter_list { var pars = new List (4); pars.Add ((Parameter) $1); - + parameterListCommas.Clear (); $$ = pars; } | lambda_parameter_list COMMA lambda_parameter @@ -4121,6 +4182,8 @@ lambda_parameter_list } pars.Add (p); + parameterListCommas.Add (GetLocation ($2)); + $$ = pars; } ; @@ -4150,6 +4213,7 @@ opt_lambda_parameter_list | lambda_parameter_list { var pars_list = (List) $1; $$ = new ParametersCompiled (pars_list.ToArray ()); + lbag.AddLocation ($$, parameterListCommas); } ; @@ -4295,8 +4359,9 @@ class_declaration if (((c.ModFlags & Modifiers.STATIC) != 0) && lang_version == LanguageVersion.ISO_1) { FeatureIsNotAvailable (c.Location, "static classes"); } - + push_current_class (c, $3); + lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); } opt_class_base opt_type_parameter_constraints_clauses @@ -4304,12 +4369,13 @@ class_declaration lexer.ConstraintsParsing = false; current_class.SetParameterInfo ((List) $9); - lbag.AddMember (current_class, GetModifierLocations (), GetLocation ($4)); if (doc_support) { current_container.DocComment = Lexer.consume_doc_comment (); Lexer.doc_state = XmlCommentState.Allowed; } + + lexer.parsing_modifiers = true; } OPEN_BRACE opt_class_member_declarations CLOSE_BRACE { @@ -4319,7 +4385,9 @@ class_declaration } opt_semicolon { - lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13), GetLocation ($15)); + lbag.AppendToMember (current_class, GetLocation ($11), GetLocation ($13)); + if ($15 != null) + current_class.OptionalSemicolon = GetLocation ($15); $$ = pop_current_class (); } ; @@ -4336,8 +4404,12 @@ opt_modifiers { mod_locations = null; $$ = ModifierNone; + lexer.parsing_modifiers = false; } | modifiers + { + lexer.parsing_modifiers = false; + } ; modifiers @@ -4447,6 +4519,7 @@ opt_class_base : /* empty */ | COLON type_list { + lbag.AppendToMember (current_class, GetLocation ($1)); current_container.AddBasesForPart (current_class, (List) $2); } ; @@ -4494,6 +4567,7 @@ type_parameter_constraints_clause { var lt = (Tokenizer.LocatedToken) $2; $$ = new Constraints (new SimpleMemberName (lt.Value, lt.Location), (List) $4, GetLocation ($1)); + lbag.AddLocation ($$, GetLocation ($3)); } ; @@ -4525,6 +4599,7 @@ type_parameter_constraints } constraints.Add ((FullNamedExpression) $3); + lbag.AppendTo (constraints, GetLocation ($2)); $$ = constraints; } ; @@ -4570,10 +4645,12 @@ type_parameter_variance : OUT { $$ = Variance.Covariant; + savedLocation = GetLocation ($1); } | IN { $$ = Variance.Contravariant; + savedLocation = GetLocation ($1); } ; @@ -4743,7 +4820,7 @@ labeled_statement { var lt = (Tokenizer.LocatedToken) $1; LabeledStatement labeled = new LabeledStatement (lt.Value, current_block, lt.Location); - + lbag.AddLocation (labeled, GetLocation ($2)); current_block.AddLabel (labeled); current_block.AddStatement (labeled); } @@ -4903,6 +4980,17 @@ opt_variable_declarators | variable_declarators ; +opt_using_or_fixed_variable_declarators + : /* empty */ + | variable_declarators + { + foreach (var d in current_variable.Declarators) { + if (d.Initializer == null) + Error_MissingInitializer (d.Variable.Location); + } + } + ; + variable_declarators : variable_declarator | variable_declarators variable_declarator @@ -5513,7 +5601,7 @@ fixed_statement current_block.AddLocalName (li); current_variable = new Fixed.VariableDeclaration ((FullNamedExpression) $3, li); } - using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS + using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS { $$ = current_variable; current_variable = null; @@ -5541,7 +5629,7 @@ using_statement current_block.AddLocalName (li); current_variable = new Using.VariableDeclaration ((FullNamedExpression) $3, li); } - using_or_fixed_variable_initializer opt_variable_declarators CLOSE_PARENS + using_or_fixed_variable_initializer opt_using_or_fixed_variable_declarators CLOSE_PARENS { $$ = current_variable; current_variable = null; @@ -5570,11 +5658,12 @@ using_statement using_or_fixed_variable_initializer : /* empty */ { - report.Error (210, lexer.Location, "You must provide an initializer in a fixed or using statement declaration"); + Error_MissingInitializer (lexer.Location); } | ASSIGN variable_initializer { current_variable.Initializer = (Expression) $2; + lbag.AppendTo (current_variable, GetLocation ($1)); $$ = current_variable; } ; @@ -6318,6 +6407,11 @@ void Error_NamedArgumentExpected (NamedArgument a) report.Error (1738, a.Location, "Named arguments must appear after the positional arguments"); } +void Error_MissingInitializer (Location loc) +{ + report.Error (210, loc, "You must provide an initializer in a fixed or using statement declaration"); +} + void push_current_class (TypeContainer tc, object partial_token) { if (module.Evaluator != null && current_container is ModuleContainer){ @@ -6573,6 +6667,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync oob_stack.Push (current_anonymous_method); oob_stack.Push (current_local_parameters); oob_stack.Push (current_variable); + oob_stack.Push (lexer.async_block); current_local_parameters = parameters; if (isLambda) { @@ -6587,6 +6682,7 @@ void start_anonymous (bool isLambda, ParametersCompiled parameters, bool isAsync current_anonymous_method = new AnonymousMethodExpression (isAsync, loc); } + lexer.async_block = isAsync; // Force the next block to be created as a ToplevelBlock parsing_anonymous_method = true; } @@ -6602,6 +6698,7 @@ AnonymousMethodExpression end_anonymous (ParametersBlock anon_block) current_anonymous_method.Block = anon_block; retval = current_anonymous_method; + lexer.async_block = (bool) oob_stack.Pop (); current_variable = (BlockVariableDeclaration) oob_stack.Pop (); current_local_parameters = (ParametersCompiled) oob_stack.Pop (); current_anonymous_method = (AnonymousMethodExpression) oob_stack.Pop (); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs index 6054c4462..e87f7676a 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/cs-tokenizer.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/cs-tokenizer.cs @@ -3,13 +3,13 @@ // This also implements the preprocessor // // Author: Miguel de Icaza (miguel@gnu.org) -// Marek Safar (marek.safar@seznam.cz) +// Marek Safar (marek.safar@gmail.com) // // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2001, 2002 Ximian, Inc (http://www.ximian.com) // Copyright 2004-2008 Novell, Inc -// +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // using System; using System.Text; @@ -205,6 +205,10 @@ namespace Mono.CSharp public int parsing_declaration; public bool parsing_attribute_section; + public bool parsing_modifiers; + + public bool async_block; + // // The special characters to inject on streams to run the unit parser // in the special expression mode. Using private characters from @@ -787,18 +791,47 @@ namespace Mono.CSharp res = -1; break; - // TODO: async, it's modifiers context only case Token.ASYNC: - if (context.Settings.Version != LanguageVersion.Future) { + if (parsing_modifiers) { + // + // Skip attributes section or constructor called async + // + if (parsing_attribute_section || peek_token () == Token.OPEN_PARENS) { + res = -1; + } else { + // async is keyword + } + } else if (parsing_block > 0) { + switch (peek_token ()) { + case Token.DELEGATE: + case Token.OPEN_PARENS_LAMBDA: + // async is keyword + break; + case Token.IDENTIFIER: + PushPosition (); + xtoken (); + if (xtoken () != Token.ARROW) + res = -1; + + PopPosition (); + break; + default: + res = -1; + break; + } + } else { res = -1; } + + if (res == Token.ASYNC && context.Settings.Version <= LanguageVersion.V_4) { + Report.FeatureIsNotAvailable (context, Location, "asynchronous functions"); + } + break; - // TODO: async, it's async block context only case Token.AWAIT: - if (context.Settings.Version != LanguageVersion.Future) { + if (!async_block) res = -1; - } break; } @@ -1833,7 +1866,8 @@ namespace Mono.CSharp var cmd = GetPreprocessorDirective (id_builder, TokenizePreprocessorIdentifier (out c, out endLine, out endCol)); if ((cmd & PreprocessorDirective.CustomArgumentsParsing) != 0) { - sbag.AddPreProcessorDirective (startLine, startCol, line, col, cmd, null); + if (position_stack.Count == 0) + sbag.AddPreProcessorDirective (startLine, startCol, line, col, cmd, null); return cmd; } @@ -1899,7 +1933,8 @@ namespace Mono.CSharp // Eat any trailing whitespaces arg = arg.Trim (simple_whitespaces); } - sbag.AddPreProcessorDirective (startLine, startCol, endLine, endCol, cmd, arg); + if (position_stack.Count == 0) + sbag.AddPreProcessorDirective (startLine, startCol, endLine, endCol, cmd, arg); return cmd; } @@ -2196,14 +2231,16 @@ namespace Mono.CSharp { if (peek_char () != '/') Report.Warning (1696, 1, Location, "Single-line comment or end-of-line expected"); - sbag.StartComment (SpecialsBag.CommentType.Single, startsLine, line, col - 1); + if (position_stack.Count == 0) + sbag.StartComment (SpecialsBag.CommentType.Single, startsLine, line, col - 1); // Read everything till the end of the line or file int c; do { c = get_char (); - sbag.PushCommentChar (c); + if (position_stack.Count == 0) + sbag.PushCommentChar (c); var pc = peek_char (); - if (pc == '\n' || pc == -1) + if (pc == '\n' || pc == -1 && position_stack.Count == 0) sbag.EndComment (line, col + 1); } while (c != -1 && c != '\n'); } @@ -2541,6 +2578,7 @@ namespace Mono.CSharp ifstack.Push (flags | TAKING); return true; } + sbag.SkipIf (); ifstack.Push (flags); return false; @@ -3149,17 +3187,16 @@ namespace Mono.CSharp get_char (); return Token.OP_DIV_ASSIGN; } - // Handle double-slash comments. if (d == '/') { get_char (); if (doc_processing) { if (peek_char () == '/') { - sbag.StartComment (SpecialsBag.CommentType.Documentation, startsLine, line, col - 1); get_char (); // Don't allow ////. if ((d = peek_char ()) != '/') { - sbag.PushCommentChar (d); + if (position_stack.Count == 0) + sbag.PushCommentChar (d); if (doc_state == XmlCommentState.Allowed) handle_one_line_xml_comment (); else if (doc_state == XmlCommentState.NotAllowed) @@ -3171,39 +3208,41 @@ namespace Mono.CSharp } } else { bool isDoc = peek_char () == '/'; - sbag.StartComment (isDoc ? SpecialsBag.CommentType.Documentation : SpecialsBag.CommentType.Single, startsLine, line, col - 1); + if (position_stack.Count == 0) + sbag.StartComment (isDoc ? SpecialsBag.CommentType.Documentation : SpecialsBag.CommentType.Single, startsLine, line, col - 1); if (isDoc) get_char (); } d = peek_char (); - if (d == '\n' || d == '\r') - sbag.EndComment (line, col + 1); while ((d = get_char ()) != -1 && (d != '\n') && d != '\r') { - sbag.PushCommentChar (d); - var pc = peek_char (); - if (pc == -1 || pc == '\n' || pc == '\r') { - sbag.EndComment (line, col + 1); - } + if (position_stack.Count == 0) + sbag.PushCommentChar (d); } + if (position_stack.Count == 0) + sbag.EndComment (line, col + 1); any_token_seen |= tokens_seen; tokens_seen = false; comments_seen = false; continue; } else if (d == '*'){ - sbag.StartComment (SpecialsBag.CommentType.Multi, startsLine, line, col); + if (position_stack.Count == 0) + sbag.StartComment (SpecialsBag.CommentType.Multi, startsLine, line, col); get_char (); bool docAppend = false; if (doc_processing && peek_char () == '*') { int ch = get_char (); - sbag.PushCommentChar (ch); + if (position_stack.Count == 0) + sbag.PushCommentChar (ch); // But when it is /**/, just do nothing. if (peek_char () == '/') { ch = get_char (); - sbag.PushCommentChar (ch); - sbag.EndComment (line, col + 1); + if (position_stack.Count == 0) { + sbag.PushCommentChar (ch); + sbag.EndComment (line, col + 1); + } continue; } if (doc_state == XmlCommentState.Allowed) @@ -3220,11 +3259,14 @@ namespace Mono.CSharp } while ((d = get_char ()) != -1){ - sbag.PushCommentChar (d); + if (position_stack.Count == 0) + sbag.PushCommentChar (d); if (d == '*' && peek_char () == '/'){ - sbag.PushCommentChar ('/'); + if (position_stack.Count == 0) + sbag.PushCommentChar ('/'); get_char (); - sbag.EndComment (line, col + 1); + if (position_stack.Count == 0) + sbag.EndComment (line, col + 1); comments_seen = true; break; } @@ -3390,16 +3432,20 @@ namespace Mono.CSharp int TokenizeBackslash () { +#if FULL_AST + int read_start = reader.Position; +#endif + Location start_location = Location; int c = get_char (); tokens_seen = true; if (c == '\'') { - val = new CharLiteral (context.BuiltinTypes, (char) c, Location); - Report.Error (1011, Location, "Empty character literal"); + val = new CharLiteral (context.BuiltinTypes, (char) c, start_location); + Report.Error (1011, start_location, "Empty character literal"); return Token.LITERAL; } - if (c == '\n') { - Report.Error (1010, Location, "Newline in constant"); + if (c == '\r') { + Report.Error (1010, start_location, "Newline in constant"); return Token.ERROR; } @@ -3410,11 +3456,12 @@ namespace Mono.CSharp if (d != 0) throw new NotImplementedException (); - val = new CharLiteral (context.BuiltinTypes, (char) c, Location); + ILiteralConstant res = new CharLiteral (context.BuiltinTypes, (char) c, start_location); + val = res; c = get_char (); if (c != '\'') { - Report.Error (1012, Location, "Too many characters in character literal"); + Report.Error (1012, start_location, "Too many characters in character literal"); // Try to recover, read until newline or next "'" while ((c = get_char ()) != -1) { @@ -3423,6 +3470,10 @@ namespace Mono.CSharp } } +#if FULL_AST + res.ParsedValue = reader.ReadChars (read_start - 1, reader.Position); +#endif + return Token.LITERAL; } @@ -3480,11 +3531,13 @@ namespace Mono.CSharp { int c; while ((c = peek_char ()) == ' ') { - sbag.PushCommentChar (c); + if (position_stack.Count == 0) + sbag.PushCommentChar (c); get_char (); // skip heading whitespaces. } while ((c = peek_char ()) != -1 && c != '\n' && c != '\r') { - sbag.PushCommentChar (c); + if (position_stack.Count == 0) + sbag.PushCommentChar (c); xml_comment_buffer.Append ((char) get_char ()); } if (c == '\r' || c == '\n') diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs index 0329cf6a5..32c8d071a 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/decl.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/decl.cs @@ -27,7 +27,7 @@ using IKVM.Reflection.Emit; #else using System.Reflection; using System.Reflection.Emit; -using Mono.Collections.Generic; +//using Mono.Collections.Generic; #endif namespace Mono.CSharp { @@ -49,6 +49,12 @@ namespace Mono.CSharp { public bool IsDoubleColon { get { return is_double_colon; } } +#if FULL_AST + public Location DotLocation { + get; + set; + } +#endif private MemberName (MemberName left, string name, bool is_double_colon, Location loc) { @@ -154,7 +160,11 @@ namespace Mono.CSharp { } Expression lexpr = Left.GetTypeExpression (); - return new MemberAccess (lexpr, Name, TypeArguments, Location); + var result = new MemberAccess (lexpr, Name, TypeArguments, Location); +#if FULL_AST + result.DotLocation = DotLocation; +#endif + return result; } public MemberName Clone () @@ -694,9 +704,9 @@ namespace Mono.CSharp { return true; } - public virtual IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + public virtual ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) { - return Parent.LookupExtensionMethod (extensionType, name, arity, ref scope); + return Parent.LookupExtensionMethod (extensionType, name, arity); } public virtual FullNamedExpression LookupNamespaceAlias (string name) @@ -1441,6 +1451,21 @@ namespace Mono.CSharp { get; private set; } + + public bool HasOptionalSemicolon { + get; + private set; + } + Location optionalSemicolon; + public Location OptionalSemicolon { + get { + return optionalSemicolon; + } + set { + optionalSemicolon = value; + HasOptionalSemicolon = true; + } + } #endif public List Constraints { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs index 8752aebc1..cc381846f 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/delegate.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/delegate.cs @@ -434,6 +434,11 @@ namespace Mono.CSharp { protected MethodSpec constructor_method; protected MethodGroupExpr method_group; + public override bool ContainsEmitWithAwait () + { + return false; + } + public static Arguments CreateDelegateMethodArguments (AParametersCollection pd, TypeSpec[] types, Location loc) { Arguments delegate_arguments = new Arguments (pd.Count); @@ -541,7 +546,7 @@ namespace Mono.CSharp { public override void Emit (EmitContext ec) { if (method_group.InstanceExpression == null) - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); else method_group.InstanceExpression.Emit (ec); @@ -717,6 +722,11 @@ namespace Mono.CSharp { this.arguments = args; this.loc = loc; } + + public override bool ContainsEmitWithAwait () + { + return InstanceExpr.ContainsEmitWithAwait () || (arguments != null && arguments.ContainsEmitWithAwait ()); + } public override Expression CreateExpressionTree (ResolveContext ec) { @@ -753,7 +763,9 @@ namespace Mono.CSharp { // Invocation on delegates call the virtual Invoke member // so we are always `instance' calls // - Invocation.EmitCall (ec, InstanceExpr, method, arguments, loc); + var call = new CallEmitter (); + call.InstanceExpression = InstanceExpr; + call.EmitPredefined (ec, method, arguments); } public override void EmitStatement (EmitContext ec) diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj b/ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.csproj similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.csproj rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.csproj diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config b/ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.exe.config similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.config rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.exe.config diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources b/ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.exe.sources similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.exe.sources rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.exe.sources diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln b/ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.sln similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/dmcs.sln rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/dmcs.sln diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/doc-bootstrap.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/doc-bootstrap.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/doc-bootstrap.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/doc.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/doc.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/driver.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/driver.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/dynamic.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/dynamic.cs index c7df9f7c8..76447fad0 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/dynamic.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/dynamic.cs @@ -6,6 +6,7 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2009 Novell, Inc +// Copyright 2011 Xamarin Inc. // using System; @@ -95,9 +96,14 @@ namespace Mono.CSharp throw new NotImplementedException (); } + public override bool ContainsEmitWithAwait () + { + throw new NotSupportedException (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { - throw new NotImplementedException (); + throw new NotSupportedException (); } protected override Expression DoResolve (ResolveContext ec) @@ -122,7 +128,7 @@ namespace Mono.CSharp throw new NotImplementedException (); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { throw new NotImplementedException (); } @@ -262,6 +268,11 @@ namespace Mono.CSharp } } + public override bool ContainsEmitWithAwait () + { + return arguments.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { ec.Report.Error (1963, loc, "An expression tree cannot contain a dynamic operation"); @@ -714,7 +725,7 @@ namespace Mono.CSharp class DynamicInvocation : DynamicExpressionStatement, IDynamicBinder { - ATypeNameExpression member; + readonly ATypeNameExpression member; public DynamicInvocation (ATypeNameExpression member, Arguments args, Location loc) : base (null, args, loc) @@ -897,7 +908,7 @@ namespace Mono.CSharp throw new NotImplementedException (); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { EmitCall (ec, setter, setter_args, !leave_copy); } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs similarity index 94% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs index 3be2ce0cd..d7e357c01 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/ecore.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/ecore.cs @@ -7,6 +7,7 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc. // Copyright 2003-2008 Novell, Inc. +// Copyright 2011 Xamarin Inc. // // @@ -130,16 +131,14 @@ namespace Mono.CSharp { set { type = value; } } - public Location Location { - get { return loc; } + public virtual bool IsSideEffectFree { + get { + return false; + } } - public virtual string GetSignatureForError () - { - if (type == null) - return ""; - TypeSpec typeSpec = type.GetDefinition (); - return typeSpec != null ? typeSpec.GetSignatureForError () : ""; + public Location Location { + get { return loc; } } public virtual bool IsNull { @@ -148,6 +147,15 @@ namespace Mono.CSharp { } } + // + // Returns true when the expression during Emit phase breaks stack + // by using await expression + // + public virtual bool ContainsEmitWithAwait () + { + return false; + } + /// /// Performs semantic analysis on the Expression /// @@ -343,6 +351,11 @@ namespace Mono.CSharp { } } } + + public virtual string GetSignatureForError () + { + return type.GetDefinition ().GetSignatureForError (); + } /// /// Resolves an expression and performs semantic analysis on it. @@ -469,6 +482,107 @@ namespace Mono.CSharp { ec.Emit (OpCodes.Pop); } + // + // Emits the expression into temporary field variable. The method + // should be used for await expressions only + // + public virtual Expression EmitToField (EmitContext ec) + { + // + // This is the await prepare Emit method. When emitting code like + // a + b we emit code like + // + // a.Emit () + // b.Emit () + // Opcodes.Add + // + // For await a + await b we have to interfere the flow to keep the + // stack clean because await yields from the expression. The emit + // then changes to + // + // a = a.EmitToField () // a is changed to temporary field access + // b = b.EmitToField () + // a.Emit () + // b.Emit () + // Opcodes.Add + // + // + // The idea is to emit expression and leave the stack empty with + // result value still available. + // + // Expressions should override this default implementation when + // optimized version can be provided (e.g. FieldExpr) + // + // + // We can optimize for side-effect free expressions, they can be + // emitted out of order + // + if (IsSideEffectFree) + return this; + + bool needs_temporary = ContainsEmitWithAwait (); + if (!needs_temporary) + ec.EmitThis (); + + // Emit original code + EmitToFieldSource (ec); + + // + // Store the result to temporary field when we + // cannot load this directly + // + var field = ec.GetTemporaryField (type); + if (needs_temporary) { + // + // Create temporary local (we cannot load this before Emit) + // + var temp = ec.GetTemporaryLocal (type); + ec.Emit (OpCodes.Stloc, temp); + + ec.EmitThis (); + ec.Emit (OpCodes.Ldloc, temp); + field.EmitAssignFromStack (ec); + + ec.FreeTemporaryLocal (temp, type); + } else { + field.EmitAssignFromStack (ec); + } + + return field; + } + + protected virtual void EmitToFieldSource (EmitContext ec) + { + // + // Default implementation calls Emit method + // + Emit (ec); + } + + protected static void EmitExpressionsList (EmitContext ec, List expressions) + { + if (ec.HasSet (BuilderContext.Options.AsyncBody)) { + bool contains_await = false; + + for (int i = 1; i < expressions.Count; ++i) { + if (expressions[i].ContainsEmitWithAwait ()) { + contains_await = true; + break; + } + } + + if (contains_await) { + for (int i = 0; i < expressions.Count; ++i) { + expressions[i] = expressions[i].EmitToField (ec); + } + } + } + + for (int i = 0; i < expressions.Count; ++i) { + expressions[i].Emit (ec); + } + } + /// /// Protected constructor. Only derivate types should /// be able to be created @@ -498,7 +612,7 @@ namespace Mono.CSharp { return null; } - protected static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc) + public static MethodSpec ConstructorLookup (ResolveContext rc, TypeSpec type, ref Arguments args, Location loc) { var ctors = MemberCache.FindMembers (type, Constructor.ConstructorName, true); if (ctors == null) { @@ -961,6 +1075,11 @@ namespace Mono.CSharp { } } + public override bool ContainsEmitWithAwait () + { + return child.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -1140,6 +1259,12 @@ namespace Mono.CSharp { get { return child.IsOneInteger; } } + public override bool IsSideEffectFree { + get { + return child.IsSideEffectFree; + } + } + public override bool IsZeroInteger { get { return child.IsZeroInteger; } } @@ -1277,6 +1402,12 @@ namespace Mono.CSharp { } } + public override bool IsSideEffectFree { + get { + return Child.IsSideEffectFree; + } + } + public override bool IsZeroInteger { get { return Child.IsZeroInteger; } } @@ -1731,6 +1862,17 @@ namespace Mono.CSharp { c = new ReducedConstantExpression (c, orig_expr); return c; } + + public override void EncodeAttributeValue (IMemberContext rc, AttributeEncoder enc, TypeSpec targetType) + { + // + // LAMESPEC: Reduced conditional expression is allowed as an attribute argument + // + if (orig_expr is Conditional) + child.EncodeAttributeValue (rc, enc, targetType); + else + base.EncodeAttributeValue (rc, enc, targetType); + } } sealed class ReducedExpressionStatement : ExpressionStatement @@ -1748,6 +1890,11 @@ namespace Mono.CSharp { this.loc = orig.Location; } + public override bool ContainsEmitWithAwait () + { + return stm.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { return orig_expr.CreateExpressionTree (ec); @@ -1790,6 +1937,11 @@ namespace Mono.CSharp { #endregion + public override bool ContainsEmitWithAwait () + { + return expr.ContainsEmitWithAwait (); + } + // // Creates fully resolved expression switcher // @@ -1873,6 +2025,11 @@ namespace Mono.CSharp { this.loc = expr.Location; } + public override bool ContainsEmitWithAwait () + { + return expr.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext rc) { return expr.CreateExpressionTree (rc); @@ -1930,6 +2087,11 @@ namespace Mono.CSharp { target.expr = expr.Clone (clonectx); } + public override bool ContainsEmitWithAwait () + { + return expr.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -2090,7 +2252,6 @@ namespace Mono.CSharp { } } - // MSAF var retval = ctx.LookupNamespaceOrType (Name, Arity, LookupMode.IgnoreAccessibility, loc); if (retval != null) { ctx.Module.Compiler.Report.SymbolRelatedToPreviousError (retval.Type); @@ -2379,6 +2540,11 @@ namespace Mono.CSharp { // resolved to different type } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -2626,6 +2792,11 @@ namespace Mono.CSharp { } } + public override bool ContainsEmitWithAwait () + { + return InstanceExpression != null && InstanceExpression.ContainsEmitWithAwait (); + } + static bool IsSameOrBaseQualifier (TypeSpec type, TypeSpec qtype) { do { @@ -2814,6 +2985,7 @@ namespace Mono.CSharp { InstanceExpression.Emit (ec); t.Store (ec); t.AddressOf (ec, AddressOp.Store); + t.Release (ec); } } else { InstanceExpression.Emit (ec); @@ -2830,18 +3002,57 @@ namespace Mono.CSharp { public abstract void SetTypeArguments (ResolveContext ec, TypeArguments ta); } + public class ExtensionMethodCandidates + { + NamespaceContainer container; + Namespace ns; + IList methods; + + public ExtensionMethodCandidates (IList methods, NamespaceContainer nsContainer) + : this (methods, nsContainer, null) + { + } + + public ExtensionMethodCandidates (IList methods, NamespaceContainer nsContainer, Namespace ns) + { + this.methods = methods; + this.container = nsContainer; + this.ns = ns; + } + + public NamespaceContainer Container { + get { + return container; + } + } + + public bool HasUninspectedMembers { get; set; } + + public Namespace Namespace { + get { + return ns; + } + } + + public IList Methods { + get { + return methods; + } + } + } + // // Represents a group of extension method candidates for whole namespace // class ExtensionMethodGroupExpr : MethodGroupExpr, OverloadResolver.IErrorHandler { - NamespaceContainer namespace_entry; + ExtensionMethodCandidates candidates; public readonly Expression ExtensionExpression; - public ExtensionMethodGroupExpr (IList list, NamespaceContainer n, Expression extensionExpr, Location l) - : base (list.Cast().ToList (), extensionExpr.Type, l) + public ExtensionMethodGroupExpr (ExtensionMethodCandidates candidates, Expression extensionExpr, Location loc) + : base (candidates.Methods.Cast().ToList (), extensionExpr.Type, loc) { - this.namespace_entry = n; + this.candidates = candidates; this.ExtensionExpression = extensionExpr; } @@ -2849,21 +3060,55 @@ namespace Mono.CSharp { get { return true; } } + // + // For extension methodgroup we are not looking for base members but parent + // namespace extension methods + // public override IList GetBaseMembers (TypeSpec baseType) { - if (namespace_entry == null) + // TODO: candidates are null only when doing error reporting, that's + // incorrect. We have to discover same extension methods in error mode + if (candidates == null) return null; + int arity = type_arguments == null ? 0 : type_arguments.Count; + // - // For extension methodgroup we are not looking for base members but parent - // namespace extension methods + // Here we try to resume the search for extension method at the point + // where the last bunch of candidates was found. It's more tricky than + // it seems as we have to check both namespace containers and namespace + // in correct order. // - int arity = type_arguments == null ? 0 : type_arguments.Count; - var found = namespace_entry.LookupExtensionMethod (DeclaringType, Name, arity, ref namespace_entry); - if (found == null) + // Consider: + // + // namespace A { + // using N1; + // namespace B.C.D { + // ().ToList (); + } + } + + var ns_container = candidates.HasUninspectedMembers ? candidates.Container : candidates.Container.Parent; + if (ns_container == null) + return null; + + candidates = ns_container.LookupExtensionMethod (ExtensionExpression.Type, Name, arity); + if (candidates == null) return null; - return found.Cast ().ToList (); + return candidates.Methods.Cast ().ToList (); } public override MethodGroupExpr LookupExtensionMethod (ResolveContext rc) @@ -3072,7 +3317,9 @@ namespace Mono.CSharp { public void EmitCall (EmitContext ec, Arguments arguments) { - Invocation.EmitCall (ec, InstanceExpression, best_candidate, arguments, loc); + var call = new CallEmitter (); + call.InstanceExpression = InstanceExpression; + call.Emit (ec, best_candidate, arguments, loc); } public override void Error_ValueCannotBeConverted (ResolveContext ec, Location loc, TypeSpec target, bool expl) @@ -3197,12 +3444,11 @@ namespace Mono.CSharp { return null; int arity = type_arguments == null ? 0 : type_arguments.Count; - NamespaceContainer methods_scope = null; - var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity, ref methods_scope); + var methods = rc.LookupExtensionMethod (InstanceExpression.Type, Methods[0].Name, arity); if (methods == null) return null; - var emg = new ExtensionMethodGroupExpr (methods, methods_scope, InstanceExpression, loc); + var emg = new ExtensionMethodGroupExpr (methods, InstanceExpression, loc); emg.SetTypeArguments (rc, type_arguments); return emg; } @@ -3969,9 +4215,11 @@ namespace Mono.CSharp { // // Indentity, implicit reference or boxing conversion must exist for the extension parameter // + // LAMESPEC: or implicit type parameter conversion + // var at = a.Type; if (at == pt || TypeSpecComparer.IsEqual (at, pt) || - Convert.ImplicitReferenceConversionExists (at, pt) || + Convert.ImplicitReferenceConversionExists (at, pt, false) || Convert.ImplicitBoxingConversion (null, at, pt) != null) { score = 0; continue; @@ -4756,10 +5004,11 @@ namespace Mono.CSharp { } } - /// - /// Fully resolved expression that evaluates to a Field - /// - public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference { + // + // Fully resolved expression that references a Field + // + public class FieldExpr : MemberExpr, IDynamicAssign, IMemoryLocation, IVariableReference + { protected FieldSpec spec; VariableInfo variable_info; @@ -4929,7 +5178,7 @@ namespace Mono.CSharp { } else if (var != null && var.IsHoisted) { AnonymousMethodExpression.Error_AddressOfCapturedVar (ec, var, loc); } - + return new FixedBufferPtr (this, fb.ElementType, loc).Resolve (ec); } @@ -5108,23 +5357,27 @@ namespace Mono.CSharp { } } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { - var await_expr = source as Await; - if (await_expr != null) { - // - // Await is not ordinary expression (it contains jump), hence the usual flow cannot be used - // to emit instance load before expression - // - await_expr.EmitAssign (ec, this); - } else { - prepared = prepare_for_load && !(source is DynamicExpressionStatement); - if (IsInstance) - EmitInstance (ec, prepared); + bool has_await_source = ec.HasSet (BuilderContext.Options.AsyncBody) && source.ContainsEmitWithAwait (); + if (isCompound && !(source is DynamicExpressionStatement)) { + if (has_await_source) { + if (IsInstance) + InstanceExpression = InstanceExpression.EmitToField (ec); + } else { + prepared = true; + } + } - source.Emit (ec); + if (IsInstance) { + if (has_await_source) + source = source.EmitToField (ec); + + EmitInstance (ec, prepared); } + source.Emit (ec); + if (leave_copy) { ec.Emit (OpCodes.Dup); if (!IsStatic) { @@ -5150,6 +5403,18 @@ namespace Mono.CSharp { } } + // + // Emits store to field with prepared values on stack + // + public void EmitAssignFromStack (EmitContext ec) + { + if (IsStatic) { + ec.Emit (OpCodes.Stsfld, spec); + } else { + ec.Emit (OpCodes.Stfld, spec); + } + } + public override void Emit (EmitContext ec) { Emit (ec, false); @@ -5187,12 +5452,12 @@ namespace Mono.CSharp { } else need_copy = false; - if (need_copy){ - LocalBuilder local; + if (need_copy) { Emit (ec); - local = ec.DeclareLocal (type, false); - ec.Emit (OpCodes.Stloc, local); - ec.Emit (OpCodes.Ldloca, local); + var temp = ec.GetTemporaryLocal (type); + ec.Emit (OpCodes.Stloc, temp); + ec.Emit (OpCodes.Ldloca, temp); + ec.FreeTemporaryLocal (temp, type); return; } @@ -5229,14 +5494,13 @@ namespace Mono.CSharp { } - /// - /// Expression that evaluates to a Property. The Assign class - /// might set the `Value' expression if we are in an assignment. - /// - /// This is not an LValue because we need to re-write the expression, we - /// can not take data from the stack and store it. - /// - class PropertyExpr : PropertyOrIndexerExpr + // + // Expression that evaluates to a Property. + // + // This is not an LValue because we need to re-write the expression. We + // can not take data from the stack and store it. + // + sealed class PropertyExpr : PropertyOrIndexerExpr { public PropertyExpr (PropertySpec spec, Location l) : base (l) @@ -5247,6 +5511,14 @@ namespace Mono.CSharp { #region Properties + protected override Arguments Arguments { + get { + return null; + } + set { + } + } + protected override TypeSpec DeclaringType { get { return best_candidate.DeclaringType; @@ -5279,6 +5551,14 @@ namespace Mono.CSharp { #endregion + public static PropertyExpr CreatePredefined (PropertySpec spec, Location loc) + { + return new PropertyExpr (spec, loc) { + Getter = spec.Get, + Setter = spec.Set + }; + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args; @@ -5347,36 +5627,41 @@ namespace Mono.CSharp { // Special case: length of single dimension array property is turned into ldlen // if (IsSingleDimensionalArrayLength ()) { - if (!prepared) - EmitInstance (ec, false); + EmitInstance (ec, false); ec.Emit (OpCodes.Ldlen); ec.Emit (OpCodes.Conv_I4); return; } - Invocation.EmitCall (ec, InstanceExpression, Getter, null, loc, prepared, false); - - if (leave_copy) { - ec.Emit (OpCodes.Dup); - if (!IsStatic) { - temp = new LocalTemporary (this.Type); - temp.Store (ec); - } - } + base.Emit (ec, leave_copy); } - public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { Arguments args; + LocalTemporary await_source_arg = null; - if (prepare_for_load && !(source is DynamicExpressionStatement)) { - args = new Arguments (0); - prepared = true; + if (isCompound && !(source is DynamicExpressionStatement)) { + emitting_compound_assignment = true; source.Emit (ec); - - if (leave_copy) { - ec.Emit (OpCodes.Dup); - if (!IsStatic) { + + if (has_await_arguments) { + await_source_arg = new LocalTemporary (Type); + await_source_arg.Store (ec); + + args = new Arguments (1); + args.Add (new Argument (await_source_arg)); + + if (leave_copy) { + temp = await_source_arg; + } + + has_await_arguments = false; + } else { + args = null; + + if (leave_copy) { + ec.Emit (OpCodes.Dup); temp = new LocalTemporary (this.Type); temp.Store (ec); } @@ -5394,12 +5679,23 @@ namespace Mono.CSharp { } } - Invocation.EmitCall (ec, InstanceExpression, Setter, args, loc, false, prepared); - + emitting_compound_assignment = false; + + var call = new CallEmitter (); + call.InstanceExpression = InstanceExpression; + if (args == null) + call.InstanceExpressionOnStack = true; + + call.Emit (ec, Setter, args, loc); + if (temp != null) { temp.Emit (ec); temp.Release (ec); } + + if (await_source_arg != null) { + await_source_arg.Release (ec); + } } protected override Expression OverloadResolve (ResolveContext rc, Expression right_side) @@ -5437,7 +5733,8 @@ namespace Mono.CSharp { protected T best_candidate; protected LocalTemporary temp; - protected bool prepared; + protected bool emitting_compound_assignment; + protected bool has_await_arguments; protected PropertyOrIndexerExpr (Location l) { @@ -5446,6 +5743,8 @@ namespace Mono.CSharp { #region Properties + protected abstract Arguments Arguments { get; set; } + public MethodSpec Getter { get { return getter; @@ -5520,14 +5819,43 @@ namespace Mono.CSharp { // // Implements the IAssignMethod interface for assignments // - public abstract void Emit (EmitContext ec, bool leave_copy); - public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load); + public virtual void Emit (EmitContext ec, bool leave_copy) + { + var call = new CallEmitter (); + call.InstanceExpression = InstanceExpression; + if (has_await_arguments) + call.HasAwaitArguments = true; + else + call.DuplicateArguments = emitting_compound_assignment; + + call.Emit (ec, Getter, Arguments, loc); + + if (call.HasAwaitArguments) { + InstanceExpression = call.InstanceExpression; + Arguments = call.EmittedArguments; + has_await_arguments = true; + } + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + + public abstract void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound); public override void Emit (EmitContext ec) { Emit (ec, false); } + protected override void EmitToFieldSource (EmitContext ec) + { + has_await_arguments = true; + Emit (ec, false); + } + public abstract SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source); protected abstract Expression OverloadResolve (ResolveContext rc, Expression right_side); @@ -5716,14 +6044,17 @@ namespace Mono.CSharp { throw new NotImplementedException (); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { - if (leave_copy || !prepare_for_load) + if (leave_copy || !isCompound) throw new NotImplementedException ("EventExpr::EmitAssign"); Arguments args = new Arguments (1); args.Add (new Argument (source)); - Invocation.EmitCall (ec, InstanceExpression, op, args, loc); + + var call = new CallEmitter (); + call.InstanceExpression = InstanceExpression; + call.Emit (ec, op, args, loc); } #endregion @@ -5810,20 +6141,15 @@ namespace Mono.CSharp { return new TemporaryVariableReference (li, loc); } - public override Expression CreateExpressionTree (ResolveContext ec) - { - throw new NotSupportedException ("ET"); - } - protected override Expression DoResolve (ResolveContext ec) { eclass = ExprClass.Variable; // // Don't capture temporary variables except when using - // iterator redirection + // state machine redirection // - if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod.IsIterator && ec.IsVariableCapturingRequired) { + if (ec.CurrentAnonymousMethod != null && ec.CurrentAnonymousMethod is StateMachineInitializer && ec.IsVariableCapturingRequired) { AnonymousMethodStorey storey = li.Block.Explicit.CreateAnonymousMethodStorey (ec); storey.CaptureLocalVariable (ec, li); } @@ -5877,7 +6203,7 @@ namespace Mono.CSharp { } public override VariableInfo VariableInfo { - get { throw new NotImplementedException (); } + get { return null; } } } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs index ec23b5267..fef5af717 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/enum.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/enum.cs @@ -117,6 +117,11 @@ namespace Mono.CSharp { this.prev = prev; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("Missing Resolve call"); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/eval.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/eval.cs index 03097dfd8..fdcff115e 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/eval.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/eval.cs @@ -988,6 +988,13 @@ namespace Mono.CSharp } } + /// + /// Same as quit - useful in script scenerios + /// + static public void Quit () { + QuitRequested = true; + } + #if !NET_2_1 /// /// Describes an object or a type. diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs similarity index 94% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs index 3349a7c00..e708b6c1c 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/expression.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/expression.cs @@ -7,6 +7,7 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc. // Copyright 2003-2008 Novell, Inc. +// Copyright 2011 Xamarin Inc. // using System; @@ -46,6 +47,11 @@ namespace Mono.CSharp this.loc = loc; } + public override bool ContainsEmitWithAwait () + { + return arguments.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { if (expr_tree != null) @@ -73,7 +79,8 @@ namespace Mono.CSharp public override void Emit (EmitContext ec) { - Invocation.EmitCall (ec, null, oper, arguments, loc); + var call = new CallEmitter (); + call.EmitPredefined (ec, oper, arguments); } public override SLE.Expression MakeExpression (BuilderContext ctx) @@ -336,6 +343,11 @@ namespace Mono.CSharp return EmptyCast.Create (this, type); } + public override bool ContainsEmitWithAwait () + { + return Expr.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { return CreateExpressionTree (ec, null); @@ -498,7 +510,10 @@ namespace Mono.CSharp case Operator.UnaryNegation: if (ec.HasSet (EmitContext.Options.CheckedScope) && !IsFloat (type)) { - ec.Emit (OpCodes.Ldc_I4_0); + if (ec.HasSet (BuilderContext.Options.AsyncBody) && Expr.ContainsEmitWithAwait ()) + Expr = Expr.EmitToField (ec); + + ec.EmitInt (0); if (type.BuiltinType == BuiltinTypeSpec.Type.Long) ec.Emit (OpCodes.Conv_U8); Expr.Emit (ec); @@ -512,7 +527,7 @@ namespace Mono.CSharp case Operator.LogicalNot: Expr.Emit (ec); - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.Emit (OpCodes.Ceq); break; @@ -815,17 +830,26 @@ namespace Mono.CSharp loc = l; } - public override Expression CreateExpressionTree (ResolveContext ec) - { - Error_PointerInsideExpressionTree (ec); - return null; + public bool IsFixed { + get { return true; } } - + protected override void CloneTo (CloneContext clonectx, Expression t) { Indirection target = (Indirection) t; target.expr = expr.Clone (clonectx); - } + } + + public override bool ContainsEmitWithAwait () + { + throw new NotImplementedException (); + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + Error_PointerInsideExpressionTree (ec); + return null; + } public override void Emit (EmitContext ec) { @@ -845,13 +869,13 @@ namespace Mono.CSharp } } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { - prepared = prepare_for_load; + prepared = isCompound; expr.Emit (ec); - if (prepare_for_load) + if (isCompound) ec.Emit (OpCodes.Dup); source.Emit (ec); @@ -906,15 +930,6 @@ namespace Mono.CSharp return this; } - public bool IsFixed { - get { return true; } - } - - public override string ToString () - { - return "*(" + expr + ")"; - } - public override object Accept (StructuralVisitor visitor) { return visitor.Visit (this); @@ -979,7 +994,7 @@ namespace Mono.CSharp // // Emits target assignment using unmodified source value // - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { // // Allocate temporary variable to keep original value before it's modified @@ -988,7 +1003,7 @@ namespace Mono.CSharp expr.Emit (ec); temp.Store (ec); - ((IAssignMethod) expr).EmitAssign (ec, source, false, prepare_for_load); + ((IAssignMethod) expr).EmitAssign (ec, source, false, isCompound); if (leave_copy) Emit (ec); @@ -1014,7 +1029,7 @@ namespace Mono.CSharp Mode mode; bool is_expr, recurse; - Expression expr; + protected Expression expr; // Holds the real operation Expression operation; @@ -1038,6 +1053,11 @@ namespace Mono.CSharp expr = e; } + public override bool ContainsEmitWithAwait () + { + return expr.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { return new SimpleAssign (this, this).CreateExpressionTree (ec); @@ -1088,6 +1108,11 @@ namespace Mono.CSharp if (expr.Type.IsNullableType) return new Nullable.LiftedUnaryMutator (mode, expr, loc).Resolve (ec); + return DoResolveOperation (ec); + } + + protected Expression DoResolveOperation (ResolveContext ec) + { eclass = ExprClass.Value; type = expr.Type; @@ -1228,7 +1253,7 @@ namespace Mono.CSharp if (recurse) { ((IAssignMethod) expr).Emit (ec, is_expr && (mode == Mode.PostIncrement || mode == Mode.PostDecrement)); - operation.Emit (ec); + EmitOperation (ec); recurse = false; return; @@ -1237,6 +1262,11 @@ namespace Mono.CSharp EmitCode (ec, true); } + protected virtual void EmitOperation (EmitContext ec) + { + operation.Emit (ec); + } + public override void EmitStatement (EmitContext ec) { EmitCode (ec, false); @@ -1277,15 +1307,11 @@ namespace Mono.CSharp } - /// - /// Base class for the `Is' and `As' classes. - /// - /// - /// - /// FIXME: Split this in two, and we get to save the `Operator' Oper - /// size. - /// - public abstract class Probe : Expression { + // + // Base class for the `is' and `as' operators + // + public abstract class Probe : Expression + { public Expression ProbeType; protected Expression expr; protected TypeSpec probe_type_expr; @@ -1303,6 +1329,11 @@ namespace Mono.CSharp } } + public override bool ContainsEmitWithAwait () + { + return expr.ContainsEmitWithAwait (); + } + protected override Expression DoResolve (ResolveContext ec) { probe_type_expr = ProbeType.ResolveAsType (ec); @@ -1348,7 +1379,8 @@ namespace Mono.CSharp /// /// Implementation of the `is' operator. /// - public class Is : Probe { + public class Is : Probe + { Nullable.Unwrap expr_unwrap; public Is (Expression expr, Expression probe_type, Location l) @@ -1379,7 +1411,7 @@ namespace Mono.CSharp ec.Emit (OpCodes.Box, expr.Type); ec.Emit (OpCodes.Isinst, probe_type_expr); - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); ec.Emit (OpCodes.Cgt_Un); } @@ -1489,11 +1521,22 @@ namespace Mono.CSharp return CreateConstantResult (ec, true); } } else { - // if (InflatedTypeSpec.ContainsTypeParameter (d)) - // return this; + if (Convert.ImplicitReferenceConversionExists (d, t)) { + // + // Do not optimize for imported type + // + if (d.MemberDefinition.IsImported && d.BuiltinType != BuiltinTypeSpec.Type.None) + return this; + + // + // Turn is check into simple null check for implicitly convertible reference types + // + return ReducedExpression.Create ( + new Binary (Binary.Operator.Inequality, expr, new NullLiteral (loc), loc).Resolve (ec), + this).Resolve (ec); + } - if (Convert.ImplicitReferenceConversionExists (d, t) || - Convert.ExplicitReferenceConversionExists (d, t)) { + if (Convert.ExplicitReferenceConversionExists (d, t)) { return this; } } @@ -1741,6 +1784,17 @@ namespace Mono.CSharp this.loc = loc; } + public override bool IsSideEffectFree { + get { + return true; + } + } + + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -1780,6 +1834,7 @@ namespace Mono.CSharp temp_storage.AddressOf(ec, AddressOp.LoadStore); ec.Emit(OpCodes.Initobj, type); temp_storage.Emit(ec); + temp_storage.Release (ec); } #if NET_4_0 && !STATIC @@ -2380,6 +2435,11 @@ namespace Mono.CSharp } } + public override bool ContainsEmitWithAwait () + { + return left.ContainsEmitWithAwait () || right.ContainsEmitWithAwait (); + } + public static void EmitOperatorOpcode (EmitContext ec, Operator oper, TypeSpec l) { OpCode opcode; @@ -2453,7 +2513,7 @@ namespace Mono.CSharp case Operator.Inequality: ec.Emit (OpCodes.Ceq); - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); opcode = OpCodes.Ceq; break; @@ -2477,7 +2537,7 @@ namespace Mono.CSharp ec.Emit (OpCodes.Cgt_Un); else ec.Emit (OpCodes.Cgt); - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); opcode = OpCodes.Ceq; break; @@ -2488,7 +2548,7 @@ namespace Mono.CSharp else ec.Emit (OpCodes.Clt); - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); opcode = OpCodes.Ceq; break; @@ -3815,6 +3875,14 @@ namespace Mono.CSharp protected virtual void EmitOperator (EmitContext ec, TypeSpec l) { + if (ec.HasSet (BuilderContext.Options.AsyncBody) && right.ContainsEmitWithAwait ()) { + left = left.EmitToField (ec); + + if ((oper & Operator.LogicalMask) == 0) { + right = right.EmitToField (ec); + } + } + // // Handle short-circuit operators differently // than the rest @@ -3829,7 +3897,7 @@ namespace Mono.CSharp ec.Emit (OpCodes.Br_S, end); ec.MarkLabel (load_result); - ec.Emit (is_or ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); + ec.EmitInt (is_or ? 1 : 0); ec.MarkLabel (end); return; } @@ -4018,6 +4086,11 @@ namespace Mono.CSharp arguments = new Arguments (2); } + public override bool ContainsEmitWithAwait () + { + return arguments.ContainsEmitWithAwait (); + } + public static StringConcat Create (ResolveContext rc, Expression left, Expression right, Location loc) { if (left.eclass == ExprClass.Unresolved || right.eclass == ExprClass.Unresolved) @@ -4115,8 +4188,10 @@ namespace Mono.CSharp var members = GetConcatMethodCandidates (); var res = new OverloadResolver (members, OverloadResolver.Restrictions.NoBaseMembers, loc); var method = res.ResolveMember (new ResolveContext (ec.MemberContext), ref arguments); - if (method != null) - Invocation.EmitCall (ec, null, method, arguments, loc); + if (method != null) { + var call = new CallEmitter (); + call.EmitPredefined (ec, method, arguments); + } } public override SLE.Expression MakeExpression (BuilderContext ctx) @@ -4132,7 +4207,8 @@ namespace Mono.CSharp // // User-defined conditional logical operator // - public class ConditionalLogicalOperator : UserOperatorCall { + public class ConditionalLogicalOperator : UserOperatorCall + { readonly bool is_and; Expression oper_expr; @@ -4175,13 +4251,33 @@ namespace Mono.CSharp // // Emit and duplicate left argument // - arguments [0].Expr.Emit (ec); - ec.Emit (OpCodes.Dup); - arguments.RemoveAt (0); + bool right_contains_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments[1].Expr.ContainsEmitWithAwait (); + if (right_contains_await) { + arguments[0] = arguments[0].EmitToField (ec); + arguments[0].Expr.Emit (ec); + } else { + arguments[0].Expr.Emit (ec); + ec.Emit (OpCodes.Dup); + arguments.RemoveAt (0); + } oper_expr.EmitBranchable (ec, end_target, true); + base.Emit (ec); - ec.MarkLabel (end_target); + + if (right_contains_await) { + // + // Special handling when right expression contains await and left argument + // could not be left on stack before logical branch + // + Label skip_left_load = ec.DefineLabel (); + ec.Emit (OpCodes.Br_S, skip_left_load); + ec.MarkLabel (end_target); + arguments[0].Expr.Emit (ec); + ec.MarkLabel (skip_left_load); + } else { + ec.MarkLabel (end_target); + } } } @@ -4201,6 +4297,11 @@ namespace Mono.CSharp this.op = op; } + public override bool ContainsEmitWithAwait () + { + throw new NotImplementedException (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Error_PointerInsideExpressionTree (ec); @@ -4423,6 +4524,8 @@ namespace Mono.CSharp this.loc = loc; } + #region Properties + public Expression Expr { get { return expr; @@ -4440,7 +4543,14 @@ namespace Mono.CSharp return false_expr; } } - + + #endregion + + public override bool ContainsEmitWithAwait () + { + return Expr.ContainsEmitWithAwait () || true_expr.ContainsEmitWithAwait () || false_expr.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (3); @@ -4453,8 +4563,32 @@ namespace Mono.CSharp protected override Expression DoResolve (ResolveContext ec) { expr = expr.Resolve (ec); - true_expr = true_expr.Resolve (ec); - false_expr = false_expr.Resolve (ec); + + // + // Unreachable code needs different resolve path. For instance for await + // expression to not generate unreachable resumable statement + // + Constant c = expr as Constant; + if (c != null && ec.CurrentBranching != null) { + bool unreachable = ec.CurrentBranching.CurrentUsageVector.IsUnreachable; + + if (c.IsDefaultValue) { + ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true; + true_expr = true_expr.Resolve (ec); + ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable; + + false_expr = false_expr.Resolve (ec); + } else { + true_expr = true_expr.Resolve (ec); + + ec.CurrentBranching.CurrentUsageVector.IsUnreachable = true; + false_expr = false_expr.Resolve (ec); + ec.CurrentBranching.CurrentUsageVector.IsUnreachable = unreachable; + } + } else { + true_expr = true_expr.Resolve (ec); + false_expr = false_expr.Resolve (ec); + } if (true_expr == null || false_expr == null || expr == null) return null; @@ -4494,11 +4628,17 @@ namespace Mono.CSharp } } - // Dead code optimalization - Constant c = expr as Constant; - if (c != null){ + if (c != null) { bool is_false = c.IsDefaultValue; - ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, "Unreachable expression code detected"); + + // + // Don't issue the warning for constant expressions + // + if (!(is_false ? true_expr is Constant : false_expr is Constant)) { + ec.Report.Warning (429, 4, is_false ? true_expr.Location : false_expr.Location, + "Unreachable expression code detected"); + } + return ReducedExpression.Create ( is_false ? false_expr : true_expr, this, false_expr is Constant && true_expr is Constant).Resolve (ec); @@ -4515,13 +4655,6 @@ namespace Mono.CSharp expr.EmitBranchable (ec, false_target, false); true_expr.Emit (ec); - if (type.IsInterface) { - LocalBuilder temp = ec.GetTemporaryLocal (type); - ec.Emit (OpCodes.Stloc, temp); - ec.Emit (OpCodes.Ldloc, temp); - ec.FreeTemporaryLocal (temp, type); - } - ec.Emit (OpCodes.Br, end_target); ec.MarkLabel (false_target); false_expr.Emit (ec); @@ -4543,7 +4676,8 @@ namespace Mono.CSharp } } - public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference { + public abstract class VariableReference : Expression, IAssignMethod, IMemoryLocation, IVariableReference + { LocalTemporary temp; #region Abstract @@ -4578,6 +4712,22 @@ namespace Mono.CSharp Variable.EmitAddressOf (ec); } + public override bool ContainsEmitWithAwait () + { + return false; + } + + public override Expression CreateExpressionTree (ResolveContext ec) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) + return hv.CreateExpressionTree (); + + Arguments arg = new Arguments (1); + arg.Add (new Argument (this)); + return CreateExpressionFactoryCall (ec, "Constant", arg); + } + public override Expression DoResolveLValue (ResolveContext rc, Expression right_side) { if (IsLockedByStatement) { @@ -4683,6 +4833,15 @@ namespace Mono.CSharp } } + public override Expression EmitToField (EmitContext ec) + { + HoistedVariable hv = GetHoistedVariable (ec); + if (hv != null) { + return hv.EmitToField (ec); + } + + return base.EmitToField (ec); + } public HoistedVariable GetHoistedVariable (ResolveContext rc) { @@ -4767,17 +4926,6 @@ namespace Mono.CSharp local_info.AddressTaken = true; } - public override Expression CreateExpressionTree (ResolveContext ec) - { - HoistedVariable hv = GetHoistedVariable (ec); - if (hv != null) - return hv.CreateExpressionTree (); - - Arguments arg = new Arguments (1); - arg.Add (new Argument (this)); - return CreateExpressionFactoryCall (ec, "Constant", arg); - } - void DoResolveBase (ResolveContext ec) { VerifyAssigned (ec); @@ -5074,22 +5222,6 @@ namespace Mono.CSharp SetAssigned (ec); return base.DoResolveLValue (ec, right_side); } - - static public void EmitLdArg (EmitContext ec, int x) - { - switch (x) { - case 0: ec.Emit (OpCodes.Ldarg_0); break; - case 1: ec.Emit (OpCodes.Ldarg_1); break; - case 2: ec.Emit (OpCodes.Ldarg_2); break; - case 3: ec.Emit (OpCodes.Ldarg_3); break; - default: - if (x > byte.MaxValue) - ec.Emit (OpCodes.Ldarg, x); - else - ec.Emit (OpCodes.Ldarg_S, (byte) x); - break; - } - } } /// @@ -5137,6 +5269,13 @@ namespace Mono.CSharp target.expr = expr.Clone (clonectx); } + public override bool ContainsEmitWithAwait () + { + if (arguments != null && arguments.ContainsEmitWithAwait ()) + return true; + + return mg.ContainsEmitWithAwait (); + } public override Expression CreateExpressionTree (ResolveContext ec) { @@ -5333,168 +5472,6 @@ namespace Mono.CSharp return true; } - // - // Used to decide whether call or callvirt is needed - // - static bool IsVirtualCallRequired (Expression instance, MethodSpec method) - { - // - // There are 2 scenarious where we emit callvirt - // - // Case 1: A method is virtual and it's not used to call base - // Case 2: A method instance expression can be null. In this casen callvirt ensures - // correct NRE exception when the method is called - // - var decl_type = method.DeclaringType; - if (decl_type.IsStruct || decl_type.IsEnum) - return false; - - if (instance is BaseThis) - return false; - - // - // It's non-virtual and will never be null - // - if (!method.IsVirtual && (instance is This || instance is New || instance is ArrayCreation || instance is DelegateCreation)) - return false; - - return true; - } - - /// - /// is_base tells whether we want to force the use of the `call' - /// opcode instead of using callvirt. Call is required to call - /// a specific method, while callvirt will always use the most - /// recent method in the vtable. - /// - /// is_static tells whether this is an invocation on a static method - /// - /// instance_expr is an expression that represents the instance - /// it must be non-null if is_static is false. - /// - /// method is the method to invoke. - /// - /// Arguments is the list of arguments to pass to the method or constructor. - /// - public static void EmitCall (EmitContext ec, Expression instance_expr, - MethodSpec method, Arguments Arguments, Location loc) - { - EmitCall (ec, instance_expr, method, Arguments, loc, false, false); - } - - // `dup_args' leaves an extra copy of the arguments on the stack - // `omit_args' does not leave any arguments at all. - // So, basically, you could make one call with `dup_args' set to true, - // and then another with `omit_args' set to true, and the two calls - // would have the same set of arguments. However, each argument would - // only have been evaluated once. - public static void EmitCall (EmitContext ec, Expression instance_expr, - MethodSpec method, Arguments Arguments, Location loc, - bool dup_args, bool omit_args) - { - LocalTemporary this_arg = null; - - // Speed up the check by not doing it on not allowed targets - if (method.ReturnType.Kind == MemberKind.Void && method.IsConditionallyExcluded (ec.Module.Compiler, loc)) - return; - - OpCode call_op; - TypeSpec iexpr_type; - - if (method.IsStatic) { - iexpr_type = null; - call_op = OpCodes.Call; - } else { - iexpr_type = instance_expr.Type; - - if (IsVirtualCallRequired (instance_expr, method)) { - call_op = OpCodes.Callvirt; - } else { - call_op = OpCodes.Call; - } - - // - // If this is ourselves, push "this" - // - if (!omit_args) { - TypeSpec t = iexpr_type; - - // - // Push the instance expression - // - if ((iexpr_type.IsStruct && (call_op == OpCodes.Callvirt || (call_op == OpCodes.Call && method.DeclaringType == iexpr_type))) || - iexpr_type.IsGenericParameter || method.DeclaringType.IsNullableType) { - // - // If the expression implements IMemoryLocation, then - // we can optimize and use AddressOf on the - // return. - // - // If not we have to use some temporary storage for - // it. - var iml = instance_expr as IMemoryLocation; - if (iml != null) { - iml.AddressOf (ec, AddressOp.Load); - } else { - LocalTemporary temp = new LocalTemporary (iexpr_type); - instance_expr.Emit (ec); - temp.Store (ec); - temp.AddressOf (ec, AddressOp.Load); - } - - // avoid the overhead of doing this all the time. - if (dup_args) - t = ReferenceContainer.MakeType (ec.Module, iexpr_type); - } else if (iexpr_type.IsEnum || iexpr_type.IsStruct) { - instance_expr.Emit (ec); - ec.Emit (OpCodes.Box, iexpr_type); - t = iexpr_type = ec.BuiltinTypes.Object; - } else { - instance_expr.Emit (ec); - } - - if (dup_args) { - ec.Emit (OpCodes.Dup); - if (Arguments != null && Arguments.Count != 0) { - this_arg = new LocalTemporary (t); - this_arg.Store (ec); - } - } - } - } - - if (!omit_args && Arguments != null) { - var dup_arg_exprs = Arguments.Emit (ec, dup_args); - if (dup_args) { - this_arg.Emit (ec); - LocalTemporary lt; - foreach (var dup in dup_arg_exprs) { - dup.Emit (ec); - lt = dup as LocalTemporary; - if (lt != null) - lt.Release (ec); - } - } - } - - if (call_op == OpCodes.Callvirt && (iexpr_type.IsGenericParameter || iexpr_type.IsStruct)) { - ec.Emit (OpCodes.Constrained, iexpr_type); - } - - if (method.Parameters.HasArglist) { - var varargs_types = GetVarargsTypes (method, Arguments); - ec.Emit (call_op, method, varargs_types); - return; - } - - // - // If you have: - // this.DoFoo (); - // and DoFoo is not virtual, you can omit the callvirt, - // because you don't need the null checking behavior. - // - ec.Emit (call_op, method); - } - public override void Emit (EmitContext ec) { mg.EmitCall (ec, arguments); @@ -5621,6 +5598,11 @@ namespace Mono.CSharp return null; } + public override bool ContainsEmitWithAwait () + { + return arguments != null && arguments.ContainsEmitWithAwait (); + } + // // Checks whether the type is an interface that has the // [ComImport, CoClass] attributes and must be treated @@ -5776,6 +5758,7 @@ namespace Mono.CSharp temp.AddressOf (ec, AddressOp.Store); ec.Emit (OpCodes.Initobj, type); temp.Emit (ec); + temp.Release (ec); ec.Emit (OpCodes.Br_S, label_end); ec.MarkLabel (label_activator); @@ -5822,9 +5805,13 @@ namespace Mono.CSharp } else if (vr != null && vr.IsRef) { vr.EmitLoad (ec); } - - if (arguments != null) + + if (arguments != null) { + if (ec.HasSet (BuilderContext.Options.AsyncBody) && (arguments.Count > (this is NewInitialize ? 0 : 1)) && arguments.ContainsEmitWithAwait ()) + arguments = arguments.Emit (ec, false, true); + arguments.Emit (ec); + } if (is_value_type) { if (method == null) { @@ -5985,6 +5972,11 @@ namespace Mono.CSharp elements.Add (expr); } + public override bool ContainsEmitWithAwait () + { + throw new NotSupportedException (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -6003,7 +5995,7 @@ namespace Mono.CSharp { var current_field = rc.CurrentMemberDefinition as FieldBase; TypeExpression type; - if (current_field != null) { + if (current_field != null && rc.CurrentAnonymousMethod == null) { type = new TypeExpression (current_field.MemberType, current_field.Location); } else if (variable != null) { if (variable.TypeExpression is VarExpr) { @@ -6119,12 +6111,7 @@ namespace Mono.CSharp { } - protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) - { - ec.Report.Error (248, loc, "Cannot create an array with a negative size"); - } - - bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds) + bool CheckIndices (ResolveContext ec, ArrayInitializer probe, int idx, bool specified_dims, int child_bounds) { if (initializers != null && bounds == null) { // @@ -6214,6 +6201,16 @@ namespace Mono.CSharp return true; } + public override bool ContainsEmitWithAwait () + { + foreach (var arg in arguments) { + if (arg.ContainsEmitWithAwait ()) + return true; + } + + return InitializersContainAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args; @@ -6262,6 +6259,24 @@ namespace Mono.CSharp } } + protected override void Error_NegativeArrayIndex (ResolveContext ec, Location loc) + { + ec.Report.Error (248, loc, "Cannot create an array with a negative size"); + } + + bool InitializersContainAwait () + { + if (array_data == null) + return false; + + foreach (var expr in array_data) { + if (expr.ContainsEmitWithAwait ()) + return true; + } + + return false; + } + protected virtual Expression ResolveArrayElement (ResolveContext ec, Expression element) { element = element.Resolve (ec); @@ -6508,7 +6523,7 @@ namespace Mono.CSharp // // Emits the initializers for the array // - void EmitStaticInitializers (EmitContext ec) + void EmitStaticInitializers (EmitContext ec, FieldExpr stackArray) { var m = ec.Module.PredefinedMembers.RuntimeHelpersInitializeArray.Resolve (loc); if (m == null) @@ -6520,7 +6535,12 @@ namespace Mono.CSharp byte [] data = MakeByteBlob (); var fb = ec.CurrentTypeDefinition.Module.MakeStaticData (data, loc); - ec.Emit (OpCodes.Dup); + if (stackArray == null) { + ec.Emit (OpCodes.Dup); + } else { + stackArray.Emit (ec); + } + ec.Emit (OpCodes.Ldtoken, fb); ec.Emit (OpCodes.Call, m); } @@ -6532,7 +6552,7 @@ namespace Mono.CSharp // // This always expect the top value on the stack to be the array // - void EmitDynamicInitializers (EmitContext ec, bool emitConstants) + void EmitDynamicInitializers (EmitContext ec, bool emitConstants, FieldExpr stackArray) { int dims = bounds.Count; var current_pos = new int [dims]; @@ -6544,9 +6564,18 @@ namespace Mono.CSharp // Constant can be initialized via StaticInitializer if (c == null || (c != null && emitConstants && !c.IsDefaultInitializer (array_element_type))) { - TypeSpec etype = e.Type; - ec.Emit (OpCodes.Dup); + var etype = e.Type; + + if (stackArray != null) { + if (e.ContainsEmitWithAwait ()) { + e = e.EmitToField (ec); + } + + stackArray.Emit (ec); + } else { + ec.Emit (OpCodes.Dup); + } for (int idx = 0; idx < dims; idx++) ec.EmitInt (current_pos [idx]); @@ -6600,31 +6629,47 @@ namespace Mono.CSharp first_emit_temp.Store (ec); } - foreach (Expression e in arguments) - e.Emit (ec); + FieldExpr await_stack_field; + if (ec.HasSet (BuilderContext.Options.AsyncBody) && InitializersContainAwait ()) { + await_stack_field = ec.GetTemporaryField (type); + ec.EmitThis (); + } else { + await_stack_field = null; + } + + EmitExpressionsList (ec, arguments); ec.EmitArrayNew ((ArrayContainer) type); if (initializers == null) return; + if (await_stack_field != null) + await_stack_field.EmitAssignFromStack (ec); + #if STATIC - // Emit static initializer for arrays which have contain more than 2 items and + // + // Emit static initializer for arrays which contain more than 2 items and // the static initializer will initialize at least 25% of array values or there // is more than 10 items to be initialized + // // NOTE: const_initializers_count does not contain default constant values. + // if (const_initializers_count > 2 && (array_data.Count > 10 || const_initializers_count * 4 > (array_data.Count)) && (BuiltinTypeSpec.IsPrimitiveType (array_element_type) || array_element_type.IsEnum)) { - EmitStaticInitializers (ec); + EmitStaticInitializers (ec, await_stack_field); if (!only_constant_initializers) - EmitDynamicInitializers (ec, false); + EmitDynamicInitializers (ec, false, await_stack_field); } else #endif { - EmitDynamicInitializers (ec, true); + EmitDynamicInitializers (ec, true, await_stack_field); } + if (await_stack_field != null) + await_stack_field.Emit (ec); + if (first_emit_temp != null) first_emit_temp.Release (ec); } @@ -6828,7 +6873,7 @@ namespace Mono.CSharp public void Emit (EmitContext ec) { - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); } public void EmitAssign (EmitContext ec) @@ -6838,7 +6883,7 @@ namespace Mono.CSharp public void EmitAddressOf (EmitContext ec) { - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); } } @@ -6867,6 +6912,12 @@ namespace Mono.CSharp get { return type.IsStruct; } } + public override bool IsSideEffectFree { + get { + return true; + } + } + protected override ILocalVariable Variable { get { return ThisVariable.Instance; } } @@ -6955,16 +7006,6 @@ namespace Mono.CSharp } } - public override Expression CreateExpressionTree (ResolveContext ec) - { - Arguments args = new Arguments (1); - args.Add (new Argument (this)); - - // Use typeless constant for ldarg.0 to save some - // space and avoid problems with anonymous stories - return CreateExpressionFactoryCall (ec, "Constant", args); - } - protected override Expression DoResolve (ResolveContext ec) { ResolveBase (ec); @@ -7035,6 +7076,16 @@ namespace Mono.CSharp this.loc = loc; } + protected override void CloneTo (CloneContext clonectx, Expression target) + { + // nothing. + } + + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -7058,10 +7109,6 @@ namespace Mono.CSharp ec.Emit (OpCodes.Arglist); } - protected override void CloneTo (CloneContext clonectx, Expression target) - { - // nothing. - } public override object Accept (StructuralVisitor visitor) { return visitor.Visit (this); @@ -7098,6 +7145,11 @@ namespace Mono.CSharp return retval; } } + + public override bool ContainsEmitWithAwait () + { + throw new NotImplementedException (); + } public override Expression CreateExpressionTree (ResolveContext ec) { @@ -7151,6 +7203,11 @@ namespace Mono.CSharp this.loc = loc; } + public override bool ContainsEmitWithAwait () + { + return false; + } + protected override Expression DoResolve (ResolveContext rc) { expr = expr.Resolve (rc); @@ -7222,6 +7279,11 @@ namespace Mono.CSharp this.loc = loc; } + public override bool ContainsEmitWithAwait () + { + throw new NotImplementedException (); + } + protected override Expression DoResolve (ResolveContext rc) { expr = expr.ResolveLValue (rc, EmptyExpression.LValueMemberAccess); @@ -7265,6 +7327,13 @@ namespace Mono.CSharp } #region Properties + + public override bool IsSideEffectFree { + get { + return true; + } + } + public TypeSpec TypeArgument { get { return typearg; @@ -7279,6 +7348,19 @@ namespace Mono.CSharp #endregion + + protected override void CloneTo (CloneContext clonectx, Expression t) + { + TypeOf target = (TypeOf) t; + if (QueriedType != null) + target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx); + } + + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -7372,14 +7454,7 @@ namespace Mono.CSharp if (m != null) ec.Emit (OpCodes.Call, m); } - - protected override void CloneTo (CloneContext clonectx, Expression t) - { - TypeOf target = (TypeOf) t; - if (QueriedType != null) - target.QueriedType = (FullNamedExpression) QueriedType.Clone (clonectx); - } - + public override object Accept (StructuralVisitor visitor) { return visitor.Visit (this); @@ -7436,6 +7511,17 @@ namespace Mono.CSharp this.loc = loc; } + public override bool IsSideEffectFree { + get { + return true; + } + } + + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -7516,6 +7602,17 @@ namespace Mono.CSharp loc = l; } + public override bool IsSideEffectFree { + get { + return true; + } + } + + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { Error_PointerInsideExpressionTree (ec); @@ -7666,6 +7763,13 @@ namespace Mono.CSharp { protected Expression expr; +#if FULL_AST + public Location DotLocation { + get; + set; + } +#endif + public MemberAccess (Expression expr, string id) : base (id, expr.Location) { @@ -7739,7 +7843,7 @@ namespace Mono.CSharp const MemberKind dot_kinds = MemberKind.Class | MemberKind.Struct | MemberKind.Delegate | MemberKind.Enum | MemberKind.Interface | MemberKind.TypeParameter | MemberKind.ArrayType; - return (type.Kind & dot_kinds) != 0; + return (type.Kind & dot_kinds) != 0 || type.BuiltinType == BuiltinTypeSpec.Type.Dynamic; } public override Expression LookupNameExpression (ResolveContext rc, MemberLookupRestrictions restrictions) @@ -7817,10 +7921,9 @@ namespace Mono.CSharp // Try to look for extension method when member lookup failed // if (MethodGroupExpr.IsExtensionMethodArgument (expr)) { - NamespaceContainer scope = null; - var methods = rc.LookupExtensionMethod (expr_type, Name, lookup_arity, ref scope); + var methods = rc.LookupExtensionMethod (expr_type, Name, lookup_arity); if (methods != null) { - var emg = new ExtensionMethodGroupExpr (methods, scope, expr, loc); + var emg = new ExtensionMethodGroupExpr (methods, expr, loc); if (HasTypeArguments) { if (!targs.Resolve (rc)) return null; @@ -7971,8 +8074,14 @@ namespace Mono.CSharp if (nested.IsAccessible (rc)) break; - // Keep looking after inaccessible candidate - expr_type = nested.DeclaringType.BaseType; + // + // Keep looking after inaccessible candidate but only if + // we are not in same context as the definition itself + // + if (expr_type.MemberDefinition == rc.CurrentMemberDefinition) + break; + + expr_type = expr_type.BaseType; } TypeExpr texpr; @@ -8054,6 +8163,11 @@ namespace Mono.CSharp Expr = e; loc = l; } + + public override bool ContainsEmitWithAwait () + { + return Expr.ContainsEmitWithAwait (); + } public override Expression CreateExpressionTree (ResolveContext ec) { @@ -8079,19 +8193,19 @@ namespace Mono.CSharp public override void Emit (EmitContext ec) { - using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + using (ec.With (EmitContext.Options.CheckedScope, true)) Expr.Emit (ec); } public override void EmitBranchable (EmitContext ec, Label target, bool on_true) { - using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + using (ec.With (EmitContext.Options.CheckedScope, true)) Expr.EmitBranchable (ec, target, on_true); } public override SLE.Expression MakeExpression (BuilderContext ctx) { - using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) { + using (ctx.With (BuilderContext.Options.CheckedScope, true)) { return Expr.MakeExpression (ctx); } } @@ -8120,6 +8234,11 @@ namespace Mono.CSharp Expr = e; loc = l; } + + public override bool ContainsEmitWithAwait () + { + return Expr.ContainsEmitWithAwait (); + } public override Expression CreateExpressionTree (ResolveContext ec) { @@ -8145,13 +8264,13 @@ namespace Mono.CSharp public override void Emit (EmitContext ec) { - using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + using (ec.With (EmitContext.Options.CheckedScope, false)) Expr.Emit (ec); } public override void EmitBranchable (EmitContext ec, Label target, bool on_true) { - using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + using (ec.With (EmitContext.Options.CheckedScope, false)) Expr.EmitBranchable (ec, target, on_true); } @@ -8173,7 +8292,8 @@ namespace Mono.CSharp /// During semantic analysis these are transformed into /// IndexerAccess, ArrayAccess or a PointerArithmetic. /// - public class ElementAccess : Expression { + public class ElementAccess : Expression + { public Arguments Arguments; public Expression Expr; @@ -8184,6 +8304,11 @@ namespace Mono.CSharp this.Arguments = args; } + public override bool ContainsEmitWithAwait () + { + return Expr.ContainsEmitWithAwait () || Arguments.ContainsEmitWithAwait (); + } + // // We perform some simple tests, and then to "split" the emit and store // code we create an instance of a different class, and return that. @@ -8306,9 +8431,9 @@ namespace Mono.CSharp // ElementAccess ea; - LocalTemporary temp, expr_copy; - Expression[] prepared_arguments; + LocalTemporary temp; bool prepared; + bool? has_await_args; public ArrayAccess (ElementAccess ea_data, Location l) { @@ -8316,11 +8441,28 @@ namespace Mono.CSharp loc = l; } + public void AddressOf (EmitContext ec, AddressOp mode) + { + var ac = (ArrayContainer) ea.Expr.Type; + + LoadInstanceAndArguments (ec, false, false); + + if (ac.Element.IsGenericParameter && mode == AddressOp.Load) + ec.Emit (OpCodes.Readonly); + + ec.EmitArrayAddress (ac); + } + public override Expression CreateExpressionTree (ResolveContext ec) { return ea.CreateExpressionTree (ec); } + public override bool ContainsEmitWithAwait () + { + return ea.ContainsEmitWithAwait (); + } + public override Expression DoResolveLValue (ResolveContext ec, Expression right_side) { return DoResolve (ec); @@ -8365,10 +8507,24 @@ namespace Mono.CSharp // // Load the array arguments into the stack. // - void LoadArrayAndArguments (EmitContext ec) + void LoadInstanceAndArguments (EmitContext ec, bool duplicateArguments, bool prepareAwait) { - ea.Expr.Emit (ec); - ea.Arguments.Emit (ec); + if (prepareAwait) { + ea.Expr = ea.Expr.EmitToField (ec); + } else if (duplicateArguments) { + ea.Expr.Emit (ec); + ec.Emit (OpCodes.Dup); + + var copy = new LocalTemporary (ea.Expr.Type); + copy.Store (ec); + ea.Expr = copy; + } else { + ea.Expr.Emit (ec); + } + + var dup_args = ea.Arguments.Emit (ec, duplicateArguments, prepareAwait); + if (dup_args != null) + ea.Arguments = dup_args; } public void Emit (EmitContext ec, bool leave_copy) @@ -8378,19 +8534,11 @@ namespace Mono.CSharp if (prepared) { ec.EmitLoadFromPtr (type); } else { - if (prepared_arguments == null) { - LoadArrayAndArguments (ec); - } else { - expr_copy.Emit (ec); - LocalTemporary lt; - foreach (var expr in prepared_arguments) { - expr.Emit (ec); - lt = expr as LocalTemporary; - if (lt != null) - lt.Release (ec); - } + if (!has_await_args.HasValue && ec.HasSet (BuilderContext.Options.AsyncBody) && ea.Arguments.ContainsEmitWithAwait ()) { + LoadInstanceAndArguments (ec, false, true); } + LoadInstanceAndArguments (ec, false, false); ec.EmitArrayLoad (ac); } @@ -8406,40 +8554,56 @@ namespace Mono.CSharp Emit (ec, false); } - public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) + public void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { var ac = (ArrayContainer) ea.Expr.Type; TypeSpec t = source.Type; + has_await_args = ec.HasSet (BuilderContext.Options.AsyncBody) && (ea.Arguments.ContainsEmitWithAwait () || source.ContainsEmitWithAwait ()); + // // When we are dealing with a struct, get the address of it to avoid value copy // Same cannot be done for reference type because array covariance and the // check in ldelema requires to specify the type of array element stored at the index // - if (t.IsStruct && ((prepare_for_load && !(source is DynamicExpressionStatement)) || !BuiltinTypeSpec.IsPrimitiveType (t))) { - LoadArrayAndArguments (ec); + if (t.IsStruct && ((isCompound && !(source is DynamicExpressionStatement)) || !BuiltinTypeSpec.IsPrimitiveType (t))) { + LoadInstanceAndArguments (ec, false, has_await_args.Value); + + if (has_await_args.Value) { + if (source.ContainsEmitWithAwait ()) { + source = source.EmitToField (ec); + isCompound = false; + prepared = true; + } + + LoadInstanceAndArguments (ec, isCompound, false); + } else { + prepared = true; + } + ec.EmitArrayAddress (ac); - if (prepare_for_load) { + if (isCompound) { ec.Emit (OpCodes.Dup); + prepared = true; } + } else { + LoadInstanceAndArguments (ec, isCompound, has_await_args.Value); - prepared = true; - } else if (prepare_for_load) { - ea.Expr.Emit (ec); - ec.Emit (OpCodes.Dup); + if (has_await_args.Value) { + if (source.ContainsEmitWithAwait ()) + source = source.EmitToField (ec); - expr_copy = new LocalTemporary (ea.Expr.Type); - expr_copy.Store (ec); - prepared_arguments = ea.Arguments.Emit (ec, true); - } else { - LoadArrayAndArguments (ec); + LoadInstanceAndArguments (ec, false, false); + } } source.Emit (ec); - if (expr_copy != null) { - expr_copy.Release (ec); + if (isCompound) { + var lt = ea.Expr as LocalTemporary; + if (lt != null) + lt.Release (ec); } if (leave_copy) { @@ -8460,28 +8624,19 @@ namespace Mono.CSharp } } - public void EmitNew (EmitContext ec, New source, bool leave_copy) - { - if (!source.Emit (ec, this)) { - if (leave_copy) - throw new NotImplementedException (); - - return; - } - - throw new NotImplementedException (); - } - - public void AddressOf (EmitContext ec, AddressOp mode) + public override Expression EmitToField (EmitContext ec) { - var ac = (ArrayContainer) ea.Expr.Type; - - LoadArrayAndArguments (ec); - - if (ac.Element.IsGenericParameter && mode == AddressOp.Load) - ec.Emit (OpCodes.Readonly); - - ec.EmitArrayAddress (ac); + // + // Have to be specialized for arrays to get access to + // underlying element. Instead of another result copy we + // need direct access to element + // + // Consider: + // + // CallRef (ref a[await Task.Factory.StartNew (() => 1)]); + // + ea.Expr = ea.Expr.EmitToField (ec); + return this; } public SLE.Expression MakeAssignExpression (BuilderContext ctx, Expression source) @@ -8500,7 +8655,7 @@ namespace Mono.CSharp SLE.Expression[] MakeExpressionArguments (BuilderContext ctx) { - using (ctx.With (BuilderContext.Options.AllCheckStateFlags, true)) { + using (ctx.With (BuilderContext.Options.CheckedScope, true)) { return Arguments.MakeExpression (ea.Arguments, ctx); } } @@ -8509,9 +8664,8 @@ namespace Mono.CSharp // // Indexer access expression // - class IndexerExpr : PropertyOrIndexerExpr, OverloadResolver.IBaseMembersProvider + sealed class IndexerExpr : PropertyOrIndexerExpr, OverloadResolver.IBaseMembersProvider { - LocalTemporary prepared_value; IList indexers; Arguments arguments; TypeSpec queried_type; @@ -8527,6 +8681,15 @@ namespace Mono.CSharp #region Properties + protected override Arguments Arguments { + get { + return arguments; + } + set { + arguments = value; + } + } + protected override TypeSpec DeclaringType { get { return best_candidate.DeclaringType; @@ -8553,6 +8716,11 @@ namespace Mono.CSharp #endregion + public override bool ContainsEmitWithAwait () + { + return base.ContainsEmitWithAwait () || arguments.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = Arguments.CreateForExpressionTree (ec, arguments, @@ -8561,55 +8729,71 @@ namespace Mono.CSharp return CreateExpressionFactoryCall (ec, "Call", args); } - - public override void Emit (EmitContext ec, bool leave_copy) + + public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool isCompound) { - if (prepared) { - prepared_value.Emit (ec); - } else { - Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc); - } + LocalTemporary await_source_arg = null; - if (leave_copy) { - ec.Emit (OpCodes.Dup); - temp = new LocalTemporary (Type); - temp.Store (ec); - } - } - - public override void EmitAssign (EmitContext ec, Expression source, bool leave_copy, bool prepare_for_load) - { - prepared = prepare_for_load; - Expression value = source; + if (isCompound) { + emitting_compound_assignment = true; + if (source is DynamicExpressionStatement) { + Emit (ec, false); + } else { + source.Emit (ec); + } + emitting_compound_assignment = false; - if (prepared) { - Invocation.EmitCall (ec, InstanceExpression, Getter, arguments, loc, true, false); + if (has_await_arguments) { + await_source_arg = new LocalTemporary (Type); + await_source_arg.Store (ec); - prepared_value = new LocalTemporary (type); - prepared_value.Store (ec); - source.Emit (ec); - prepared_value.Release (ec); + arguments.Add (new Argument (await_source_arg)); + if (leave_copy) { + temp = await_source_arg; + } + + has_await_arguments = false; + } else { + arguments = null; + + if (leave_copy) { + ec.Emit (OpCodes.Dup); + temp = new LocalTemporary (Type); + temp.Store (ec); + } + } + } else { if (leave_copy) { - ec.Emit (OpCodes.Dup); - temp = new LocalTemporary (Type); - temp.Store (ec); + if (ec.HasSet (BuilderContext.Options.AsyncBody) && (arguments.ContainsEmitWithAwait () || source.ContainsEmitWithAwait ())) { + source = source.EmitToField (ec); + } else { + temp = new LocalTemporary (Type); + source.Emit (ec); + temp.Store (ec); + source = temp; + } } - } else if (leave_copy) { - temp = new LocalTemporary (Type); - source.Emit (ec); - temp.Store (ec); - value = temp; + + arguments.Add (new Argument (source)); } - - if (!prepared) - arguments.Add (new Argument (value)); - Invocation.EmitCall (ec, InstanceExpression, Setter, arguments, loc, false, prepared); - + var call = new CallEmitter (); + call.InstanceExpression = InstanceExpression; + if (arguments == null) + call.InstanceExpressionOnStack = true; + + call.Emit (ec, Setter, arguments, loc); + if (temp != null) { temp.Emit (ec); temp.Release (ec); + } else if (leave_copy) { + source.Emit (ec); + } + + if (await_source_arg != null) { + await_source_arg.Release (ec); } } @@ -8803,7 +8987,7 @@ namespace Mono.CSharp /// This is also now used as a placeholder where a no-action expression /// is needed (the `New' class). /// - class EmptyExpression : Expression + public class EmptyExpression : Expression { sealed class OutAccessExpression : EmptyExpression { @@ -8837,6 +9021,11 @@ namespace Mono.CSharp loc = Location.Null; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -8855,6 +9044,24 @@ namespace Mono.CSharp public override void EmitSideEffect (EmitContext ec) { } + + public override object Accept (StructuralVisitor visitor) + { + return visitor.Visit (this); + } + } + + sealed class EmptyAwaitExpression : EmptyExpression + { + public EmptyAwaitExpression (TypeSpec type) + : base (type) + { + } + + public override bool ContainsEmitWithAwait () + { + return true; + } } // @@ -8869,6 +9076,11 @@ namespace Mono.CSharp loc = Location.Null; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { return null; @@ -8939,6 +9151,11 @@ namespace Mono.CSharp } } + public override bool ContainsEmitWithAwait () + { + return source.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (3); @@ -9143,6 +9360,11 @@ namespace Mono.CSharp this.loc = l; } + public override bool ContainsEmitWithAwait () + { + throw new NotImplementedException (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Error_PointerInsideExpressionTree (ec); @@ -9246,6 +9468,11 @@ namespace Mono.CSharp loc = l; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -9522,6 +9749,12 @@ namespace Mono.CSharp } } + public IList Initializers { + get { + return initializers; + } + } + protected override void CloneTo (CloneContext clonectx, Expression target) { CollectionOrObjectInitializers t = (CollectionOrObjectInitializers) target; @@ -9531,6 +9764,16 @@ namespace Mono.CSharp t.initializers.Add (e.Clone (clonectx)); } + public override bool ContainsEmitWithAwait () + { + foreach (var e in initializers) { + if (e.ContainsEmitWithAwait ()) + return true; + } + + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { var expr_initializers = new ArrayInitializer (initializers.Count, loc); @@ -9641,6 +9884,11 @@ namespace Mono.CSharp this.new_instance = newInstance; } + public override bool ContainsEmitWithAwait () + { + return false; + } + public override Expression CreateExpressionTree (ResolveContext ec) { // Should not be reached @@ -9663,6 +9911,11 @@ namespace Mono.CSharp e.Emit (ec); } + public override Expression EmitToField (EmitContext ec) + { + return (Expression) new_instance.instance; + } + #region IMemoryLocation Members public void AddressOf (EmitContext ec, AddressOp mode) @@ -9676,22 +9929,18 @@ 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) { this.initializers = initializers; } - protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode) - { - instance = base.EmitAddressOf (ec, Mode); - - if (!initializers.IsEmpty) - initializers.Emit (ec); - - return instance; - } - protected override void CloneTo (CloneContext clonectx, Expression t) { base.CloneTo (clonectx, t); @@ -9700,6 +9949,11 @@ namespace Mono.CSharp target.initializers = (CollectionOrObjectInitializers) initializers.Clone (clonectx); } + public override bool ContainsEmitWithAwait () + { + return base.ContainsEmitWithAwait () || initializers.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { Arguments args = new Arguments (2); @@ -9732,11 +9986,14 @@ namespace Mono.CSharp if (initializers.IsEmpty) return left_on_stack; - LocalTemporary temp = target as LocalTemporary; - if (temp == null) { + LocalTemporary temp = null; + + instance = target as LocalTemporary; + + if (instance == null) { if (!left_on_stack) { VariableReference vr = target as VariableReference; - + // FIXME: This still does not work correctly for pre-set variables if (vr != null && vr.IsRef) target.AddressOf (ec, AddressOp.Load); @@ -9745,23 +10002,41 @@ namespace Mono.CSharp left_on_stack = true; } - temp = new LocalTemporary (type); + if (ec.HasSet (BuilderContext.Options.AsyncBody) && initializers.ContainsEmitWithAwait ()) { + instance = new EmptyAwaitExpression (Type).EmitToField (ec) as IMemoryLocation; + } else { + temp = new LocalTemporary (type); + instance = temp; + } } - instance = temp; - if (left_on_stack) + if (left_on_stack && temp != null) temp.Store (ec); initializers.Emit (ec); if (left_on_stack) { - temp.Emit (ec); - temp.Release (ec); + if (temp != null) { + temp.Emit (ec); + temp.Release (ec); + } else { + ((Expression) instance).Emit (ec); + } } return left_on_stack; } + protected override IMemoryLocation EmitAddressOf (EmitContext ec, AddressOp Mode) + { + instance = base.EmitAddressOf (ec, Mode); + + if (!initializers.IsEmpty) + initializers.Emit (ec); + + return instance; + } + public override object Accept (StructuralVisitor visitor) { return visitor.Visit (this); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/field.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/field.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/flowanalysis.cs similarity index 94% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/flowanalysis.cs index d864dc875..f54f6f179 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/flowanalysis.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/flowanalysis.cs @@ -7,6 +7,7 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc. // Copyright 2003-2008 Novell, Inc. +// Copyright 2011 Xamarin, Inc. // using System; @@ -250,7 +251,12 @@ namespace Mono.CSharp } public bool IsUnreachable { - get { return is_unreachable; } + get { + return is_unreachable; + } + set { + is_unreachable = value; + } } public void ResetBarrier () @@ -415,9 +421,9 @@ namespace Mono.CSharp return Parent.CheckRethrow (loc); } - public virtual bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + public virtual bool AddResumePoint (ResumableStatement stmt, out int pc) { - return Parent.AddResumePoint (stmt, loc, out pc); + return Parent.AddResumePoint (stmt, out pc); } // returns true if we crossed an unwind-protected region (try/catch/finally, lock, using, ...) @@ -636,15 +642,15 @@ namespace Mono.CSharp public class FlowBranchingIterator : FlowBranchingBlock { - readonly StateMachineInitializer iterator; + readonly Iterator iterator; - public FlowBranchingIterator (FlowBranching parent, StateMachineInitializer iterator) + public FlowBranchingIterator (FlowBranching parent, Iterator iterator) : base (parent, BranchingType.Iterator, SiblingType.Block, iterator.Block, iterator.Location) { this.iterator = iterator; } - public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + public override bool AddResumePoint (ResumableStatement stmt, out int pc) { pc = iterator.AddResumePoint (stmt); return false; @@ -666,7 +672,7 @@ namespace Mono.CSharp return false; } - public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + public override bool AddResumePoint (ResumableStatement stmt, out int pc) { throw new InternalErrorException ("A yield in a non-iterator block"); } @@ -730,11 +736,12 @@ namespace Mono.CSharp public class FlowBranchingTryCatch : FlowBranchingBlock { - TryCatch stmt; + readonly TryCatch tc; + public FlowBranchingTryCatch (FlowBranching parent, TryCatch stmt) : base (parent, BranchingType.Block, SiblingType.Try, null, stmt.loc) { - this.stmt = stmt; + this.tc = stmt; } public override bool CheckRethrow (Location loc) @@ -742,37 +749,46 @@ namespace Mono.CSharp return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc); } - public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + public override bool AddResumePoint (ResumableStatement stmt, out int pc) { int errors = Report.Errors; - Parent.AddResumePoint (stmt, loc, out pc); + Parent.AddResumePoint (tc.IsTryCatchFinally ? stmt : tc, out pc); if (errors == Report.Errors) { - if (CurrentUsageVector.Next == null) - Report.Error (1626, loc, "Cannot yield a value in the body of a try block with a catch clause"); - else - Report.Error (1631, loc, "Cannot yield a value in the body of a catch clause"); + if (stmt is AwaitStatement) { + if (CurrentUsageVector.Next != null) { + Report.Error (1985, stmt.loc, "The `await' operator cannot be used in the body of a catch clause"); + } else { + this.tc.AddResumePoint (stmt, pc); + } + } else { + if (CurrentUsageVector.Next == null) + Report.Error (1626, stmt.loc, "Cannot yield a value in the body of a try block with a catch clause"); + else + Report.Error (1631, stmt.loc, "Cannot yield a value in the body of a catch clause"); + } } + return true; } public override bool AddBreakOrigin (UsageVector vector, Location loc) { Parent.AddBreakOrigin (vector, loc); - stmt.SomeCodeFollows (); + tc.SomeCodeFollows (); return true; } public override bool AddContinueOrigin (UsageVector vector, Location loc) { Parent.AddContinueOrigin (vector, loc); - stmt.SomeCodeFollows (); + tc.SomeCodeFollows (); return true; } public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) { Parent.AddReturnOrigin (vector, exit_stmt); - stmt.SomeCodeFollows (); + tc.SomeCodeFollows (); return true; } @@ -783,7 +799,53 @@ namespace Mono.CSharp } } - public class FlowBranchingException : FlowBranching + public class FlowBranchingAsync : FlowBranchingBlock + { + readonly AsyncInitializer async_init; + + public FlowBranchingAsync (FlowBranching parent, AsyncInitializer async_init) + : base (parent, BranchingType.Block, SiblingType.Try, null, async_init.Location) + { + this.async_init = async_init; + } +/* + public override bool CheckRethrow (Location loc) + { + return CurrentUsageVector.Next != null || Parent.CheckRethrow (loc); + } +*/ + public override bool AddResumePoint (ResumableStatement stmt, out int pc) + { + pc = async_init.AddResumePoint (stmt); + return true; + } + + public override bool AddBreakOrigin (UsageVector vector, Location loc) + { + Parent.AddBreakOrigin (vector, loc); + return true; + } + + public override bool AddContinueOrigin (UsageVector vector, Location loc) + { + Parent.AddContinueOrigin (vector, loc); + return true; + } + + public override bool AddReturnOrigin (UsageVector vector, ExitStatement exit_stmt) + { + Parent.AddReturnOrigin (vector, exit_stmt); + return true; + } + + public override bool AddGotoOrigin (UsageVector vector, Goto goto_stmt) + { + Parent.AddGotoOrigin (vector, goto_stmt); + return true; + } + } + + public class FlowBranchingTryFinally : FlowBranching { ExceptionStatement stmt; UsageVector current_vector; @@ -869,7 +931,7 @@ namespace Mono.CSharp SavedOrigin saved_origins; - public FlowBranchingException (FlowBranching parent, + public FlowBranchingTryFinally (FlowBranching parent, ExceptionStatement stmt) : base (parent, BranchingType.Exception, SiblingType.Try, null, stmt.loc) @@ -906,15 +968,20 @@ namespace Mono.CSharp return false; } - public override bool AddResumePoint (ResumableStatement stmt, Location loc, out int pc) + public override bool AddResumePoint (ResumableStatement stmt, out int pc) { int errors = Report.Errors; - Parent.AddResumePoint (this.stmt, loc, out pc); + Parent.AddResumePoint (this.stmt, out pc); if (errors == Report.Errors) { if (finally_vector == null) this.stmt.AddResumePoint (stmt, pc); - else - Report.Error (1625, loc, "Cannot yield in the body of a finally clause"); + else { + if (stmt is AwaitStatement) { + Report.Error (1984, stmt.loc, "The `await' operator cannot be used in the body of a finally clause"); + } else { + Report.Error (1625, stmt.loc, "Cannot yield in the body of a finally clause"); + } + } } return true; } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/generic.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/generic.cs index 197570477..d955f868f 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/generic.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/generic.cs @@ -9,7 +9,9 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc (http://www.ximian.com) // Copyright 2004-2008 Novell, Inc +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // + using System; using System.Collections.Generic; using System.Text; @@ -723,8 +725,8 @@ namespace Mono.CSharp { } } - if (ifaces_defined == null && ifaces != null) - ifaces_defined = ifaces.ToArray (); + if (ifaces_defined == null) + ifaces_defined = ifaces == null ? TypeSpec.EmptyTypes : ifaces.ToArray (); state |= StateFlags.InterfacesExpanded; } @@ -738,13 +740,19 @@ namespace Mono.CSharp { // public TypeSpec[] InterfacesDefined { get { - if (ifaces_defined == null && ifaces != null) + if (ifaces_defined == null) { + if (ifaces == null) + return null; + ifaces_defined = ifaces.ToArray (); + } - return ifaces_defined; + return ifaces_defined.Length == 0 ? null : ifaces_defined; } set { - ifaces = ifaces_defined = value; + ifaces_defined = value; + if (value != null && value.Length != 0) + ifaces = value; } } @@ -974,10 +982,13 @@ namespace Mono.CSharp { // Check interfaces implementation -> definition if (InterfacesDefined != null) { - foreach (var iface in InterfacesDefined) { + // + // Iterate over inflated interfaces + // + foreach (var iface in Interfaces) { found = false; if (other.InterfacesDefined != null) { - foreach (var oiface in other.InterfacesDefined) { + foreach (var oiface in other.Interfaces) { if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { found = true; break; @@ -1007,9 +1018,12 @@ namespace Mono.CSharp { if (InterfacesDefined == null) return false; - foreach (var oiface in other.InterfacesDefined) { + // + // Iterate over inflated interfaces + // + foreach (var oiface in other.Interfaces) { found = false; - foreach (var iface in InterfacesDefined) { + foreach (var iface in Interfaces) { if (TypeSpecComparer.Override.IsEqual (iface, oiface)) { found = true; break; @@ -2789,7 +2803,7 @@ namespace Mono.CSharp { // Some types cannot be used as type arguments // if (bound.Type.Kind == MemberKind.Void || bound.Type.IsPointer || bound.Type.IsSpecialRuntimeType || - bound.Type == InternalType.MethodGroup) + bound.Type == InternalType.MethodGroup || bound.Type == InternalType.AnonymousMethod) return; var a = bounds [index]; diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj b/ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.csproj similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.csproj rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.csproj diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config b/ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.exe.config similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.exe.config index fe1df560a..4b560e2f7 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.config +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.exe.config @@ -1,14 +1,14 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources b/ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.exe.sources similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.exe.sources rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.exe.sources diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln b/ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.sln similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.sln rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.sln diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.userprefs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs.userprefs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs.userprefs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj b/ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs2.csproj similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/gmcs2.csproj rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/gmcs2.csproj diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/hosting.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/hosting.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/hosting.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/hosting.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/import.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/import.cs index 137c5ccb3..595a6193e 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/import.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/import.cs @@ -5,7 +5,8 @@ // // Dual licensed under the terms of the MIT X11 or GNU GPL // -// Copyright 2009, 2010 Novell, Inc +// Copyright 2009-2011 Novell, Inc +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // using System; @@ -962,6 +963,15 @@ namespace Mono.CSharp if (spec.BaseType != null) { var bifaces = spec.BaseType.Interfaces; if (bifaces != null) { + // + // Before adding base class interfaces close defined interfaces + // on type parameter + // + var tp = spec as TypeParameterSpec; + if (tp != null && tp.InterfacesDefined == null) { + tp.InterfacesDefined = TypeSpec.EmptyTypes; + } + foreach (var iface in bifaces) spec.AddInterface (iface); } @@ -1894,6 +1904,15 @@ namespace Mono.CSharp } } + // + // Load base interfaces first to minic behaviour of compiled members + // + if (declaringType.IsInterface && declaringType.Interfaces != null) { + foreach (var iface in declaringType.Interfaces) { + cache.AddInterface (iface); + } + } + if (!onlyTypes) { // // The logic here requires methods to be returned first which seems to work for both Mono and .NET @@ -2024,12 +2043,6 @@ namespace Mono.CSharp cache.AddMemberImported (imported); } } - - if (declaringType.IsInterface && declaringType.Interfaces != null) { - foreach (var iface in declaringType.Interfaces) { - cache.AddInterface (iface); - } - } } } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs similarity index 92% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs index 9a256de68..04e468db4 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/iterators.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/iterators.cs @@ -8,6 +8,7 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // Copyright 2003 Ximian, Inc. // Copyright 2003-2008 Novell, Inc. +// Copyright 2011 Xamarin Inc. // // TODO: @@ -28,7 +29,7 @@ namespace Mono.CSharp public abstract class YieldStatement : ResumableStatement where T : StateMachineInitializer { protected Expression expr; - bool unwind_protect; + protected bool unwind_protect; protected T machine_initializer; int resume_pc; @@ -62,7 +63,7 @@ namespace Mono.CSharp machine_initializer = bc.CurrentAnonymousMethod as T; if (!bc.CurrentBranching.CurrentUsageVector.IsUnreachable) - unwind_protect = bc.CurrentBranching.AddResumePoint (this, loc, out resume_pc); + unwind_protect = bc.CurrentBranching.AddResumePoint (this, out resume_pc); return true; } @@ -156,7 +157,6 @@ namespace Mono.CSharp Start = 0 } - Field disposing_field; Field pc_field; int local_name_idx; StateMachineMethod method; @@ -168,12 +168,6 @@ namespace Mono.CSharp #region Properties - public Field DisposingField { - get { - return disposing_field; - } - } - public StateMachineMethod StateMachineMethod { get { return method; @@ -200,14 +194,13 @@ namespace Mono.CSharp protected override bool DoDefineMembers () { pc_field = AddCompilerGeneratedField ("$PC", new TypeExpression (Compiler.BuiltinTypes.Int, Location)); - disposing_field = AddCompilerGeneratedField ("$disposing", new TypeExpression (Compiler.BuiltinTypes.Bool, Location)); return base.DoDefineMembers (); } protected override string GetVariableMangledName (LocalVariable local_info) { - return "<" + local_info.Name + ">__" + local_name_idx++.ToString (); + return "<" + local_info.Name + ">__" + local_name_idx++.ToString ("X"); } } @@ -280,7 +273,7 @@ namespace Mono.CSharp { Label label_init = ec.DefineLabel (); - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); ec.Emit (OpCodes.Ldflda, host.PC.Spec); ec.EmitInt ((int) State.Start); ec.EmitInt ((int) State.Uninitialized); @@ -292,7 +285,7 @@ namespace Mono.CSharp ec.EmitInt ((int) State.Uninitialized); ec.Emit (OpCodes.Bne_Un_S, label_init); - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); ec.Emit (OpCodes.Ret); ec.MarkLabel (label_init); @@ -396,6 +389,7 @@ namespace Mono.CSharp TypeExpr iterator_type_expr; Field current_field; + Field disposing_field; TypeExpr enumerator_type; TypeExpr enumerable_type; @@ -411,7 +405,15 @@ namespace Mono.CSharp } public Field CurrentField { - get { return current_field; } + get { + return current_field; + } + } + + public Field DisposingField { + get { + return disposing_field; + } } public IList HoistedParameters { @@ -457,6 +459,7 @@ namespace Mono.CSharp protected override bool DoDefineMembers () { current_field = AddCompilerGeneratedField ("$current", iterator_type_expr); + disposing_field = AddCompilerGeneratedField ("$disposing", new TypeExpression (Compiler.BuiltinTypes.Bool, Location)); if (hoisted_params != null) { // @@ -578,6 +581,10 @@ namespace Mono.CSharp { EmitContext ec = new EmitContext (this, ig, MemberType); ec.CurrentAnonymousMethod = expr; + + if (expr is AsyncInitializer) + ec.With (BuilderContext.Options.AsyncBody, true); + return ec; } } @@ -617,9 +624,11 @@ namespace Mono.CSharp // The state as we generate the machine // Label move_next_ok; + Label iterator_body_end; protected Label move_next_error; - protected LocalBuilder skip_finally, current_pc; - List resume_points; + LocalBuilder skip_finally; + protected LocalBuilder current_pc; + protected List resume_points; protected StateMachineInitializer (ParametersBlock block, TypeContainer host, TypeSpec returnType) : base (block, returnType, block.StartLocation) @@ -627,12 +636,35 @@ namespace Mono.CSharp this.Host = host; } + #region Properties + + public Label BodyEnd { + get { + return iterator_body_end; + } + } + + public LocalBuilder CurrentPC + { + get { + return current_pc; + } + } + + public LocalBuilder SkipFinally { + get { + return skip_finally; + } + } + public override AnonymousMethodStorey Storey { get { return storey; } } + #endregion + public int AddResumePoint (ResumableStatement stmt) { if (resume_points == null) @@ -660,7 +692,6 @@ namespace Mono.CSharp var ctx = CreateBlockContext (ec); - ctx.StartFlowBranching (this, ec.CurrentBranching); Block.Resolve (ctx); // @@ -690,70 +721,26 @@ namespace Mono.CSharp storey.Instance.Emit (ec); } - public void EmitDispose (EmitContext ec) - { - Label end = ec.DefineLabel (); - - Label[] labels = null; - int n_resume_points = resume_points == null ? 0 : resume_points.Count; - for (int i = 0; i < n_resume_points; ++i) { - ResumableStatement s = resume_points[i]; - Label ret = s.PrepareForDispose (ec, end); - if (ret.Equals (end) && labels == null) - continue; - if (labels == null) { - labels = new Label[resume_points.Count + 1]; - for (int j = 0; j <= i; ++j) - labels[j] = end; - } - - labels[i + 1] = ret; - } - - if (labels != null) { - current_pc = ec.GetTemporaryLocal (ec.BuiltinTypes.UInt); - ec.Emit (OpCodes.Ldarg_0); - ec.Emit (OpCodes.Ldfld, storey.PC.Spec); - ec.Emit (OpCodes.Stloc, current_pc); - } - - ec.Emit (OpCodes.Ldarg_0); - ec.EmitInt (1); - ec.Emit (OpCodes.Stfld, storey.DisposingField.Spec); - - ec.Emit (OpCodes.Ldarg_0); - ec.EmitInt ((int) IteratorStorey.State.After); - ec.Emit (OpCodes.Stfld, storey.PC.Spec); - - if (labels != null) { - //SymbolWriter.StartIteratorDispatcher (ec.ig); - ec.Emit (OpCodes.Ldloc, current_pc); - ec.Emit (OpCodes.Switch, labels); - //SymbolWriter.EndIteratorDispatcher (ec.ig); - - foreach (ResumableStatement s in resume_points) - s.EmitForDispose (ec, current_pc, end, true); - } - - ec.MarkLabel (end); - } - void EmitMoveNext_NoResumePoints (EmitContext ec, Block original_block) { - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); ec.Emit (OpCodes.Ldfld, storey.PC.Spec); - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); ec.EmitInt ((int) IteratorStorey.State.After); ec.Emit (OpCodes.Stfld, storey.PC.Spec); // We only care if the PC is zero (start executing) or non-zero (don't do anything) ec.Emit (OpCodes.Brtrue, move_next_error); + iterator_body_end = ec.DefineLabel (); + SymbolWriter.StartIteratorBody (ec); original_block.Emit (ec); SymbolWriter.EndIteratorBody (ec); + ec.MarkLabel (iterator_body_end); + EmitMoveNextEpilogue (ec); ec.MarkLabel (move_next_error); @@ -773,14 +760,14 @@ namespace Mono.CSharp EmitMoveNext_NoResumePoints (ec, block); return; } - + current_pc = ec.GetTemporaryLocal (ec.BuiltinTypes.UInt); - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); ec.Emit (OpCodes.Ldfld, storey.PC.Spec); ec.Emit (OpCodes.Stloc, current_pc); // We're actually in state 'running', but this is as good a PC value as any if there's an abnormal exit - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); ec.EmitInt ((int) IteratorStorey.State.After); ec.Emit (OpCodes.Stfld, storey.PC.Spec); @@ -796,33 +783,57 @@ namespace Mono.CSharp if (need_skip_finally) { skip_finally = ec.GetTemporaryLocal (ec.BuiltinTypes.Bool); - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.Emit (OpCodes.Stloc, skip_finally); } + var async_init = this as AsyncInitializer; + if (async_init != null) + ec.BeginExceptionBlock (); + SymbolWriter.StartIteratorDispatcher (ec); ec.Emit (OpCodes.Ldloc, current_pc); ec.Emit (OpCodes.Switch, labels); - ec.Emit (OpCodes.Br, move_next_error); + ec.Emit (async_init != null ? OpCodes.Leave : OpCodes.Br, move_next_error); SymbolWriter.EndIteratorDispatcher (ec); ec.MarkLabel (labels[0]); + iterator_body_end = ec.DefineLabel (); + SymbolWriter.StartIteratorBody (ec); block.Emit (ec); SymbolWriter.EndIteratorBody (ec); SymbolWriter.StartIteratorDispatcher (ec); - ec.Emit (OpCodes.Ldarg_0); + ec.MarkLabel (iterator_body_end); + + if (async_init != null) { + var catch_value = LocalVariable.CreateCompilerGenerated (ec.Module.Compiler.BuiltinTypes.Exception, block, Location); + + ec.BeginCatchBlock (catch_value.Type); + catch_value.EmitAssign (ec); + + ec.EmitThis (); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + ((AsyncTaskStorey) async_init.Storey).EmitSetException (ec, new LocalVariableReference (catch_value, Location)); + + ec.Emit (OpCodes.Leave, move_next_ok); + ec.EndExceptionBlock (); + } + + ec.EmitThis (); ec.EmitInt ((int) IteratorStorey.State.After); ec.Emit (OpCodes.Stfld, storey.PC.Spec); EmitMoveNextEpilogue (ec); ec.MarkLabel (move_next_error); - + if (ReturnType.Kind != MemberKind.Void) { ec.EmitInt (0); ec.Emit (OpCodes.Ret); @@ -842,6 +853,12 @@ namespace Mono.CSharp { } + public void EmitLeave (EmitContext ec, bool unwind_protect) + { + // Return ok + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); + } + // // Called back from YieldStatement // @@ -851,28 +868,29 @@ namespace Mono.CSharp // Guard against being disposed meantime // Label disposed = ec.DefineLabel (); - ec.Emit (OpCodes.Ldarg_0); - ec.Emit (OpCodes.Ldfld, storey.DisposingField.Spec); - ec.Emit (OpCodes.Brtrue_S, disposed); + var iterator = storey as IteratorStorey; + if (iterator != null) { + ec.EmitThis (); + ec.Emit (OpCodes.Ldfld, iterator.DisposingField.Spec); + ec.Emit (OpCodes.Brtrue_S, disposed); + } // // store resume program-counter // - ec.Emit (OpCodes.Ldarg_0); + ec.EmitThis (); ec.EmitInt (resume_pc); ec.Emit (OpCodes.Stfld, storey.PC.Spec); - ec.MarkLabel (disposed); + + if (iterator != null) { + ec.MarkLabel (disposed); + } // mark finally blocks as disabled if (unwind_protect && skip_finally != null) { ec.EmitInt (1); ec.Emit (OpCodes.Stloc, skip_finally); } - - // Return ok - ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, move_next_ok); - - ec.MarkLabel (resume_point); } } @@ -894,14 +912,6 @@ namespace Mono.CSharp this.type = method.ReturnType; } - public LocalBuilder SkipFinally { - get { return skip_finally; } - } - - public LocalBuilder CurrentPC { - get { return current_pc; } - } - public Block Container { get { return OriginalMethod.Block; } } @@ -951,6 +961,54 @@ namespace Mono.CSharp } } + public void EmitDispose (EmitContext ec) + { + Label end = ec.DefineLabel (); + + Label[] labels = null; + int n_resume_points = resume_points == null ? 0 : resume_points.Count; + for (int i = 0; i < n_resume_points; ++i) { + ResumableStatement s = resume_points[i]; + Label ret = s.PrepareForDispose (ec, end); + if (ret.Equals (end) && labels == null) + continue; + if (labels == null) { + labels = new Label[resume_points.Count + 1]; + for (int j = 0; j <= i; ++j) + labels[j] = end; + } + + labels[i + 1] = ret; + } + + if (labels != null) { + current_pc = ec.GetTemporaryLocal (ec.BuiltinTypes.UInt); + ec.EmitThis (); + ec.Emit (OpCodes.Ldfld, storey.PC.Spec); + ec.Emit (OpCodes.Stloc, current_pc); + } + + ec.EmitThis (); + ec.EmitInt (1); + ec.Emit (OpCodes.Stfld, ((IteratorStorey) storey).DisposingField.Spec); + + ec.EmitThis (); + ec.EmitInt ((int) IteratorStorey.State.After); + ec.Emit (OpCodes.Stfld, storey.PC.Spec); + + if (labels != null) { + //SymbolWriter.StartIteratorDispatcher (ec.ig); + ec.Emit (OpCodes.Ldloc, current_pc); + ec.Emit (OpCodes.Switch, labels); + //SymbolWriter.EndIteratorDispatcher (ec.ig); + + foreach (ResumableStatement s in resume_points) + s.EmitForDispose (ec, current_pc, end, true); + } + + ec.MarkLabel (end); + } + public override void EmitStatement (EmitContext ec) { throw new NotImplementedException (); @@ -964,6 +1022,17 @@ namespace Mono.CSharp fe.EmitAssign (ec, expr, false, false); base.InjectYield (ec, expr, resume_pc, unwind_protect, resume_point); + + EmitLeave (ec, unwind_protect); + + ec.MarkLabel (resume_point); + } + + protected override BlockContext CreateBlockContext (ResolveContext rc) + { + var bc = base.CreateBlockContext (rc); + bc.StartFlowBranching (this, rc.CurrentBranching); + return bc; } public static void CreateIterator (IMethodData method, TypeContainer parent, Modifiers modifiers) diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs index 3cad50ce4..16f96a33d 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.cs @@ -199,7 +199,11 @@ namespace Mono.CSharp { { if (statement != null) { statement.EmitStatement (ec); - ec.Emit (OpCodes.Ret); + if (unwind_protect) + ec.Emit (OpCodes.Leave, ec.CreateReturnLabel ()); + else { + ec.Emit (OpCodes.Ret); + } return; } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo b/ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.todo similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/lambda.todo rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/lambda.todo diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/linq.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/linq.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/literal.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/literal.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/literal.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/location.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/location.cs index fd3fe3aaa..04907b346 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/location.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/location.cs @@ -516,7 +516,9 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" public readonly Tokenizer.PreprocessorDirective Cmd; public readonly string Arg; - + + public bool Take = true; + public PreProcessorDirective (int line, int col, int endLine, int endCol, Tokenizer.PreprocessorDirective cmd, string arg) { this.Line = line; @@ -574,6 +576,15 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" { Specials.Add (new PreProcessorDirective (startLine, startCol, endLine, endColumn, cmd, arg)); } + + public void SkipIf () + { + if (Specials.Count > 0) { + var directive = Specials[Specials.Count - 1] as PreProcessorDirective; + if (directive != null) + directive.Take = false; + } + } } // @@ -897,6 +908,12 @@ if (checkpoints.Length <= CheckpointIndex) throw new Exception (String.Format (" curNamespace.Pop (); } + [Conditional ("FULL_AST")] + public void EndNamespace () + { + curNamespace.Pop (); + } + [Conditional ("FULL_AST")] public void OpenNamespace (Location bracketLocation) { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/membercache.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/membercache.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/membercache.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs similarity index 96% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs index 75998515a..c69c1d766 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/method.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/method.cs @@ -613,7 +613,7 @@ namespace Mono.CSharp { MethodData = new MethodData ( this, ModFlags, flags, this, MethodBuilder, GenericMethod, base_method); - if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName), Report)) + if (!MethodData.Define (Parent.PartialContainer, GetFullName (MemberName))) return false; MethodBuilder = MethodData.MethodBuilder; @@ -1151,7 +1151,7 @@ namespace Mono.CSharp { } if ((ModFlags & Modifiers.ASYNC) != 0) { - AsyncInitializer.Create (block, parameters, Parent.PartialContainer, ReturnType, Location); + AsyncInitializer.Create (this, block, parameters, Parent.PartialContainer, ReturnType, Location); } } @@ -1316,6 +1316,11 @@ namespace Mono.CSharp { } } + public override bool ContainsEmitWithAwait () + { + throw new NotSupportedException (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException ("ET"); @@ -1386,7 +1391,9 @@ namespace Mono.CSharp { ec.Mark (loc); - Invocation.EmitCall (ec, new CompilerGeneratedThis (type, loc), base_ctor, argument_list, loc); + var call = new CallEmitter (); + call.InstanceExpression = new CompilerGeneratedThis (type, loc); + call.EmitPredefined (ec, base_ctor, argument_list); } public override void EmitStatement (EmitContext ec) @@ -1633,11 +1640,6 @@ namespace Mono.CSharp { EmitContext ec = new EmitContext (this, ConstructorBuilder.GetILGenerator (), bc.ReturnType); ec.With (EmitContext.Options.ConstructorScope, true); - if (!ec.HasReturnLabel && bc.HasReturnLabel) { - ec.ReturnLabel = bc.ReturnLabel; - ec.HasReturnLabel = true; - } - block.Emit (ec); } } @@ -1817,32 +1819,34 @@ namespace Mono.CSharp { this.parent_method = parent_method; } - public bool Define (DeclSpace parent, string method_full_name, Report Report) + public bool Define (TypeContainer container, string method_full_name) { - TypeContainer container = parent.PartialContainer; - PendingImplementation pending = container.PendingImplementations; MethodSpec ambig_iface_method; + bool optional = false; + if (pending != null) { - implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method); + implementing = pending.IsInterfaceMethod (method.MethodName, member.InterfaceType, this, out ambig_iface_method, ref optional); if (member.InterfaceType != null) { if (implementing == null) { if (member is PropertyBase) { - Report.Error (550, method.Location, "`{0}' is an accessor not found in interface member `{1}{2}'", + container.Compiler.Report.Error (550, method.Location, + "`{0}' is an accessor not found in interface member `{1}{2}'", method.GetSignatureForError (), TypeManager.CSharpName (member.InterfaceType), member.GetSignatureForError ().Substring (member.GetSignatureForError ().LastIndexOf ('.'))); } else { - Report.Error (539, method.Location, + container.Compiler.Report.Error (539, method.Location, "`{0}.{1}' in explicit interface declaration is not a member of interface", TypeManager.CSharpName (member.InterfaceType), member.ShortName); } return false; } if (implementing.IsAccessor && !method.IsAccessor) { - Report.SymbolRelatedToPreviousError (implementing); - Report.Error (683, method.Location, "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor", + container.Compiler.Report.SymbolRelatedToPreviousError (implementing); + container.Compiler.Report.Error (683, method.Location, + "`{0}' explicit method implementation cannot implement `{1}' because it is an accessor", member.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); return false; } @@ -1850,20 +1854,23 @@ namespace Mono.CSharp { if (implementing != null) { if (!method.IsAccessor) { if (implementing.IsAccessor) { - Report.SymbolRelatedToPreviousError (implementing); - Report.Error (470, method.Location, "Method `{0}' cannot implement interface accessor `{1}'", + container.Compiler.Report.SymbolRelatedToPreviousError (implementing); + container.Compiler.Report.Error (470, method.Location, + "Method `{0}' cannot implement interface accessor `{1}'", method.GetSignatureForError (), TypeManager.CSharpSignature (implementing)); } } else if (implementing.DeclaringType.IsInterface) { if (!implementing.IsAccessor) { - Report.SymbolRelatedToPreviousError (implementing); - Report.Error (686, method.Location, "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation", + container.Compiler.Report.SymbolRelatedToPreviousError (implementing); + container.Compiler.Report.Error (686, method.Location, + "Accessor `{0}' cannot implement interface member `{1}' for type `{2}'. Use an explicit interface implementation", method.GetSignatureForError (), TypeManager.CSharpSignature (implementing), container.GetSignatureForError ()); } else { PropertyBase.PropertyMethod pm = method as PropertyBase.PropertyMethod; if (pm != null && pm.HasCustomAccessModifier && (pm.ModFlags & Modifiers.PUBLIC) == 0) { - Report.SymbolRelatedToPreviousError (implementing); - Report.Error (277, method.Location, "Accessor `{0}' must be declared public to implement interface member `{1}'", + container.Compiler.Report.SymbolRelatedToPreviousError (implementing); + container.Compiler.Report.Error (277, method.Location, + "Accessor `{0}' must be declared public to implement interface member `{1}'", method.GetSignatureForError (), implementing.GetSignatureForError ()); } } @@ -1879,43 +1886,44 @@ namespace Mono.CSharp { // explicit implementations, make sure we are private. // if (implementing != null){ - // - // Setting null inside this block will trigger a more - // verbose error reporting for missing interface implementations - // - // The "candidate" function has been flagged already - // but it wont get cleared - // - if (member.IsExplicitImpl){ + if (member.IsExplicitImpl) { if (method.ParameterInfo.HasParams && !implementing.Parameters.HasParams) { - Report.SymbolRelatedToPreviousError (implementing); - Report.Error (466, method.Location, "`{0}': the explicit interface implementation cannot introduce the params modifier", + container.Compiler.Report.SymbolRelatedToPreviousError (implementing); + container.Compiler.Report.Error (466, method.Location, + "`{0}': the explicit interface implementation cannot introduce the params modifier", method.GetSignatureForError ()); } if (ambig_iface_method != null) { - Report.SymbolRelatedToPreviousError (ambig_iface_method); - Report.SymbolRelatedToPreviousError (implementing); - Report.Warning (473, 2, method.Location, + container.Compiler.Report.SymbolRelatedToPreviousError (ambig_iface_method); + container.Compiler.Report.SymbolRelatedToPreviousError (implementing); + container.Compiler.Report.Warning (473, 2, method.Location, "Explicit interface implementation `{0}' matches more than one interface member. Consider using a non-explicit implementation instead", method.GetSignatureForError ()); } - } else { + // + // Setting implementin to null inside this block will trigger a more + // verbose error reporting for missing interface implementations + // if (implementing.DeclaringType.IsInterface) { // // If this is an interface method implementation, // check for public accessibility // - if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) - { + if ((flags & MethodAttributes.MemberAccessMask) != MethodAttributes.Public) { + implementing = null; + } else if (optional && (container.Interfaces == null || Array.IndexOf (container.Interfaces, implementing.DeclaringType) < 0)) { + // + // We are not implementing interface when base class already implemented it + // implementing = null; } - } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private){ + } else if ((flags & MethodAttributes.MemberAccessMask) == MethodAttributes.Private) { // We may never be private. implementing = null; - } else if ((modifiers & Modifiers.OVERRIDE) == 0){ + } else if ((modifiers & Modifiers.OVERRIDE) == 0) { // // We may be protected if we're overriding something. // @@ -1939,9 +1947,8 @@ namespace Mono.CSharp { // When implementing interface methods, set NewSlot // unless, we are overwriting a method. // - if (implementing.DeclaringType.IsInterface){ - if ((modifiers & Modifiers.OVERRIDE) == 0) - flags |= MethodAttributes.NewSlot; + if ((modifiers & Modifiers.OVERRIDE) == 0 && implementing.DeclaringType.IsInterface) { + flags |= MethodAttributes.NewSlot; } flags |= MethodAttributes.Virtual | MethodAttributes.HideBySig; @@ -1953,8 +1960,8 @@ namespace Mono.CSharp { // // clear the pending implementation flag (requires explicit methods to be defined first) // - parent.PartialContainer.PendingImplementations.ImplementMethod (method.MethodName, - member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method); + pending.ImplementMethod (method.MethodName, + member.InterfaceType, this, member.IsExplicitImpl, out ambig_iface_method, ref optional); // // Update indexer accessor name to match implementing abstract accessor @@ -2036,10 +2043,6 @@ namespace Mono.CSharp { BlockContext bc = new BlockContext (mc, block, method.ReturnType); if (block.Resolve (null, bc, method)) { EmitContext ec = method.CreateEmitContext (MethodBuilder.GetILGenerator ()); - if (!ec.HasReturnLabel && bc.HasReturnLabel) { - ec.ReturnLabel = bc.ReturnLabel; - ec.HasReturnLabel = true; - } block.Emit (ec); } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/modifiers.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/modifiers.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/modifiers.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs index fdafbee39..bd55dce6c 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/namespace.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/namespace.cs @@ -370,9 +370,9 @@ namespace Mono.CSharp { return res; } - /// - /// Looks for extension method in this namespace - /// + // + // Looks for extension method in this namespace + // public List LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity) { if (types == null) @@ -402,6 +402,26 @@ namespace Mono.CSharp { return found; } + // + // Extension methods look up for dotted namespace names + // + public IList LookupExtensionMethod (IMemberContext invocationContext, TypeSpec extensionType, string name, int arity, out Namespace scope) + { + // + // Inspect parent namespaces in namespace expression + // + scope = this; + do { + var candidates = scope.LookupExtensionMethod (invocationContext, extensionType, name, arity); + if (candidates != null) + return candidates; + + scope = scope.Parent; + } while (scope != null); + + return null; + } + public void AddType (ModuleContainer module, TypeSpec ts) { if (types == null) { @@ -797,7 +817,7 @@ namespace Mono.CSharp { // Does extension methods look up to find a method which matches name and extensionType. // Search starts from this namespace and continues hierarchically up to top level. // - public IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) { List candidates = null; foreach (Namespace n in GetUsingTable ()) { @@ -811,29 +831,21 @@ namespace Mono.CSharp { candidates.AddRange (a); } - scope = parent; if (candidates != null) - return candidates; + return new ExtensionMethodCandidates (candidates, this); if (parent == null) return null; - // - // Inspect parent namespaces in namespace expression - // - Namespace parent_ns = ns.Parent; - do { - candidates = parent_ns.LookupExtensionMethod (this, extensionType, name, arity); - if (candidates != null) - return candidates; - - parent_ns = parent_ns.Parent; - } while (parent_ns != null); + Namespace ns_scope; + var ns_candidates = ns.Parent.LookupExtensionMethod (this, extensionType, name, arity, out ns_scope); + if (ns_candidates != null) + return new ExtensionMethodCandidates (ns_candidates, this, ns_scope); // - // Continue in parent scope + // Continue in parent container // - return parent.LookupExtensionMethod (extensionType, name, arity, ref scope); + return parent.LookupExtensionMethod (extensionType, name, arity); } public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs similarity index 91% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs index f6b9abcca..28cf683e4 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/nullable.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/nullable.cs @@ -79,7 +79,7 @@ namespace Mono.CSharp.Nullable } } - public class Unwrap : Expression, IMemoryLocation, IAssignMethod + public class Unwrap : Expression, IMemoryLocation { Expression expr; @@ -96,6 +96,11 @@ namespace Mono.CSharp.Nullable eclass = expr.eclass; } + public override bool ContainsEmitWithAwait () + { + return expr.ContainsEmitWithAwait (); + } + public static Expression Create (Expression expr) { // @@ -132,16 +137,24 @@ namespace Mono.CSharp.Nullable public override void Emit (EmitContext ec) { Store (ec); + + var call = new CallEmitter (); + call.InstanceExpression = this; + if (useDefaultValue) - Invocation.EmitCall (ec, this, NullableInfo.GetGetValueOrDefault (expr.Type), null, loc); + call.EmitPredefined (ec, NullableInfo.GetGetValueOrDefault (expr.Type), null); else - Invocation.EmitCall (ec, this, NullableInfo.GetValue (expr.Type), null, loc); + call.EmitPredefined (ec, NullableInfo.GetValue (expr.Type), null); } public void EmitCheck (EmitContext ec) { Store (ec); - Invocation.EmitCall (ec, this, NullableInfo.GetHasValue (expr.Type), null, loc); + + var call = new CallEmitter (); + call.InstanceExpression = this; + + call.EmitPredefined (ec, NullableInfo.GetHasValue (expr.Type), null); } public override bool Equals (object obj) @@ -169,10 +182,10 @@ namespace Mono.CSharp.Nullable void Store (EmitContext ec) { - if (expr is VariableReference) + if (temp != null) return; - if (temp != null) + if (expr is VariableReference) return; expr.Emit (ec); @@ -211,51 +224,6 @@ namespace Mono.CSharp.Nullable return temp; } } - - public void Emit (EmitContext ec, bool leave_copy) - { - if (leave_copy) - Load (ec); - - Emit (ec); - } - - public void EmitAssign (EmitContext ec, Expression source, - bool leave_copy, bool prepare_for_load) - { - InternalWrap wrap = new InternalWrap (source, expr.Type, loc); - ((IAssignMethod) expr).EmitAssign (ec, wrap, leave_copy, false); - } - - class InternalWrap : Expression - { - public Expression expr; - - public InternalWrap (Expression expr, TypeSpec type, Location loc) - { - this.expr = expr; - this.loc = loc; - this.type = type; - - eclass = ExprClass.Value; - } - - public override Expression CreateExpressionTree (ResolveContext ec) - { - throw new NotSupportedException ("ET"); - } - - protected override Expression DoResolve (ResolveContext ec) - { - return this; - } - - public override void Emit (EmitContext ec) - { - expr.Emit (ec); - ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); - } - } } // @@ -280,7 +248,9 @@ namespace Mono.CSharp.Nullable public override void Emit (EmitContext ec) { - Invocation.EmitCall (ec, Child, NullableInfo.GetValue (Child.Type), null, loc); + var call = new CallEmitter (); + call.InstanceExpression = Child; + call.EmitPredefined (ec, NullableInfo.GetValue (Child.Type), null); } } @@ -354,6 +324,7 @@ namespace Mono.CSharp.Nullable value_target.AddressOf (ec, AddressOp.Store); ec.Emit (OpCodes.Initobj, type); value_target.Emit (ec); + value_target.Release (ec); } public void AddressOf (EmitContext ec, AddressOp Mode) @@ -386,6 +357,11 @@ namespace Mono.CSharp.Nullable : this (expr, unwrap as Unwrap, type) { } + + public override bool ContainsEmitWithAwait () + { + return unwrap.ContainsEmitWithAwait (); + } public override Expression CreateExpressionTree (ResolveContext ec) { @@ -677,7 +653,7 @@ namespace Mono.CSharp.Nullable } left_unwrap.Emit (ec); - ec.Emit (OpCodes.Brtrue_S, load_right); + ec.Emit (OpCodes.Brtrue, load_right); // value & null, value | null if (right_unwrap != null) { @@ -733,7 +709,7 @@ namespace Mono.CSharp.Nullable if (left_unwrap != null && (IsRightNullLifted || right.IsNull)) { left_unwrap.EmitCheck (ec); if (Oper == Binary.Operator.Equality) { - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.Emit (OpCodes.Ceq); } return; @@ -742,7 +718,7 @@ namespace Mono.CSharp.Nullable if (right_unwrap != null && (IsLeftNullLifted || left.IsNull)) { right_unwrap.EmitCheck (ec); if (Oper == Binary.Operator.Equality) { - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.Emit (OpCodes.Ceq); } return; @@ -755,6 +731,11 @@ namespace Mono.CSharp.Nullable user_operator.Emit (ec); ec.Emit (Oper == Operator.Equality ? OpCodes.Brfalse_S : OpCodes.Brtrue_S, dissimilar_label); } else { + if (ec.HasSet (BuilderContext.Options.AsyncBody) && right.ContainsEmitWithAwait ()) { + left = left.EmitToField (ec); + right = right.EmitToField (ec); + } + left.Emit (ec); right.Emit (ec); @@ -774,7 +755,7 @@ namespace Mono.CSharp.Nullable ec.Emit (OpCodes.Ceq); } else { if (Oper == Operator.Inequality) { - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.Emit (OpCodes.Ceq); } } @@ -783,9 +764,9 @@ namespace Mono.CSharp.Nullable ec.MarkLabel (dissimilar_label); if (Oper == Operator.Inequality) - ec.Emit (OpCodes.Ldc_I4_1); + ec.EmitInt (1); else - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.MarkLabel (end_label); } @@ -839,7 +820,7 @@ namespace Mono.CSharp.Nullable ec.MarkLabel (is_null_label); if ((Oper & Operator.ComparisonMask) != 0) { - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); } else { LiftedNull.Create (type, loc).Emit (ec); } @@ -854,8 +835,14 @@ namespace Mono.CSharp.Nullable return; } - if (l.IsNullableType) - l = TypeManager.GetTypeArguments (l) [0]; + if (left.Type.IsNullableType) { + l = NullableInfo.GetUnderlyingType (left.Type); + left = EmptyCast.Create (left, l); + } + + if (right.Type.IsNullableType) { + right = EmptyCast.Create (right, NullableInfo.GetUnderlyingType (right.Type)); + } base.EmitOperator (ec, l); } @@ -1149,6 +1136,14 @@ namespace Mono.CSharp.Nullable return this; } + public override bool ContainsEmitWithAwait () + { + if (unwrap != null) + return unwrap.ContainsEmitWithAwait () || right.ContainsEmitWithAwait (); + + return left.ContainsEmitWithAwait () || right.ContainsEmitWithAwait (); + } + protected override Expression DoResolve (ResolveContext ec) { left = left.Resolve (ec); @@ -1217,75 +1212,58 @@ namespace Mono.CSharp.Nullable } } - public class LiftedUnaryMutator : ExpressionStatement + class LiftedUnaryMutator : UnaryMutator { - public readonly UnaryMutator.Mode Mode; - Expression expr; - UnaryMutator underlying; - Unwrap unwrap; - - public LiftedUnaryMutator (UnaryMutator.Mode mode, Expression expr, Location loc) + public LiftedUnaryMutator (Mode mode, Expression expr, Location loc) + : base (mode, expr, loc) { - this.expr = expr; - this.Mode = mode; - this.loc = loc; - } - - public override Expression CreateExpressionTree (ResolveContext ec) - { - return new SimpleAssign (this, this).CreateExpressionTree (ec); } protected override Expression DoResolve (ResolveContext ec) { - expr = expr.Resolve (ec); - if (expr == null) - return null; - - unwrap = Unwrap.Create (expr, false); - if (unwrap == null) - return null; + var orig_expr = expr; - underlying = (UnaryMutator) new UnaryMutator (Mode, unwrap, loc).Resolve (ec); - if (underlying == null) - return null; + expr = Unwrap.Create (expr); + var res = base.DoResolveOperation (ec); - eclass = ExprClass.Value; + expr = orig_expr; type = expr.Type; - return this; + + return res; } - void DoEmit (EmitContext ec, bool is_expr) + protected override void EmitOperation (EmitContext ec) { Label is_null_label = ec.DefineLabel (); Label end_label = ec.DefineLabel (); - unwrap.EmitCheck (ec); + LocalTemporary lt = new LocalTemporary (type); + + // Value is on the stack + lt.Store (ec); + + var call = new CallEmitter (); + call.InstanceExpression = lt; + call.EmitPredefined (ec, NullableInfo.GetHasValue (expr.Type), null); + ec.Emit (OpCodes.Brfalse, is_null_label); - if (is_expr) { - underlying.Emit (ec); - ec.Emit (OpCodes.Br_S, end_label); - } else { - underlying.EmitStatement (ec); - } + call = new CallEmitter (); + call.InstanceExpression = lt; + call.EmitPredefined (ec, NullableInfo.GetValue (expr.Type), null); - ec.MarkLabel (is_null_label); - if (is_expr) - LiftedNull.Create (type, loc).Emit (ec); + lt.Release (ec); - ec.MarkLabel (end_label); - } + base.EmitOperation (ec); - public override void Emit (EmitContext ec) - { - DoEmit (ec, true); - } + ec.Emit (OpCodes.Newobj, NullableInfo.GetConstructor (type)); + ec.Emit (OpCodes.Br_S, end_label); - public override void EmitStatement (EmitContext ec) - { - DoEmit (ec, false); + ec.MarkLabel (is_null_label); + LiftedNull.Create (type, loc).Emit (ec); + + ec.MarkLabel (end_label); } } } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/outline.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/outline.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/outline.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs index c36699f93..e9b9042cf 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/parameter.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/parameter.cs @@ -616,40 +616,20 @@ namespace Mono.CSharp { public void Emit (EmitContext ec) { - int arg_idx = idx; - if (!ec.IsStatic) - arg_idx++; - - ParameterReference.EmitLdArg (ec, arg_idx); + ec.EmitArgumentLoad (idx); } public void EmitAssign (EmitContext ec) { - int arg_idx = idx; - if (!ec.IsStatic) - arg_idx++; - - if (arg_idx <= 255) - ec.Emit (OpCodes.Starg_S, (byte) arg_idx); - else - ec.Emit (OpCodes.Starg, arg_idx); + ec.EmitArgumentStore (idx); } public void EmitAddressOf (EmitContext ec) { - int arg_idx = idx; - - if (!ec.IsStatic) - arg_idx++; - - bool is_ref = (ModFlags & Modifier.ISBYREF) != 0; - if (is_ref) { - ParameterReference.EmitLdArg (ec, arg_idx); + if ((ModFlags & Modifier.ISBYREF) != 0) { + ec.EmitArgumentLoad (idx); } else { - if (arg_idx <= 255) - ec.Emit (OpCodes.Ldarga_S, (byte) arg_idx); - else - ec.Emit (OpCodes.Ldarga, arg_idx); + ec.EmitArgumentAddress (idx); } } @@ -1298,7 +1278,7 @@ namespace Mono.CSharp { type.GetSignatureForError (), parameter_type.GetSignatureForError ()); } - public virtual object Accept (StructuralVisitor visitor) + public override object Accept (StructuralVisitor visitor) { return visitor.Visit (this); } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs similarity index 92% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs index 696797aa0..0852b0f82 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/pending.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/pending.cs @@ -51,6 +51,78 @@ namespace Mono.CSharp { public MethodSpec [] need_proxy; } + struct ProxyMethodContext : IMemberContext + { + readonly TypeContainer container; + + public ProxyMethodContext (TypeContainer container) + { + this.container = container; + } + + public TypeSpec CurrentType { + get { + throw new NotImplementedException (); + } + } + + public TypeParameter[] CurrentTypeParameters { + get { + throw new NotImplementedException (); + } + } + + public MemberCore CurrentMemberDefinition { + get { + throw new NotImplementedException (); + } + } + + public bool IsObsolete { + get { + return false; + } + } + + public bool IsUnsafe { + get { + throw new NotImplementedException (); + } + } + + public bool IsStatic { + get { + return false; + } + } + + public ModuleContainer Module { + get { + return container.Module; + } + } + + public string GetSignatureForError () + { + throw new NotImplementedException (); + } + + public ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) + { + throw new NotImplementedException (); + } + + public FullNamedExpression LookupNamespaceOrType (string name, int arity, LookupMode mode, Location loc) + { + throw new NotImplementedException (); + } + + public FullNamedExpression LookupNamespaceAlias (string name) + { + throw new NotImplementedException (); + } + } + public class PendingImplementation { /// @@ -273,14 +345,14 @@ namespace Mono.CSharp { /// /// Whether the specified method is an interface method implementation /// - public MethodSpec IsInterfaceMethod (MemberName name, TypeSpec ifaceType, MethodData method, out MethodSpec ambiguousCandidate) + public MethodSpec IsInterfaceMethod (MemberName name, TypeSpec ifaceType, MethodData method, out MethodSpec ambiguousCandidate, ref bool optional) { - return InterfaceMethod (name, ifaceType, method, Operation.Lookup, out ambiguousCandidate); + return InterfaceMethod (name, ifaceType, method, Operation.Lookup, out ambiguousCandidate, ref optional); } - public void ImplementMethod (MemberName name, TypeSpec ifaceType, MethodData method, bool clear_one, out MethodSpec ambiguousCandidate) + public void ImplementMethod (MemberName name, TypeSpec ifaceType, MethodData method, bool clear_one, out MethodSpec ambiguousCandidate, ref bool optional) { - InterfaceMethod (name, ifaceType, method, clear_one ? Operation.ClearOne : Operation.ClearAll, out ambiguousCandidate); + InterfaceMethod (name, ifaceType, method, clear_one ? Operation.ClearOne : Operation.ClearAll, out ambiguousCandidate, ref optional); } /// @@ -300,7 +372,7 @@ namespace Mono.CSharp { /// that was used in the interface, then we always need to create a proxy for it. /// /// - public MethodSpec InterfaceMethod (MemberName name, TypeSpec iType, MethodData method, Operation op, out MethodSpec ambiguousCandidate) + public MethodSpec InterfaceMethod (MemberName name, TypeSpec iType, MethodData method, Operation op, out MethodSpec ambiguousCandidate, ref bool optional) { ambiguousCandidate = null; @@ -367,6 +439,7 @@ namespace Mono.CSharp { } } else { tm.found [i] = method; + optional = tm.optional; } if (op == Operation.Lookup && name.Left != null && ambiguousCandidate == null) { @@ -434,10 +507,11 @@ namespace Mono.CSharp { } int top = param.Count; - var ec = new EmitContext (null, proxy.GetILGenerator (), null); + var ec = new EmitContext (new ProxyMethodContext (container), proxy.GetILGenerator (), null); + ec.EmitThis (); // TODO: GetAllParametersArguments - for (int i = 0; i <= top; i++) - ParameterReference.EmitLdArg (ec, i); + for (int i = 0; i < top; i++) + ec.EmitArgumentLoad (i); ec.Emit (OpCodes.Call, base_method); ec.Emit (OpCodes.Ret); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/property.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/property.cs index d5adfccad..db013e307 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/property.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/property.cs @@ -205,7 +205,7 @@ namespace Mono.CSharp method_data = new MethodData (method, ModFlags, flags, this); - if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName))) return null; Spec.SetMetaInfo (method_data.MethodBuilder); @@ -272,7 +272,7 @@ namespace Mono.CSharp method_data = new MethodData (method, ModFlags, flags, this); - if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName))) return null; Spec.SetMetaInfo (method_data.MethodBuilder); @@ -1165,7 +1165,7 @@ namespace Mono.CSharp method_data = new MethodData (method, method.ModFlags, method.flags | MethodAttributes.HideBySig | MethodAttributes.SpecialName, this); - if (!method_data.Define (parent, method.GetFullName (MemberName), Report)) + if (!method_data.Define (parent.PartialContainer, method.GetFullName (MemberName))) return null; MethodBuilder mb = method_data.MethodBuilder; diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/reflection.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/reflection.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/reflection.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt b/ICSharpCode.NRefactory.CSharp/Parser/mcs/repl.txt similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/repl.txt rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/repl.txt diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs index e34e6951f..d785dad62 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/report.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/report.cs @@ -2,9 +2,10 @@ // report.cs: report errors and warnings. // // Author: Miguel de Icaza (miguel@ximian.com) -// Marek Safar (marek.safar@seznam.cz) +// Marek Safar (marek.safar@gmail.com) // // Copyright 2001 Ximian, Inc. (http://www.ximian.com) +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // using System; @@ -62,7 +63,7 @@ namespace Mono.CSharp { 1522, 1570, 1571, 1572, 1573, 1574, 1580, 1581, 1584, 1587, 1589, 1590, 1591, 1592, 1607, 1616, 1633, 1634, 1635, 1685, 1690, 1691, 1692, 1695, 1696, 1699, 1700, 1701, 1702, 1709, 1711, 1717, 1718, 1720, 1735, - 1901, 1956, 1981, + 1901, 1956, 1981, 1998, 2002, 2023, 2029, 3000, 3001, 3002, 3003, 3005, 3006, 3007, 3008, 3009, 3010, 3011, 3012, 3013, 3014, 3015, 3016, 3017, 3018, 3019, @@ -103,6 +104,9 @@ namespace Mono.CSharp { case LanguageVersion.V_3: version = "3.0"; break; + case LanguageVersion.V_4: + version = "4.0"; + break; default: throw new InternalErrorException ("Invalid feature version", compiler.Settings.Version); } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/rootcontext.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/rootcontext.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/rootcontext.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/roottypes.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/roottypes.cs index df7962043..b998806b8 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/roottypes.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/roottypes.cs @@ -608,7 +608,7 @@ namespace Mono.CSharp return PartialContainer.IsClsComplianceRequired (); } - public override IList LookupExtensionMethod (TypeSpec extensionType, string name, int arity, ref NamespaceContainer scope) + public override ExtensionMethodCandidates LookupExtensionMethod (TypeSpec extensionType, string name, int arity) { return null; } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources b/ICSharpCode.NRefactory.CSharp/Parser/mcs/smcs.exe.sources similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/smcs.exe.sources diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml b/ICSharpCode.NRefactory.CSharp/Parser/mcs/smcs.exe.sources-xml similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/smcs.exe.sources-xml rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/smcs.exe.sources-xml diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs index db028e02b..5f0b31aa0 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/statement.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/statement.cs @@ -8,6 +8,7 @@ // // Copyright 2001, 2002, 2003 Ximian, Inc. // Copyright 2003, 2004 Novell, Inc. +// Copyright 2011 Xamarin Inc. // using System; @@ -732,8 +733,6 @@ namespace Mono.CSharp { return false; unwind_protect = ec.CurrentBranching.AddReturnOrigin (ec.CurrentBranching.CurrentUsageVector, this); - if (unwind_protect) - ec.NeedReturnLabel (); ec.CurrentBranching.CurrentUsageVector.Goto (); return true; } @@ -872,9 +871,12 @@ namespace Mono.CSharp { var async_return = ((AsyncTaskStorey) async_body.Storey).HoistedReturn; // It's null for await without async - if (async_return != null) + if (async_return != null) { async_return.EmitAssign (ec); + ec.Emit (unwind_protect ? OpCodes.Leave : OpCodes.Br, async_body.BodyEnd); + } + return; } @@ -883,7 +885,7 @@ namespace Mono.CSharp { } if (unwind_protect) - ec.Emit (OpCodes.Leave, ec.ReturnLabel); + ec.Emit (OpCodes.Leave, ec.CreateReturnLabel ()); else ec.Emit (OpCodes.Ret); } @@ -1413,6 +1415,11 @@ namespace Mono.CSharp { } public override bool Resolve (BlockContext bc) + { + return Resolve (bc, true); + } + + public bool Resolve (BlockContext bc, bool resolveDeclaratorInitializers) { if (li.Type == null) { TypeSpec type = null; @@ -1490,10 +1497,10 @@ namespace Mono.CSharp { d.Variable.PrepareForFlowAnalysis (bc); } - if (d.Initializer != null) { + if (d.Initializer != null && resolveDeclaratorInitializers) { d.Initializer = ResolveInitializer (bc, d.Variable, d.Initializer); // d.Variable.DefinitelyAssigned - } + } } } @@ -1773,7 +1780,7 @@ namespace Mono.CSharp { public static LocalVariable CreateCompilerGenerated (TypeSpec type, Block block, Location loc) { - LocalVariable li = new LocalVariable (block, "<$$>", Flags.CompilerGenerated | Flags.Used, loc); + LocalVariable li = new LocalVariable (block, GetCompilerGeneratedName (block), Flags.CompilerGenerated | Flags.Used, loc); li.Type = type; return li; } @@ -1809,6 +1816,11 @@ namespace Mono.CSharp { ec.Emit (OpCodes.Ldloca, builder); } + public static string GetCompilerGeneratedName (Block block) + { + return "$locvar" + block.ParametersBlock.TemporaryLocalsCount++.ToString ("X"); + } + public string GetReadOnlyContext () { switch (flags & Flags.ReadonlyMask) { @@ -2304,8 +2316,8 @@ namespace Mono.CSharp { // // An iterator has only 1 storey block // - if (ec.CurrentIterator != null) - return ec.CurrentIterator.Storey; + if (ec.CurrentAnonymousMethod.IsIterator) + return ec.CurrentAnonymousMethod.Storey; // // When referencing a variable in iterator storey from children anonymous method @@ -2487,6 +2499,11 @@ namespace Mono.CSharp { this.block = block; } + public override bool ContainsEmitWithAwait () + { + return child.ContainsEmitWithAwait (); + } + public override Expression CreateExpressionTree (ResolveContext ec) { throw new NotSupportedException (); @@ -2607,6 +2624,8 @@ namespace Mono.CSharp { } } + public int TemporaryLocalsCount { get; set; } + #endregion // @@ -2781,7 +2800,7 @@ namespace Mono.CSharp { AddStatement (new Return (iterator, iterator.Location)); } - public void WrapIntoAsyncTask (TypeContainer host, TypeSpec returnType) + public void WrapIntoAsyncTask (IMemberContext context, TypeContainer host, TypeSpec returnType) { ParametersBlock pb = new ParametersBlock (this, ParametersCompiled.EmptyReadOnlyParameters, StartLocation); pb.EndLocation = EndLocation; @@ -2791,7 +2810,7 @@ namespace Mono.CSharp { var initializer = new AsyncInitializer (pb, host, block_type); initializer.Type = block_type; - am_storey = new AsyncTaskStorey (initializer, returnType); + am_storey = new AsyncTaskStorey (context, initializer, returnType); statements = new List (1); AddStatement (new StatementExpression (initializer)); @@ -3119,8 +3138,6 @@ namespace Mono.CSharp { #if PRODUCTION try { #endif - if (ec.HasReturnLabel) - ec.ReturnLabel = ec.DefineLabel (); base.Emit (ec); @@ -4063,21 +4080,16 @@ namespace Mono.CSharp { } } - // Base class for statements that are implemented in terms of try...finally - public abstract class ExceptionStatement : ResumableStatement + public abstract class TryFinallyBlock : ExceptionStatement { - bool code_follows; - Iterator iter; - List resume_points; - int first_resume_pc; protected Statement stmt; Label dispose_try_block; bool prepared_for_dispose, emitted_dispose; - protected ExceptionStatement (Statement stmt, Location loc) + protected TryFinallyBlock (Statement stmt, Location loc) + : base (loc) { this.stmt = stmt; - this.loc = loc; } #region Properties @@ -4090,43 +4102,30 @@ namespace Mono.CSharp { #endregion - protected abstract void EmitPreTryBody (EmitContext ec); protected abstract void EmitTryBody (EmitContext ec); protected abstract void EmitFinallyBody (EmitContext ec); - protected sealed override void DoEmit (EmitContext ec) + public override Label PrepareForDispose (EmitContext ec, Label end) { - EmitPreTryBody (ec); - - if (resume_points != null) { - ec.EmitInt ((int) IteratorStorey.State.Running); - ec.Emit (OpCodes.Stloc, iter.CurrentPC); - } - - ec.BeginExceptionBlock (); - - if (resume_points != null) { - ec.MarkLabel (resume_point); - - // For normal control flow, we want to fall-through the Switch - // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above - ec.Emit (OpCodes.Ldloc, iter.CurrentPC); - ec.EmitInt (first_resume_pc); - ec.Emit (OpCodes.Sub); - - Label [] labels = new Label [resume_points.Count]; - for (int i = 0; i < resume_points.Count; ++i) - labels [i] = resume_points [i].PrepareForEmit (ec); - ec.Emit (OpCodes.Switch, labels); + if (!prepared_for_dispose) { + prepared_for_dispose = true; + dispose_try_block = ec.DefineLabel (); } + return dispose_try_block; + } + protected sealed override void DoEmit (EmitContext ec) + { + EmitTryBodyPrepare (ec); EmitTryBody (ec); ec.BeginFinallyBlock (); Label start_finally = ec.DefineLabel (); if (resume_points != null) { - ec.Emit (OpCodes.Ldloc, iter.SkipFinally); + var state_machine = (StateMachineInitializer) ec.CurrentAnonymousMethod; + + ec.Emit (OpCodes.Ldloc, state_machine.SkipFinally); ec.Emit (OpCodes.Brfalse_S, start_finally); ec.Emit (OpCodes.Endfinally); } @@ -4137,44 +4136,6 @@ namespace Mono.CSharp { ec.EndExceptionBlock (); } - public void SomeCodeFollows () - { - code_follows = true; - } - - public override bool Resolve (BlockContext ec) - { - // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause - // So, ensure there's some IL code after this statement. - if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable) - ec.NeedReturnLabel (); - - iter = ec.CurrentIterator; - return true; - } - - public void AddResumePoint (ResumableStatement stmt, int pc) - { - if (resume_points == null) { - resume_points = new List (); - first_resume_pc = pc; - } - - if (pc != first_resume_pc + resume_points.Count) - throw new InternalErrorException ("missed an intervening AddResumePoint?"); - - resume_points.Add (stmt); - } - - public override Label PrepareForDispose (EmitContext ec, Label end) - { - if (!prepared_for_dispose) { - prepared_for_dispose = true; - dispose_try_block = ec.DefineLabel (); - } - return dispose_try_block; - } - public override void EmitForDispose (EmitContext ec, LocalBuilder pc, Label end, bool have_dispatcher) { if (emitted_dispose) @@ -4192,24 +4153,24 @@ namespace Mono.CSharp { ec.MarkLabel (dispose_try_block); - Label [] labels = null; + Label[] labels = null; for (int i = 0; i < resume_points.Count; ++i) { - ResumableStatement s = resume_points [i]; + ResumableStatement s = resume_points[i]; Label ret = s.PrepareForDispose (ec, end_of_try); if (ret.Equals (end_of_try) && labels == null) continue; if (labels == null) { - labels = new Label [resume_points.Count]; + labels = new Label[resume_points.Count]; for (int j = 0; j < i; ++j) - labels [j] = end_of_try; + labels[j] = end_of_try; } - labels [i] = ret; + labels[i] = ret; } if (labels != null) { int j; for (j = 1; j < labels.Length; ++j) - if (!labels [0].Equals (labels [j])) + if (!labels[0].Equals (labels[j])) break; bool emit_dispatcher = j < labels.Length; @@ -4236,7 +4197,84 @@ namespace Mono.CSharp { } } - public class Lock : ExceptionStatement + // + // Base class for blocks using exception handling + // + public abstract class ExceptionStatement : ResumableStatement + { +#if !STATIC + bool code_follows; +#endif + protected List resume_points; + protected int first_resume_pc; + + protected ExceptionStatement (Location loc) + { + this.loc = loc; + } + + protected virtual void EmitTryBodyPrepare (EmitContext ec) + { + StateMachineInitializer state_machine = null; + if (resume_points != null) { + state_machine = (StateMachineInitializer) ec.CurrentAnonymousMethod; + + ec.EmitInt ((int) IteratorStorey.State.Running); + ec.Emit (OpCodes.Stloc, state_machine.CurrentPC); + } + + ec.BeginExceptionBlock (); + + if (resume_points != null) { + ec.MarkLabel (resume_point); + + // For normal control flow, we want to fall-through the Switch + // So, we use CurrentPC rather than the $PC field, and initialize it to an outside value above + ec.Emit (OpCodes.Ldloc, state_machine.CurrentPC); + ec.EmitInt (first_resume_pc); + ec.Emit (OpCodes.Sub); + + Label[] labels = new Label[resume_points.Count]; + for (int i = 0; i < resume_points.Count; ++i) + labels[i] = resume_points[i].PrepareForEmit (ec); + ec.Emit (OpCodes.Switch, labels); + } + } + + public void SomeCodeFollows () + { +#if !STATIC + code_follows = true; +#endif + } + + public override bool Resolve (BlockContext ec) + { +#if !STATIC + // System.Reflection.Emit automatically emits a 'leave' at the end of a try clause + // So, ensure there's some IL code after this statement. + if (!code_follows && resume_points == null && ec.CurrentBranching.CurrentUsageVector.IsUnreachable) + ec.NeedReturnLabel (); +#endif + return true; + } + + public void AddResumePoint (ResumableStatement stmt, int pc) + { + if (resume_points == null) { + resume_points = new List (); + first_resume_pc = pc; + } + + if (pc != first_resume_pc + resume_points.Count) + throw new InternalErrorException ("missed an intervening AddResumePoint?"); + + resume_points.Add (stmt); + } + + } + + public class Lock : TryFinallyBlock { Expression expr; TemporaryVariableReference expr_copy; @@ -4294,21 +4332,21 @@ namespace Mono.CSharp { // Have to keep original lock value around to unlock same location // in the case the original has changed or is null // - expr_copy = TemporaryVariableReference.Create (ec.BuiltinTypes.Object, ec.CurrentBlock.Parent, loc); + expr_copy = TemporaryVariableReference.Create (ec.BuiltinTypes.Object, ec.CurrentBlock, loc); expr_copy.Resolve (ec); // // Ensure Monitor methods are available // if (ResolvePredefinedMethods (ec) > 1) { - lock_taken = TemporaryVariableReference.Create (ec.BuiltinTypes.Bool, ec.CurrentBlock.Parent, loc); + lock_taken = TemporaryVariableReference.Create (ec.BuiltinTypes.Bool, ec.CurrentBlock, loc); lock_taken.Resolve (ec); } return true; } - protected override void EmitPreTryBody (EmitContext ec) + protected override void EmitTryBodyPrepare (EmitContext ec) { expr_copy.EmitAssign (ec, expr); @@ -4324,6 +4362,8 @@ namespace Mono.CSharp { expr_copy.Emit (ec); ec.Emit (OpCodes.Call, ec.Module.PredefinedMembers.MonitorEnter.Get ()); } + + base.EmitTryBodyPrepare (ec); } protected override void EmitTryBody (EmitContext ec) @@ -4409,7 +4449,7 @@ namespace Mono.CSharp { protected override void DoEmit (EmitContext ec) { - using (ec.With (EmitContext.Options.AllCheckStateFlags, false)) + using (ec.With (EmitContext.Options.CheckedScope, false)) Block.Emit (ec); } @@ -4444,7 +4484,7 @@ namespace Mono.CSharp { protected override void DoEmit (EmitContext ec) { - using (ec.With (EmitContext.Options.AllCheckStateFlags, true)) + using (ec.With (EmitContext.Options.CheckedScope, true)) Block.Emit (ec); } @@ -4537,7 +4577,7 @@ namespace Mono.CSharp { public override void EmitExit (EmitContext ec) { - ec.Emit (OpCodes.Ldc_I4_0); + ec.EmitInt (0); ec.Emit (OpCodes.Conv_U); vi.EmitAssign (ec); } @@ -4589,7 +4629,7 @@ namespace Mono.CSharp { public override void EmitExit (EmitContext ec) { - ec.Emit (OpCodes.Ldnull); + ec.EmitNull (); pinned_string.EmitAssign (ec); } } @@ -4910,7 +4950,8 @@ namespace Mono.CSharp { } } - public class TryFinally : ExceptionStatement { + public class TryFinally : TryFinallyBlock + { Block fini; public Statement Stmt { @@ -4950,10 +4991,6 @@ namespace Mono.CSharp { return ok; } - protected override void EmitPreTryBody (EmitContext ec) - { - } - protected override void EmitTryBody (EmitContext ec) { stmt.Emit (ec); @@ -4979,13 +5016,15 @@ namespace Mono.CSharp { } } - public class TryCatch : Statement { + public class TryCatch : ExceptionStatement + { public Block Block; public List Specific; public Catch General; - bool inside_try_finally, code_follows; + readonly bool inside_try_finally; public TryCatch (Block block, List catch_clauses, Location l, bool inside_try_finally) + : base (l) { this.Block = block; this.Specific = catch_clauses; @@ -4996,8 +5035,12 @@ namespace Mono.CSharp { this.General = c; catch_clauses.RemoveAt (0); } + } - loc = l; + public bool IsTryCatchFinally { + get { + return inside_try_finally; + } } public override bool Resolve (BlockContext ec) @@ -5055,23 +5098,13 @@ namespace Mono.CSharp { ec.EndFlowBranching (); - // System.Reflection.Emit automatically emits a 'leave' at the end of a try/catch clause - // So, ensure there's some IL code after this statement - if (!inside_try_finally && !code_follows && ec.CurrentBranching.CurrentUsageVector.IsUnreachable) - ec.NeedReturnLabel (); - - return ok; + return base.Resolve (ec) && ok; } - public void SomeCodeFollows () - { - code_follows = true; - } - - protected override void DoEmit (EmitContext ec) + protected sealed override void DoEmit (EmitContext ec) { if (!inside_try_finally) - ec.BeginExceptionBlock (); + EmitTryBodyPrepare (ec); Block.Emit (ec); @@ -5104,7 +5137,7 @@ namespace Mono.CSharp { } } - public class Using : ExceptionStatement + public class Using : TryFinallyBlock { public class VariableDeclaration : BlockVariableDeclaration { @@ -5144,7 +5177,7 @@ namespace Mono.CSharp { if (IsNested) return true; - return base.Resolve (bc); + return base.Resolve (bc, false); } public Expression ResolveExpression (BlockContext bc) @@ -5230,7 +5263,12 @@ namespace Mono.CSharp { return dispose; } - public Statement RewriteForDeclarators (BlockContext bc, Statement stmt) + public void ResolveDeclaratorInitializer (BlockContext bc) + { + Initializer = base.ResolveInitializer (bc, Variable, Initializer); + } + + public Statement RewriteUsingDeclarators (BlockContext bc, Statement stmt) { for (int i = declarators.Count - 1; i >= 0; --i) { var d = declarators [i]; @@ -5283,9 +5321,10 @@ namespace Mono.CSharp { #endregion - protected override void EmitPreTryBody (EmitContext ec) + protected override void EmitTryBodyPrepare (EmitContext ec) { decl.Emit (ec); + base.EmitTryBodyPrepare (ec); } protected override void EmitTryBody (EmitContext ec) @@ -5311,11 +5350,15 @@ namespace Mono.CSharp { vr.IsLockedByStatement = true; } } else { - if (!decl.Resolve (ec)) - return false; + if (decl.IsNested) { + decl.ResolveDeclaratorInitializer (ec); + } else { + if (!decl.Resolve (ec)) + return false; - if (decl.Declarators != null) { - stmt = decl.RewriteForDeclarators (ec, stmt); + if (decl.Declarators != null) { + stmt = decl.RewriteUsingDeclarators (ec, stmt); + } } vr = null; diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/support.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/support.cs index c10d13f89..4e4b3dbb2 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/support.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/support.cs @@ -240,7 +240,7 @@ namespace Mono.CSharp { public char[] ReadChars (int fromPosition, int toPosition) { char[] chars = new char[toPosition - fromPosition]; - if (buffer_start <= fromPosition && toPosition < buffer_start + buffer.Length) { + if (buffer_start <= fromPosition && toPosition <= buffer_start + buffer.Length) { Array.Copy (buffer, fromPosition - buffer_start, chars, 0, chars.Length); } else { throw new NotImplementedException (); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/symbolwriter.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/symbolwriter.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/symbolwriter.cs diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs index 2e2d17064..708cace79 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/typemanager.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/typemanager.cs @@ -310,9 +310,11 @@ namespace Mono.CSharp public readonly PredefinedMember ActivatorCreateInstance; public readonly PredefinedMember AsyncTaskMethodBuilderCreate; public readonly PredefinedMember AsyncTaskMethodBuilderSetResult; + public readonly PredefinedMember AsyncTaskMethodBuilderSetException; public readonly PredefinedMember AsyncTaskMethodBuilderTask; public readonly PredefinedMember AsyncTaskMethodBuilderGenericCreate; public readonly PredefinedMember AsyncTaskMethodBuilderGenericSetResult; + public readonly PredefinedMember AsyncTaskMethodBuilderGenericSetException; public readonly PredefinedMember AsyncTaskMethodBuilderGenericTask; public readonly PredefinedMember AsyncVoidMethodBuilderCreate; public readonly PredefinedMember AsyncVoidMethodBuilderSetException; @@ -366,6 +368,10 @@ namespace Mono.CSharp AsyncTaskMethodBuilderSetResult = new PredefinedMember (module, types.AsyncTaskMethodBuilder, MemberFilter.Method ("SetResult", 0, ParametersCompiled.EmptyReadOnlyParameters, btypes.Void)); + AsyncTaskMethodBuilderSetException = new PredefinedMember (module, types.AsyncTaskMethodBuilder, + MemberFilter.Method ("SetException", 0, + ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void)); + AsyncTaskMethodBuilderTask = new PredefinedMember (module, types.AsyncTaskMethodBuilder, MemberFilter.Property ("Task", null)); @@ -382,6 +388,10 @@ namespace Mono.CSharp new TypeParameterSpec (0, null, SpecialConstraint.None, Variance.None, null) }, false), btypes.Void)); + AsyncTaskMethodBuilderGenericSetException = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, + MemberFilter.Method ("SetException", 0, + ParametersCompiled.CreateFullyResolved (btypes.Exception), btypes.Void)); + AsyncTaskMethodBuilderGenericTask = new PredefinedMember (module, types.AsyncTaskMethodBuilderGeneric, MemberFilter.Property ("Task", null)); diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs index 8c0a5ddc2..5c8455224 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/typespec.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/typespec.cs @@ -6,6 +6,7 @@ // Dual licensed under the terms of the MIT X11 or GNU GPL // // Copyright 2010 Novell, Inc +// Copyright 2011 Xamarin, Inc (http://www.xamarin.com) // using System; @@ -464,12 +465,13 @@ namespace Mono.CSharp { var t = this; do { - if (t.Interfaces != null) { - foreach (TypeSpec i in t.Interfaces) { - if (i == iface || TypeSpecComparer.IsEqual (i, iface)) + var ifaces = t.Interfaces; + if (ifaces != null) { + for (int i = 0; i < ifaces.Count; ++i) { + if (TypeSpecComparer.IsEqual (ifaces[i], iface)) return true; - if (variantly && TypeSpecComparer.Variant.IsEqual (i, iface)) + if (variantly && TypeSpecComparer.Variant.IsEqual (ifaces[i], iface)) return true; } } @@ -535,6 +537,7 @@ namespace Mono.CSharp return ((TypeParameterSpec) t).IsReferenceType; case MemberKind.Struct: case MemberKind.Enum: + case MemberKind.Void: return false; case MemberKind.InternalCompilerType: // @@ -1016,10 +1019,11 @@ namespace Mono.CSharp } for (int i = 0; i < targs_definition.Length; ++i) { + if (TypeSpecComparer.IsEqual (t1_targs[i], t2_targs[i])) + continue; + Variance v = targs_definition[i].Variance; if (v == Variance.None) { - if (t1_targs[i] == t2_targs[i]) - continue; return false; } diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs b/ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs similarity index 99% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs index 0ac678300..44c3a41f7 100644 --- a/ICSharpCode.NRefactory/CSharp/Parser/mcs/visit.cs +++ b/ICSharpCode.NRefactory.CSharp/Parser/mcs/visit.cs @@ -178,6 +178,11 @@ namespace Mono.CSharp { return null; } + + public virtual object Visit (EmptyExpression emptyExpression) + { + return null; + } public virtual object Visit (If ifStatement) { diff --git a/ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output b/ICSharpCode.NRefactory.CSharp/Parser/mcs/y.output similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Parser/mcs/y.output rename to ICSharpCode.NRefactory.CSharp/Parser/mcs/y.output diff --git a/ICSharpCode.Editor/Properties/AssemblyInfo.cs b/ICSharpCode.NRefactory.CSharp/Properties/AssemblyInfo.cs similarity index 88% rename from ICSharpCode.Editor/Properties/AssemblyInfo.cs rename to ICSharpCode.NRefactory.CSharp/Properties/AssemblyInfo.cs index 7d06f8744..0d277c77f 100644 --- a/ICSharpCode.Editor/Properties/AssemblyInfo.cs +++ b/ICSharpCode.NRefactory.CSharp/Properties/AssemblyInfo.cs @@ -9,11 +9,11 @@ using System.Runtime.InteropServices; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("ICSharpCode.Editor")] +[assembly: AssemblyTitle("ICSharpCode.NRefactory.CSharp")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("ICSharpCode.Editor")] +[assembly: AssemblyProduct("ICSharpCode.NRefactory.CSharp")] [assembly: AssemblyCopyright("Copyright 2011")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/Action.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/Action.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/Action.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs index f934917d9..8b112a5cd 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/AddAnotherAccessor.cs @@ -1,4 +1,4 @@ -// +// // AddAnotherAccessor.cs // // Author: @@ -37,7 +37,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (pdecl == null) return false; var type = pdecl.Parent as TypeDeclaration; - if (type != null && type.ClassType == ICSharpCode.NRefactory.TypeSystem.ClassType.Interface) + if (type != null && type.ClassType == ClassType.Interface) return false; return pdecl.Setter.IsNull || pdecl.Getter.IsNull; diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs index 3c52562aa..96b0915f3 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CheckIfParameterIsNull.cs @@ -1,4 +1,4 @@ -// +// // CheckIfParameterIsNull.cs // // Author: @@ -94,7 +94,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring this.parameter = parameter; } - public object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) + public override object VisitIfElseStatement (IfElseStatement ifElseStatement, object data) { if (ifElseStatement.Condition is BinaryOperatorExpression) { var binOp = ifElseStatement.Condition as BinaryOperatorExpression; diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertDecToHex.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertDecToHex.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertDecToHex.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertForeachToFor.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertHexToDec.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ConvertHexToDec.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ConvertHexToDec.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateBackingStore.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateBackingStore.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateBackingStore.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateEventInvocator.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateEventInvocator.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateField.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateField.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateField.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateLocalVariable.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateLocalVariable.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateProperty.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/CreateProperty.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/CreateProperty.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/FlipOperatorArguments.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateGetter.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateGetter.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateGetter.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs index 28ce57cf4..04c98c5b4 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/GenerateSwitchLabels.cs @@ -1,4 +1,4 @@ -// +// // GenerateSwitchLabels.cs // // Author: @@ -38,7 +38,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var result = context.Resolve (switchStatement.Expression); if (result == null) return false; - return result.Type.IsEnum (); + return result.Type.Kind == TypeKind.Enum; } public void Run (RefactoringContext context) diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs index 503899bd9..f98b5a1f3 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/InsertAnonymousMethodSignature.cs @@ -1,4 +1,4 @@ -// +// // InsertAnonymousMethodSignature.cs // // Author: @@ -84,7 +84,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (resolvedType == null) return null; delegateType = resolvedType; - if (!delegateType.IsDelegate ()) + if (delegateType.Kind != TypeKind.Delegate) return null; return anonymousMethodExpression; diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs similarity index 94% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs index d1530b90d..5a1ef70b2 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/IntroduceFormatItem.cs @@ -1,4 +1,4 @@ -// +// // IntroduceFormatItem.cs // // Author: @@ -47,8 +47,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (pexpr == null || !(pexpr.Value is string)) return false; if (pexpr.LiteralValue.StartsWith ("@")) - return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 1) && - new AstLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; + return pexpr.StartLocation < new TextLocation (context.Location.Line, context.Location.Column - 1) && + new TextLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; return pexpr.StartLocation < context.Location && context.Location < pexpr.EndLocation; } diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/InvertIf.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/InvertIf.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/InvertIf.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/RemoveBackingStore.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/RemoveBackingStore.cs index 6655656bc..05c6d6e53 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBackingStore.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/RemoveBackingStore.cs @@ -1,4 +1,4 @@ -// +// // RemoveBackingStore.cs // // Author: @@ -24,9 +24,10 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; -using ICSharpCode.NRefactory.TypeSystem; using System.Linq; using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.CSharp.Refactoring { @@ -80,7 +81,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring // automatic properties always need getter & setter if (propertyDeclaration == null || propertyDeclaration.Getter.IsNull || propertyDeclaration.Setter.IsNull || propertyDeclaration.Getter.Body.IsNull || propertyDeclaration.Setter.Body.IsNull) return null; - if (!context.HasCSharp3Support || propertyDeclaration.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Abstract) || ((TypeDeclaration)propertyDeclaration.Parent).ClassType == ICSharpCode.NRefactory.TypeSystem.ClassType.Interface) + if (!context.HasCSharp3Support || propertyDeclaration.HasModifier (ICSharpCode.NRefactory.CSharp.Modifiers.Abstract) || ((TypeDeclaration)propertyDeclaration.Parent).ClassType == ClassType.Interface) return null; var getterField = ScanGetter (context, propertyDeclaration); if (getterField == null) diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/RemoveBraces.cs similarity index 97% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/RemoveBraces.cs index eed2e429f..9d78086cf 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/RemoveBraces.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/RemoveBraces.cs @@ -51,7 +51,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring var block = context.GetNode (); if (block == null || block.LBraceToken.IsNull || block.RBraceToken.IsNull) return null; - if (block.Parent.Role == TypeDeclaration.MemberRole) + if (!(block.Parent is Statement)) return null; if (block.Statements.Count () != 1) return null; diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/ReplaceEmptyString.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/SplitDeclarationAndAssignment.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/SplitString.cs similarity index 82% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/SplitString.cs index 425f54ca3..c811f18ca 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/SplitString.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/SplitString.cs @@ -1,4 +1,4 @@ -// +// // SplitString.cs // // Author: @@ -37,10 +37,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (pexpr == null || !(pexpr.Value is string)) return false; if (pexpr.LiteralValue.StartsWith ("@")) - return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 2) && - new AstLocation (context.Location.Line, context.Location.Column + 2) < pexpr.EndLocation; - return pexpr.StartLocation < new AstLocation (context.Location.Line, context.Location.Column - 1) && - new AstLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; + return pexpr.StartLocation < new TextLocation (context.Location.Line, context.Location.Column - 2) && + new TextLocation (context.Location.Line, context.Location.Column + 2) < pexpr.EndLocation; + return pexpr.StartLocation < new TextLocation (context.Location.Line, context.Location.Column - 1) && + new TextLocation (context.Location.Line, context.Location.Column + 1) < pexpr.EndLocation; } public void Run (RefactoringContext context) diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseExplicitType.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseExplicitType.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseVarKeyword.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/ContextAction/UseVarKeyword.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/ContextAction/UseVarKeyword.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/CreateLinkAction.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/CreateLinkAction.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/CreateLinkAction.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/FormatTextAction.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/FormatTextAction.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/FormatTextAction.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/IActionFactory.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/IActionFactory.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/IActionFactory.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/IContextAction.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/IContextAction.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/IContextAction.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs similarity index 84% rename from ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs index 47d5e7ba7..fd0e81a4f 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/NodeOutputAction.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/NodeOutputAction.cs @@ -1,4 +1,4 @@ -// +// // NodeOutputChange.cs // // Author: @@ -26,6 +26,7 @@ using System; using System.Collections.Generic; +using ICSharpCode.NRefactory.Editor; namespace ICSharpCode.NRefactory.CSharp.Refactoring { @@ -109,28 +110,4 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring this.NodeOutput = output; } } - - - /// - /// An (Offset,Length)-pair. - /// - public interface ISegment - { - /// - /// Gets the start offset of the segment. - /// - int Offset { get; } - - /// - /// Gets the length of the segment. - /// - /// Must not be negative. - int Length { get; } - - /// - /// Gets the end offset of the segment. - /// - /// EndOffset = Offset + Length; - int EndOffset { get; } - } } diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/NodeSelectionAction.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/NodeSelectionAction.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/NodeSelectionAction.cs diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs similarity index 90% rename from ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs index a73d97373..420b585f8 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/RefactoringContext.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/RefactoringContext.cs @@ -1,4 +1,4 @@ -// +// // RefactoringContext.cs // // Author: @@ -25,9 +25,10 @@ // THE SOFTWARE. using System; using System.Linq; -using ICSharpCode.NRefactory.TypeSystem; -using System.Collections.Generic; using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.CSharp.Refactoring { @@ -44,7 +45,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } } - public AstLocation Location { + public TextLocation Location { get; protected set; } @@ -92,12 +93,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring public abstract int SelectionStart { get; } public abstract int SelectionEnd { get; } public abstract int SelectionLength { get; } - public abstract int GetOffset (AstLocation location); + public abstract int GetOffset (TextLocation location); public int GetOffset (int line, int col) { - return GetOffset (new AstLocation (line, col)); + return GetOffset (new TextLocation (line, col)); } - public abstract AstLocation GetLocation (int offset); + public abstract TextLocation GetLocation (int offset); public abstract string GetText (int offset, int length); #endregion @@ -127,12 +128,12 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } } - public static class ExtensionMethods + public static class RefactoringExtensions { #region ConvertTypes public static ICSharpCode.NRefactory.CSharp.AstType ConvertToAstType (this IType type) { - var builder = new TypeSystemAstBuilder (); + var builder = new TypeSystemAstBuilder (MinimalResolveContext.Instance); return builder.ConvertType (type); } #endregion diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs similarity index 98% rename from ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs index db6be3189..39d45f9af 100644 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/Script.cs +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/Script.cs @@ -1,4 +1,4 @@ -// +// // Script.cs // // Author: @@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring stringWriter.NewLine = Context.EolMarker; if (startWithNewLine) formatter.NewLine (); - var visitor = new OutputVisitor (formatter, Context.FormattingOptions); + var visitor = new CSharpOutputVisitor (formatter, Context.FormattingOptions); visitor.OutputStarted += (sender, e) => { result.NodeSegments [e.AstNode] = new NodeOutput.Segment (stringWriter.GetStringBuilder ().Length); }; diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/TextReplaceAction.cs similarity index 100% rename from ICSharpCode.NRefactory/CSharp/Refactoring/TextReplaceAction.cs rename to ICSharpCode.NRefactory.CSharp/Refactoring/TextReplaceAction.cs diff --git a/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs new file mode 100644 index 000000000..e00ab28fd --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs @@ -0,0 +1,733 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + /// + /// Converts from type system to the C# AST. + /// + public class TypeSystemAstBuilder + { + readonly CSharpResolver resolver; + readonly ITypeResolveContext context; + + #region Constructor + /// + /// Creates a new TypeSystemAstBuilder. + /// + /// + /// A resolver initialized for the position where the type will be inserted. + /// + public TypeSystemAstBuilder(CSharpResolver resolver) + { + if (resolver == null) + throw new ArgumentNullException("resolver"); + this.resolver = resolver; + this.context = resolver.Context; + InitProperties(); + } + + /// + /// Creates a new TypeSystemAstBuilder. + /// + /// + /// Context used for resolving types. + /// + public TypeSystemAstBuilder(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + InitProperties(); + } + #endregion + + #region Properties + void InitProperties() + { + this.ShowAccessibility = true; + this.ShowModifiers = true; + this.ShowBaseTypes = true; + this.ShowTypeParameters = true; + this.ShowTypeParameterConstraints = true; + this.ShowParameterNames = true; + this.ShowConstantValues = true; + } + + /// + /// Controls the accessibility modifiers are shown. + /// + public bool ShowAccessibility { get; set; } + + /// + /// Controls the non-accessibility modifiers are shown. + /// + public bool ShowModifiers { get; set; } + + /// + /// Controls whether base type references are shown. + /// + public bool ShowBaseTypes { get; set; } + + /// + /// Controls whether type parameter declarations are shown. + /// + public bool ShowTypeParameters { get; set; } + + /// + /// Controls whether contraints on type parameter declarations are shown. + /// Has no effect if ShowTypeParameters is false. + /// + public bool ShowTypeParameterConstraints { get; set; } + + /// + /// Controls whether the names of parameters are shown. + /// + public bool ShowParameterNames { get; set; } + + /// + /// Controls whether to show default values of optional parameters, and the values of constant fields. + /// + public bool ShowConstantValues { get; set; } + #endregion + + #region Convert Type + public AstType ConvertType(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + TypeWithElementType typeWithElementType = type as TypeWithElementType; + if (typeWithElementType != null) { + if (typeWithElementType is PointerType) { + return ConvertType(typeWithElementType.ElementType).MakePointerType(); + } else if (typeWithElementType is ArrayType) { + return ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions); + } else { + // e.g. ByReferenceType; not supported as type in C# + return ConvertType(typeWithElementType.ElementType); + } + } + ParameterizedType pt = type as ParameterizedType; + if (pt != null) { + if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) { + return ConvertType(pt.TypeArguments[0]).MakeNullableType(); + } + return ConvertTypeHelper(pt.GetDefinition(), pt.TypeArguments); + } + ITypeDefinition typeDef = type as ITypeDefinition; + if (typeDef != null) { + if (typeDef.TypeParameterCount > 0) { + // Unbound type + IType[] typeArguments = new IType[typeDef.TypeParameterCount]; + for (int i = 0; i < typeArguments.Length; i++) { + typeArguments[i] = SharedTypes.UnboundTypeArgument; + } + return ConvertTypeHelper(typeDef, typeArguments); + } else { + return ConvertTypeHelper(typeDef, EmptyList.Instance); + } + } + return new SimpleType(type.Name); + } + + public AstType ConvertTypeReference(ITypeReference typeRef) + { + ArrayTypeReference array = typeRef as ArrayTypeReference; + if (array != null) { + return ConvertTypeReference(array.ElementType).MakeArrayType(array.Dimensions); + } + PointerTypeReference pointer = typeRef as PointerTypeReference; + if (pointer != null) { + return ConvertTypeReference(pointer.ElementType).MakePointerType(); + } + ByReferenceType brt = typeRef as ByReferenceType; + if (brt != null) { + return ConvertTypeReference(brt.ElementType); + } + + IType type = typeRef.Resolve(context); + if (type.Kind != TypeKind.Unknown) + return ConvertType(type); + // Unknown type, let's try if we can find an appropriate type + // (anything is better than displaying a question mark) + KnownTypeReference knownType = typeRef as KnownTypeReference; + if (knownType != null) { + string keyword = ReflectionHelper.GetCSharpNameByTypeCode(knownType.TypeCode); + if (keyword != null) + return new PrimitiveType(keyword); + } + SimpleTypeOrNamespaceReference str = typeRef as SimpleTypeOrNamespaceReference; + if (str != null) { + return new SimpleType(str.Identifier, str.TypeArguments.Select(ConvertTypeReference)); + } + MemberTypeOrNamespaceReference mtr = typeRef as MemberTypeOrNamespaceReference; + if (mtr != null) { + return new MemberType(ConvertTypeReference(mtr.Target), mtr.Identifier, mtr.TypeArguments.Select(ConvertTypeReference)) { + IsDoubleColon = mtr.Target is AliasNamespaceReference + }; + } + AliasNamespaceReference alias = typeRef as AliasNamespaceReference; + if (alias != null) { + return new SimpleType(alias.Identifier); + } + // Unknown type reference that couldn't be resolved + return new SimpleType("?"); + } + + AstType ConvertTypeHelper(ITypeDefinition typeDef, IList typeArguments) + { + Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount); + TypeCode typeCode = ReflectionHelper.GetTypeCode(typeDef); + if (typeCode != TypeCode.Empty) { + string keyword = ReflectionHelper.GetCSharpNameByTypeCode(typeCode); + if (keyword != null) + return new PrimitiveType(keyword); + } + // There is no type code for System.Void + if (typeDef.Kind == TypeKind.Void) + return new PrimitiveType("void"); + + // The number of type parameters belonging to outer classes + int outerTypeParameterCount; + if (typeDef.DeclaringType != null) + outerTypeParameterCount = typeDef.DeclaringType.TypeParameterCount; + else + outerTypeParameterCount = 0; + + if (resolver != null) { + // Look if there's an alias to the target type + for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) { + foreach (var pair in usingScope.UsingAliases) { + IType type = pair.Value.Resolve(resolver.Context); + if (TypeMatches(type, typeDef, typeArguments)) + return new SimpleType(pair.Key); + } + } + + IList localTypeArguments; + if (typeDef.TypeParameterCount > outerTypeParameterCount) { + localTypeArguments = new IType[typeDef.TypeParameterCount - outerTypeParameterCount]; + for (int i = 0; i < localTypeArguments.Count; i++) { + localTypeArguments[i] = typeArguments[outerTypeParameterCount + i]; + } + } else { + localTypeArguments = EmptyList.Instance; + } + TypeResolveResult trr = resolver.ResolveSimpleName(typeDef.Name, localTypeArguments) as TypeResolveResult; + if (trr != null && !trr.IsError && TypeMatches(trr.Type, typeDef, typeArguments)) { + // We can use the short type name + SimpleType shortResult = new SimpleType(typeDef.Name); + AddTypeArguments(shortResult, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount); + return shortResult; + } + } + + MemberType result = new MemberType(); + if (typeDef.DeclaringTypeDefinition != null) { + // Handle nested types + result.Target = ConvertTypeHelper(typeDef.DeclaringTypeDefinition, typeArguments); + } else { + // Handle top-level types + if (string.IsNullOrEmpty(typeDef.Namespace)) { + result.Target = new SimpleType("global"); + result.IsDoubleColon = true; + } else { + result.Target = ConvertNamespace(typeDef.Namespace); + } + } + result.MemberName = typeDef.Name; + AddTypeArguments(result, typeArguments, outerTypeParameterCount, typeDef.TypeParameterCount); + return result; + } + + /// + /// Gets whether 'type' is the same as 'typeDef' parameterized with the given type arguments. + /// + bool TypeMatches(IType type, ITypeDefinition typeDef, IList typeArguments) + { + if (typeDef.TypeParameterCount == 0) { + return typeDef.Equals(type); + } else { + if (!typeDef.Equals(type.GetDefinition())) + return false; + ParameterizedType pt = type as ParameterizedType; + if (pt == null) { + return typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument); + } + var ta = pt.TypeArguments; + for (int i = 0; i < ta.Count; i++) { + if (!ta[i].Equals(typeArguments[i])) + return false; + } + return true; + } + } + + /// + /// Adds type arguments to the result type. + /// + /// The result AST node (a SimpleType or MemberType) + /// The list of type arguments + /// Index of first type argument to add + /// Index after last type argument to add + void AddTypeArguments(AstType result, IList typeArguments, int startIndex, int endIndex) + { + for (int i = startIndex; i < endIndex; i++) { + result.AddChild(ConvertType(typeArguments[i]), AstType.Roles.TypeArgument); + } + } + + AstType ConvertNamespace(string ns) + { + if (resolver != null) { + // Look if there's an alias to the target namespace + for (UsingScope usingScope = resolver.CurrentUsingScope; usingScope != null; usingScope = usingScope.Parent) { + foreach (var pair in usingScope.UsingAliases) { + // maybe add some caching? we're resolving all aliases N times when converting a namespace name with N parts + NamespaceResolveResult nrr = pair.Value.ResolveNamespace(resolver.Context); + if (nrr != null && nrr.NamespaceName == ns) + return new SimpleType(pair.Key); + } + } + } + + int pos = ns.LastIndexOf('.'); + if (pos < 0) { + if (IsValidNamespace(ns)) { + return new SimpleType(ns); + } else { + return new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = ns + }; + } + } else { + string parentNamespace = ns.Substring(0, pos); + string localNamespace = ns.Substring(pos + 1); + return new MemberType { + Target = ConvertNamespace(parentNamespace), + MemberName = localNamespace + }; + } + } + + bool IsValidNamespace(string firstNamespacePart) + { + if (resolver == null) + return true; // just assume namespaces are valid if we don't have a resolver + NamespaceResolveResult nrr = resolver.ResolveSimpleName(firstNamespacePart, EmptyList.Instance) as NamespaceResolveResult; + return nrr != null && !nrr.IsError && nrr.NamespaceName == firstNamespacePart; + } + #endregion + + #region Convert Constant Value + public Expression ConvertConstantValue(IConstantValue constantValue) + { + if (constantValue == null) + throw new ArgumentNullException("constantValue"); + return ConvertConstantValue(constantValue.Resolve(context)); + } + + Expression ConvertConstantValue(ResolveResult rr) + { + if (rr is TypeOfResolveResult) { + return new TypeOfExpression(ConvertType(((TypeOfResolveResult)rr).Type)); + } else if (rr is ArrayCreateResolveResult) { + ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr; + AstType type = ConvertType(acrr.Type); + throw new NotImplementedException(); + } else if (rr.IsCompileTimeConstant) { + object val = rr.ConstantValue; + if (val == null) { + if (rr.Type.IsReferenceType(context) == true) + return new NullReferenceExpression(); + else + return new DefaultValueExpression(ConvertType(rr.Type)); + } else if (rr.Type.Kind == TypeKind.Enum) { + throw new NotImplementedException(); + } else { + return new PrimitiveExpression(val); + } + } else { + return new EmptyExpression(); + } + } + #endregion + + #region Convert Parameter + public ParameterDeclaration ConvertParameter(IParameter parameter) + { + if (parameter == null) + throw new ArgumentNullException("parameter"); + ParameterDeclaration decl = new ParameterDeclaration(); + if (parameter.IsRef) { + decl.ParameterModifier = ParameterModifier.Ref; + } else if (parameter.IsOut) { + decl.ParameterModifier = ParameterModifier.Out; + } else if (parameter.IsParams) { + decl.ParameterModifier = ParameterModifier.Params; + } + decl.Type = ConvertTypeReference(parameter.Type); + if (this.ShowParameterNames) { + decl.Name = parameter.Name; + } + if (parameter.IsOptional && this.ShowConstantValues) { + decl.DefaultExpression = ConvertConstantValue(parameter.DefaultValue); + } + return decl; + } + #endregion + + #region Convert Entity + public AstNode ConvertEntity(IEntity entity) + { + if (entity == null) + throw new ArgumentNullException("entity"); + switch (entity.EntityType) { + case EntityType.TypeDefinition: + return ConvertTypeDefinition((ITypeDefinition)entity); + case EntityType.Field: + return ConvertField((IField)entity); + case EntityType.Property: + return ConvertProperty((IProperty)entity); + case EntityType.Indexer: + return ConvertIndexer((IProperty)entity); + case EntityType.Event: + return ConvertEvent((IEvent)entity); + case EntityType.Method: + return ConvertMethod((IMethod)entity); + case EntityType.Operator: + return ConvertOperator((IMethod)entity); + case EntityType.Constructor: + return ConvertConstructor((IMethod)entity); + case EntityType.Destructor: + return ConvertDestructor((IMethod)entity); + default: + throw new ArgumentException("Invalid value for EntityType: " + entity.EntityType); + } + } + + AttributedNode ConvertTypeDefinition(ITypeDefinition typeDefinition) + { + Modifiers modifiers = ModifierFromAccessibility(typeDefinition.Accessibility); + if (this.ShowModifiers) { + if (typeDefinition.IsStatic) { + modifiers |= Modifiers.Static; + } else if (typeDefinition.IsAbstract) { + modifiers |= Modifiers.Abstract; + } else if (typeDefinition.IsSealed) { + modifiers |= Modifiers.Sealed; + } + if (typeDefinition.IsShadowing) { + modifiers |= Modifiers.New; + } + } + + ClassType classType; + switch (typeDefinition.Kind) { + case TypeKind.Struct: + classType = ClassType.Struct; + break; + case TypeKind.Enum: + classType = ClassType.Enum; + break; + case TypeKind.Interface: + classType = ClassType.Interface; + break; + case TypeKind.Delegate: + IMethod invoke = typeDefinition.GetDelegateInvokeMethod(); + if (invoke != null) + return ConvertDelegate(invoke, modifiers); + else + goto default; + default: + classType = ClassType.Class; + break; + } + + TypeDeclaration decl = new TypeDeclaration(); + decl.Modifiers = modifiers; + decl.ClassType = classType; + decl.Name = typeDefinition.Name; + + if (this.ShowTypeParameters) { + foreach (ITypeParameter tp in typeDefinition.TypeParameters) { + decl.TypeParameters.Add(ConvertTypeParameter(tp)); + } + } + + if (this.ShowBaseTypes) { + foreach (ITypeReference baseType in typeDefinition.BaseTypes) { + decl.BaseTypes.Add(ConvertTypeReference(baseType)); + } + } + + if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) { + foreach (ITypeParameter tp in typeDefinition.TypeParameters) { + var constraint = ConvertTypeParameterConstraint(tp); + if (constraint != null) + decl.Constraints.Add(constraint); + } + } + return decl; + } + + DelegateDeclaration ConvertDelegate(IMethod invokeMethod, Modifiers modifiers) + { + ITypeDefinition d = invokeMethod.DeclaringTypeDefinition; + + DelegateDeclaration decl = new DelegateDeclaration(); + decl.Modifiers = modifiers; + decl.ReturnType = ConvertTypeReference(invokeMethod.ReturnType); + decl.Name = d.Name; + + if (this.ShowTypeParameters) { + foreach (ITypeParameter tp in d.TypeParameters) { + decl.TypeParameters.Add(ConvertTypeParameter(tp)); + } + } + + foreach (IParameter p in invokeMethod.Parameters) { + decl.Parameters.Add(ConvertParameter(p)); + } + + if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) { + foreach (ITypeParameter tp in d.TypeParameters) { + var constraint = ConvertTypeParameterConstraint(tp); + if (constraint != null) + decl.Constraints.Add(constraint); + } + } + return decl; + } + + AstNode ConvertField(IField field) + { + FieldDeclaration decl = new FieldDeclaration(); + if (ShowModifiers) { + Modifiers m = GetMemberModifiers(field); + if (field.IsConst) { + m &= ~Modifiers.Static; + m |= Modifiers.Const; + } else if (field.IsReadOnly) { + m |= Modifiers.Readonly; + } else if (field.IsVolatile) { + m |= Modifiers.Volatile; + } + decl.Modifiers = m; + } + decl.ReturnType = ConvertTypeReference(field.ReturnType); + Expression initializer = null; + if (field.IsConst && this.ShowConstantValues) + initializer = ConvertConstantValue(field.ConstantValue); + decl.Variables.Add(new VariableInitializer(field.Name, initializer)); + return decl; + } + + Accessor ConvertAccessor(IAccessor accessor) + { + if (accessor == null) + return Accessor.Null; + Accessor decl = new Accessor(); + decl.Modifiers = ModifierFromAccessibility(accessor.Accessibility); + return decl; + } + + PropertyDeclaration ConvertProperty(IProperty property) + { + PropertyDeclaration decl = new PropertyDeclaration(); + decl.Modifiers = GetMemberModifiers(property); + decl.ReturnType = ConvertTypeReference(property.ReturnType); + decl.Name = property.Name; + decl.Getter = ConvertAccessor(property.Getter); + decl.Setter = ConvertAccessor(property.Setter); + return decl; + } + + IndexerDeclaration ConvertIndexer(IProperty indexer) + { + IndexerDeclaration decl = new IndexerDeclaration(); + decl.Modifiers = GetMemberModifiers(indexer); + decl.ReturnType = ConvertTypeReference(indexer.ReturnType); + foreach (IParameter p in indexer.Parameters) { + decl.Parameters.Add(ConvertParameter(p)); + } + decl.Getter = ConvertAccessor(indexer.Getter); + decl.Setter = ConvertAccessor(indexer.Setter); + return decl; + } + + EventDeclaration ConvertEvent(IEvent ev) + { + EventDeclaration decl = new EventDeclaration(); + decl.Modifiers = GetMemberModifiers(ev); + decl.ReturnType = ConvertTypeReference(ev.ReturnType); + decl.Variables.Add(new VariableInitializer(ev.Name)); + return decl; + } + + MethodDeclaration ConvertMethod(IMethod method) + { + MethodDeclaration decl = new MethodDeclaration(); + decl.Modifiers = GetMemberModifiers(method); + decl.ReturnType = ConvertTypeReference(method.ReturnType); + decl.Name = method.Name; + + if (this.ShowTypeParameters) { + foreach (ITypeParameter tp in method.TypeParameters) { + decl.TypeParameters.Add(ConvertTypeParameter(tp)); + } + } + + foreach (IParameter p in method.Parameters) { + decl.Parameters.Add(ConvertParameter(p)); + } + + if (this.ShowTypeParameters && this.ShowTypeParameterConstraints) { + foreach (ITypeParameter tp in method.TypeParameters) { + var constraint = ConvertTypeParameterConstraint(tp); + if (constraint != null) + decl.Constraints.Add(constraint); + } + } + return decl; + } + + AstNode ConvertOperator(IMethod op) + { + OperatorType? opType = OperatorDeclaration.GetOperatorType(op.Name); + if (opType == null) + return ConvertMethod(op); + + OperatorDeclaration decl = new OperatorDeclaration(); + decl.Modifiers = GetMemberModifiers(op); + decl.OperatorType = opType.Value; + decl.ReturnType = ConvertTypeReference(op.ReturnType); + foreach (IParameter p in op.Parameters) { + decl.Parameters.Add(ConvertParameter(p)); + } + return decl; + } + + ConstructorDeclaration ConvertConstructor(IMethod ctor) + { + ConstructorDeclaration decl = new ConstructorDeclaration(); + decl.Modifiers = GetMemberModifiers(ctor); + decl.Name = ctor.DeclaringTypeDefinition.Name; + foreach (IParameter p in ctor.Parameters) { + decl.Parameters.Add(ConvertParameter(p)); + } + return decl; + } + + DestructorDeclaration ConvertDestructor(IMethod dtor) + { + DestructorDeclaration decl = new DestructorDeclaration(); + decl.Name = dtor.DeclaringTypeDefinition.Name; + return decl; + } + #endregion + + #region Convert Modifiers + Modifiers ModifierFromAccessibility(Accessibility accessibility) + { + if (!this.ShowAccessibility) + return Modifiers.None; + switch (accessibility) { + case Accessibility.Private: + return Modifiers.Private; + case Accessibility.Public: + return Modifiers.Public; + case Accessibility.Protected: + return Modifiers.Protected; + case Accessibility.Internal: + return Modifiers.Internal; + case Accessibility.ProtectedOrInternal: + case Accessibility.ProtectedAndInternal: + return Modifiers.Protected | Modifiers.Internal; + default: + return Modifiers.None; + } + } + + Modifiers GetMemberModifiers(IMember member) + { + Modifiers m = ModifierFromAccessibility(member.Accessibility); + if (this.ShowModifiers) { + if (member.IsStatic) { + m |= Modifiers.Static; + } else { + if (member.IsAbstract) + m |= Modifiers.Abstract; + if (member.IsOverride) + m |= Modifiers.Override; + if (member.IsVirtual && !member.IsAbstract && !member.IsOverride) + m |= Modifiers.Virtual; + if (member.IsSealed) + m |= Modifiers.Sealed; + } + if (member.IsShadowing) + m |= Modifiers.New; + } + return m; + } + #endregion + + #region Convert Type Parameter + TypeParameterDeclaration ConvertTypeParameter(ITypeParameter tp) + { + TypeParameterDeclaration decl = new TypeParameterDeclaration(); + decl.Variance = tp.Variance; + decl.Name = tp.Name; + return decl; + } + + Constraint ConvertTypeParameterConstraint(ITypeParameter tp) + { + if (tp.Constraints.Count == 0 && !tp.HasDefaultConstructorConstraint && !tp.HasReferenceTypeConstraint && !tp.HasValueTypeConstraint) { + return null; + } + Constraint c = new Constraint(); + c.TypeParameter = tp.Name; + if (tp.HasReferenceTypeConstraint) { + c.BaseTypes.Add(new PrimitiveType("class")); + } else if (tp.HasValueTypeConstraint) { + c.BaseTypes.Add(new PrimitiveType("struct")); + } + foreach (ITypeReference tr in tp.Constraints) { + c.BaseTypes.Add(ConvertTypeReference(tr)); + } + if (tp.HasDefaultConstructorConstraint) { + c.BaseTypes.Add(new PrimitiveType("new")); + } + return c; + } + #endregion + + #region Convert Variable + public VariableDeclarationStatement ConvertVariable(IVariable v) + { + VariableDeclarationStatement decl = new VariableDeclarationStatement(); + decl.Modifiers = v.IsConst ? Modifiers.Const : Modifiers.None; + decl.Type = ConvertTypeReference(v.Type); + Expression initializer = null; + if (v.IsConst) + initializer = ConvertConstantValue(v.ConstantValue); + decl.Variables.Add(new VariableInitializer(v.Name, initializer)); + return decl; + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/AliasNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/Resolver/AliasNamespaceReference.cs new file mode 100644 index 000000000..92493038a --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/AliasNamespaceReference.cs @@ -0,0 +1,72 @@ +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Looks up an alias (identifier in front of :: operator). + /// + /// + /// The member lookup performed by the :: operator is handled + /// by . + /// + [Serializable] + public class AliasNamespaceReference : ITypeOrNamespaceReference + { + readonly UsingScope parentUsingScope; + readonly string identifier; + + public AliasNamespaceReference(string identifier, UsingScope parentUsingScope) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.identifier = identifier; + this.parentUsingScope = parentUsingScope; + } + + public string Identifier { + get { return identifier; } + } + + public ResolveResult DoResolve(ITypeResolveContext context) + { + CSharpResolver r = new CSharpResolver(context); + r.CurrentUsingScope = parentUsingScope; + return r.ResolveAlias(identifier); + } + + public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) + { + return DoResolve(context) as NamespaceResolveResult; + } + + public IType Resolve(ITypeResolveContext context) + { + return SharedTypes.UnknownType; + } + + public override string ToString() + { + return identifier + "::"; + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAttribute.cs similarity index 52% rename from ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/CSharpAttribute.cs index f2f5dba1f..b0a04c202 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpAttribute.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpAttribute.cs @@ -1,14 +1,34 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; + +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.CSharp.Resolver { + [Serializable] public sealed class CSharpAttribute : Immutable, IAttribute { ITypeReference attributeType; @@ -41,21 +61,47 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public IMethod ResolveConstructor(ITypeResolveContext context) { + CSharpResolver r = new CSharpResolver(context); IType type = attributeType.Resolve(context); - throw new NotImplementedException(); + int totalArgumentCount = 0; + if (positionalArguments != null) + totalArgumentCount += positionalArguments.Count; + if (namedCtorArguments != null) + totalArgumentCount += namedCtorArguments.Count; + ResolveResult[] arguments = new ResolveResult[totalArgumentCount]; + string[] argumentNames = new string[totalArgumentCount]; + int i = 0; + if (positionalArguments != null) { + while (i < positionalArguments.Count) { + IConstantValue cv = positionalArguments[i]; + arguments[i] = cv.Resolve(context); + i++; + } + } + if (namedCtorArguments != null) { + foreach (var pair in namedCtorArguments) { + argumentNames[i] = pair.Key; + arguments[i] = pair.Value.Resolve(context); + i++; + } + } + MemberResolveResult mrr = r.ResolveObjectCreation(type, arguments, argumentNames) as MemberResolveResult; + return mrr != null ? mrr.Member as IMethod : null; } - public IList GetPositionalArguments(ITypeResolveContext context) + public IList GetPositionalArguments(ITypeResolveContext context) { + List result = new List(); + if (positionalArguments != null) { + foreach (var arg in positionalArguments) { + result.Add(Resolve(arg, context)); + } + } if (namedCtorArguments == null || namedCtorArguments.Count == 0) { // no namedCtorArguments: just return the positionalArguments - if (positionalArguments != null) - return new ReadOnlyCollection(positionalArguments); - else - return EmptyList.Instance; + return result.AsReadOnly(); } // we do have namedCtorArguments, which need to be re-ordered and appended to the positional arguments - List result = new List(this.positionalArguments); IMethod method = ResolveConstructor(context); if (method != null) { for (int i = result.Count; i < method.Parameters.Count; i++) { @@ -63,25 +109,40 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool found = false; foreach (var pair in namedCtorArguments) { if (pair.Key == p.Name) { - result.Add(pair.Value); + result.Add(Resolve(pair.Value, context)); found = true; } } if (!found) { // add the parameter's default value: - result.Add(p.DefaultValue ?? new SimpleConstantValue(p.Type, CSharpResolver.GetDefaultValue(p.Type.Resolve(context)))); + if (p.DefaultValue != null) { + result.Add(Resolve(p.DefaultValue, context)); + } else { + IType type = p.Type.Resolve(context); + result.Add(new ConstantResolveResult(type, CSharpResolver.GetDefaultValue(type))); + } } } } return result.AsReadOnly(); } - public IList> GetNamedArguments(ITypeResolveContext context) + ResolveResult Resolve(IConstantValue constantValue, ITypeResolveContext context) { - if (namedArguments != null) - return new ReadOnlyCollection>(namedArguments); + if (constantValue != null) + return constantValue.Resolve(context); else - return EmptyList>.Instance; + return new ErrorResolveResult(SharedTypes.UnknownType); + } + + public IList> GetNamedArguments(ITypeResolveContext context) + { + if (namedArguments != null) { + return namedArguments.Select(p => new KeyValuePair(p.Key, p.Value.Resolve(context))) + .ToList().AsReadOnly(); + } else { + return EmptyList>.Instance; + } } } @@ -89,6 +150,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; @@ -111,8 +173,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (attrType == null) return SharedTypes.UnknownType; - if (type == SharedTypes.UnknownType || !(type.GetDefinition () != null && type.GetDefinition ().IsDerivedFrom (attrType, context))) - type = withSuffix.Resolve(context); + if (type.GetDefinition() == null || !type.GetDefinition().IsDerivedFrom(attrType, context)) + type = withSuffix.Resolve(context); return type; } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs new file mode 100644 index 000000000..5e5bd2157 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpInvocationResolveResult.cs @@ -0,0 +1,89 @@ +// 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.Collections.Generic; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents the result of a method invocation. + /// + public class CSharpInvocationResolveResult : InvocationResolveResult + { + public readonly OverloadResolutionErrors OverloadResolutionErrors; + + /// + /// Gets whether this invocation is calling an extension method using extension method syntax. + /// + public readonly bool IsExtensionMethodInvocation; + + /// + /// Gets whether this invocation is calling a delegate (without explicitly calling ".Invoke()"). + /// + public readonly bool IsDelegateInvocation; + + /// + /// Gets whether a params-Array is being used in its expanded form. + /// + public readonly bool IsExpandedForm; + + /// + /// Gets whether this is a lifted operator invocation. + /// + public readonly bool IsLiftedOperatorInvocation; + + readonly IList argumentToParameterMap; + + public CSharpInvocationResolveResult( + ResolveResult targetResult, IParameterizedMember member, IType returnType, + IList arguments, + OverloadResolutionErrors overloadResolutionErrors = OverloadResolutionErrors.None, + bool isExtensionMethodInvocation = false, + bool isExpandedForm = false, + bool isLiftedOperatorInvocation = false, + bool isDelegateInvocation = false, + IList argumentToParameterMap = null) + : base(targetResult, member, returnType, arguments) + { + this.OverloadResolutionErrors = overloadResolutionErrors; + this.IsExtensionMethodInvocation = isExtensionMethodInvocation; + this.IsExpandedForm = isExpandedForm; + this.IsLiftedOperatorInvocation = isLiftedOperatorInvocation; + this.IsDelegateInvocation = isDelegateInvocation; + this.argumentToParameterMap = argumentToParameterMap; + } + + public override bool IsError { + get { return this.OverloadResolutionErrors != OverloadResolutionErrors.None; } + } + + /// + /// Gets an array that maps argument indices to parameter indices. + /// For arguments that could not be mapped to any parameter, the value will be -1. + /// + /// parameterIndex = ArgumentToParameterMap[argumentIndex] + /// + public IList GetArgumentToParameterMap() + { + return argumentToParameterMap; + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs similarity index 62% rename from ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs index 31dbf0f86..1c17dac02 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/CSharpResolver.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CSharpResolver.cs @@ -1,15 +1,34 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using System.Threading; + +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.CSharp.Resolver { @@ -18,11 +37,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// public class CSharpResolver { - static readonly ResolveResult ErrorResult = new ErrorResolveResult(SharedTypes.UnknownType); + static readonly ResolveResult ErrorResult = ErrorResolveResult.UnknownError; static readonly ResolveResult DynamicResult = new ResolveResult(SharedTypes.Dynamic); static readonly ResolveResult NullResult = new ResolveResult(SharedTypes.Null); readonly ITypeResolveContext context; + internal readonly Conversions conversions; internal readonly CancellationToken cancellationToken; #region Constructor @@ -36,6 +56,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver throw new ArgumentNullException("context"); this.context = context; this.cancellationToken = cancellationToken; + this.conversions = Conversions.Get(context); } #endregion @@ -60,19 +81,92 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// setting one of the properties does not automatically set the other. public IMember CurrentMember { get; set; } + /// + /// Gets the current project content. + /// Returns CurrentUsingScope.ProjectContent. + /// + public IProjectContent ProjectContent { + get { + if (currentUsingScope != null) + return currentUsingScope.UsingScope.ProjectContent; + else + return null; + } + } + #endregion + + #region Per-CurrentTypeDefinition Cache + TypeDefinitionCache currentTypeDefinition; + /// /// Gets/Sets the current type definition that is used to look up identifiers as simple members. /// - public ITypeDefinition CurrentTypeDefinition { get; set; } + public ITypeDefinition CurrentTypeDefinition { + get { return currentTypeDefinition != null ? currentTypeDefinition.TypeDefinition : null; } + set { + if (value == null) { + currentTypeDefinition = null; + } else { + if (currentTypeDefinition == null || currentTypeDefinition.TypeDefinition != value) { + currentTypeDefinition = new TypeDefinitionCache(value); + } + } + } + } + + sealed class TypeDefinitionCache + { + public readonly ITypeDefinition TypeDefinition; + public readonly Dictionary SimpleNameLookupCacheExpression = new Dictionary(); + public readonly Dictionary SimpleNameLookupCacheInvocationTarget = new Dictionary(); + public readonly Dictionary SimpleTypeLookupCache = new Dictionary(); + + public TypeDefinitionCache(ITypeDefinition typeDefinition) + { + this.TypeDefinition = typeDefinition; + } + } + #endregion + + #region CurrentUsingScope + UsingScopeCache currentUsingScope; /// /// Gets/Sets the current using scope that is used to look up identifiers as class names. /// - public UsingScope UsingScope { get; set; } + public UsingScope CurrentUsingScope { + get { return currentUsingScope != null ? currentUsingScope.UsingScope : null; } + set { + if (value == null) { + currentUsingScope = null; + } else { + if (currentUsingScope == null || currentUsingScope.UsingScope != value) { + currentUsingScope = new UsingScopeCache(value); + } + } + } + } + + /// + /// There is one cache instance per using scope; and it might be shared between multiple resolvers + /// that are on different threads, so it must be thread-safe. + /// + sealed class UsingScopeCache + { + public readonly UsingScope UsingScope; + public readonly Dictionary ResolveCache = new Dictionary(); + + public List> AllExtensionMethods; + + public UsingScopeCache(UsingScope usingScope) + { + this.UsingScope = usingScope; + } + } #endregion #region Local Variable Management - sealed class LocalVariable : IVariable + class LocalVariable : IVariable { // We store the local variable in a linked list // and provide a stack-like API. @@ -96,21 +190,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.constantValue = constantValue; } - public string Name { + string IVariable.Name { get { return name; } } - public DomRegion DeclarationRegion { - get { return region; } + DomRegion IVariable.Region { + get { return region; } } - public ITypeReference Type { + ITypeReference IVariable.Type { get { return type; } } - public bool IsConst { + bool IVariable.IsConst { get { return constantValue != null; } } - public IConstantValue ConstantValue { + IConstantValue IVariable.ConstantValue { get { return constantValue; } } @@ -123,6 +217,51 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + sealed class LambdaParameter : LocalVariable, IParameter + { + readonly bool isRef; + readonly bool isOut; + + public LambdaParameter(LocalVariable prev, ITypeReference type, DomRegion region, string name, bool isRef, bool isOut) + : base(prev, type, region, name, null) + { + this.isRef = isRef; + this.isOut = isOut; + } + + IList IParameter.Attributes { + get { return EmptyList.Instance; } + } + + IConstantValue IParameter.DefaultValue { + get { return null; } + } + + bool IParameter.IsRef { + get { return isRef; } + } + + bool IParameter.IsOut { + get { return isOut; } + } + + bool IParameter.IsParams { + get { return false; } + } + + bool IParameter.IsOptional { + get { return false; } + } + + bool IFreezable.IsFrozen { + get { return true; } + } + + void IFreezable.Freeze() + { + } + } + LocalVariable localVariableStack; /// @@ -133,6 +272,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver localVariableStack = new LocalVariable(localVariableStack, null, DomRegion.Empty, null, null); } + /// + /// Opens a new scope for local variables. + /// This works like , but additionally sets to true. + /// + public void PushLambdaBlock() + { + localVariableStack = new LambdaParameter(localVariableStack, null, DomRegion.Empty, null, false, false); + } + /// /// Closes the current scope for local variables; removing all variables in that scope. /// @@ -160,7 +308,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } /// - /// Gets all currently visible local variables. + /// Adds a new lambda parameter to the current block. + /// + public IParameter AddLambdaParameter(ITypeReference type, DomRegion declarationRegion, string name, bool isRef = false, bool isOut = false) + { + if (type == null) + throw new ArgumentNullException("type"); + if (name == null) + throw new ArgumentNullException("name"); + LambdaParameter p = new LambdaParameter(localVariableStack, type, declarationRegion, name, isRef, isOut); + localVariableStack = p; + return p; + } + + /// + /// Gets all currently visible local variables and lambda parameters. /// public IEnumerable LocalVariables { get { @@ -170,6 +332,61 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } } + + /// + /// Gets whether the resolver is currently within a lambda expression. + /// + public bool IsWithinLambdaExpression { + get { + for (LocalVariable v = localVariableStack; v != null; v = v.prev) { + if (v.name == null && v is LambdaParameter) + return true; + } + return false; + } + } + #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 @@ -247,7 +464,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } IMember IMember.MemberDefinition { - get { return null; } + get { return this; } } IList IMember.InterfaceImplementations { @@ -310,7 +527,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { return true; } } - bool IEntity.IsPrivate { + bool IEntity.IsPrivate { get { return false; } } @@ -338,6 +555,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { throw new NotSupportedException(); } } + IParsedFile IEntity.ParsedFile { + get { return null; } + } + string INamedElement.FullName { get { return "operator"; } } @@ -375,8 +596,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { cancellationToken.ThrowIfCancellationRequested(); - if (expression.Type == SharedTypes.Dynamic) - return DynamicResult; + if (SharedTypes.Dynamic.Equals(expression.Type)) + return new UnaryOperatorResolveResult(SharedTypes.Dynamic, op, expression); // C# 4.0 spec: §7.3.3 Unary operator overload resolution string overloadableOperatorName = GetOverloadableOperatorName(op); @@ -385,11 +606,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver case UnaryOperatorType.Dereference: PointerType p = expression.Type as PointerType; if (p != null) - return new ResolveResult(p.ElementType); + return new UnaryOperatorResolveResult(p.ElementType, op, expression); else return ErrorResult; case UnaryOperatorType.AddressOf: - return new ResolveResult(new PointerType(expression.Type)); + return new UnaryOperatorResolveResult(new PointerType(expression.Type), op, expression); + case UnaryOperatorType.Await: + ResolveResult getAwaiterMethodGroup = ResolveMemberAccess(expression, "GetAwaiter", EmptyList.Instance, true); + ResolveResult getAwaiterInvocation = ResolveInvocation(getAwaiterMethodGroup, new ResolveResult[0]); + var getResultMethodGroup = CreateMemberLookup().Lookup(getAwaiterInvocation, "GetResult", EmptyList.Instance, true) as MethodGroupResolveResult; + if (getResultMethodGroup != null) { + var or = getResultMethodGroup.PerformOverloadResolution(context, new ResolveResult[0], allowExtensionMethods: false, conversions: conversions); + IType awaitResultType = or.GetBestCandidateWithSubstitutedTypeArguments().ReturnType.Resolve(context); + return new UnaryOperatorResolveResult(awaitResultType, UnaryOperatorType.Await, expression); + } else { + return new UnaryOperatorResolveResult(SharedTypes.UnknownType, UnaryOperatorType.Await, expression); + } default: throw new ArgumentException("Invalid value for UnaryOperatorType", "op"); } @@ -399,8 +631,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool isNullable = NullableType.IsNullable(expression.Type); // the operator is overloadable: - // TODO: implicit support for user operators - //var candidateSet = GetUnaryOperatorCandidates(); + OverloadResolution userDefinedOperatorOR = new OverloadResolution(context, new[] { expression }, conversions: conversions); + foreach (var candidate in GetUserDefinedOperatorCandidates(type, overloadableOperatorName)) { + userDefinedOperatorOR.AddCandidate(candidate); + } + if (userDefinedOperatorOR.FoundApplicableCandidate) { + return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR); + } expression = UnaryNumericPromotion(op, ref type, isNullable, expression); OperatorMethod[] methodGroup; @@ -412,8 +649,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // C# 4.0 spec: §7.6.9 Postfix increment and decrement operators // C# 4.0 spec: §7.7.5 Prefix increment and decrement operators TypeCode code = ReflectionHelper.GetTypeCode(type); - if ((code >= TypeCode.SByte && code <= TypeCode.Decimal) || type.IsEnum() || type is PointerType) - return new ResolveResult(expression.Type); + if ((code >= TypeCode.SByte && code <= TypeCode.Decimal) || type.Kind == TypeKind.Enum || type.Kind == TypeKind.Pointer) + return new UnaryOperatorResolveResult(expression.Type, op, expression); else return new ErrorResolveResult(expression.Type); case UnaryOperatorType.Plus: @@ -426,14 +663,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver methodGroup = logicalNegationOperator; break; case UnaryOperatorType.BitNot: - if (type.IsEnum()) { + if (type.Kind == TypeKind.Enum) { if (expression.IsCompileTimeConstant && !isNullable) { // evaluate as (E)(~(U)x); var U = expression.ConstantValue.GetType().ToTypeReference().Resolve(context); var unpackedEnum = new ConstantResolveResult(U, expression.ConstantValue); return CheckErrorAndResolveCast(expression.Type, ResolveUnaryOperator(op, unpackedEnum)); } else { - return new ResolveResult(expression.Type); + return new UnaryOperatorResolveResult(expression.Type, op, expression); } } else { methodGroup = bitwiseComplementOperators; @@ -442,14 +679,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver default: throw new InvalidOperationException(); } - OverloadResolution r = new OverloadResolution(context, new[] { expression }); + OverloadResolution builtinOperatorOR = new OverloadResolution(context, new[] { expression }, conversions: conversions); foreach (var candidate in methodGroup) { - r.AddCandidate(candidate); + builtinOperatorOR.AddCandidate(candidate); } - UnaryOperatorMethod m = (UnaryOperatorMethod)r.BestCandidate; + UnaryOperatorMethod m = (UnaryOperatorMethod)builtinOperatorOR.BestCandidate; IType resultType = m.ReturnType.Resolve(context); - if (r.BestCandidateErrors != OverloadResolutionErrors.None) { - return new ErrorResolveResult(resultType); + if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { + // If there are any user-defined operators, prefer those over the built-in operators. + // It'll be a more informative error. + if (userDefinedOperatorOR.BestCandidate != null) + return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR); + else + return new ErrorResolveResult(resultType); } else if (expression.IsCompileTimeConstant && !isNullable) { object val; try { @@ -459,7 +701,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } return new ConstantResolveResult(resultType, val); } else { - return new ResolveResult(resultType); + expression = Convert(expression, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]); + return new UnaryOperatorResolveResult(resultType, op, expression); } } #endregion @@ -469,24 +712,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { // C# 4.0 spec: §7.3.6.1 TypeCode code = ReflectionHelper.GetTypeCode(type); - if (isNullable && type == SharedTypes.Null) + if (isNullable && SharedTypes.Null.Equals(type)) code = TypeCode.SByte; // cause promotion of null to int32 switch (op) { case UnaryOperatorType.Minus: if (code == TypeCode.UInt32) { - IType targetType = KnownTypeReference.Int64.Resolve(context); - type = targetType; - if (isNullable) targetType = NullableType.Create(targetType, context); - return ResolveCast(targetType, expression); + type = KnownTypeReference.Int64.Resolve(context); + return Convert(expression, MakeNullable(type, isNullable), + isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } goto case UnaryOperatorType.Plus; case UnaryOperatorType.Plus: case UnaryOperatorType.BitNot: if (code >= TypeCode.Char && code <= TypeCode.UInt16) { - IType targetType = KnownTypeReference.Int32.Resolve(context); - type = targetType; - if (isNullable) targetType = NullableType.Create(targetType, context); - return ResolveCast(targetType, expression); + type = KnownTypeReference.Int32.Resolve(context); + return Convert(expression, MakeNullable(type, isNullable), + isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } break; } @@ -611,13 +852,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver new LambdaUnaryOperatorMethod(i => ~i) ); #endregion - - object GetUserUnaryOperatorCandidates() - { - // C# 4.0 spec: §7.3.5 Candidate user-defined operators - // TODO: implement user-defined operators - throw new NotImplementedException(); - } #endregion #region ResolveBinaryOperator @@ -626,8 +860,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { cancellationToken.ThrowIfCancellationRequested(); - if (lhs.Type == SharedTypes.Dynamic || rhs.Type == SharedTypes.Dynamic) - return DynamicResult; + if (SharedTypes.Dynamic.Equals(lhs.Type) || SharedTypes.Dynamic.Equals(rhs.Type)) { + lhs = Convert(lhs, SharedTypes.Dynamic); + rhs = Convert(rhs, SharedTypes.Dynamic); + return new BinaryOperatorResolveResult(SharedTypes.Dynamic, lhs, op, rhs); + } // C# 4.0 spec: §7.3.4 Binary operator overload resolution string overloadableOperatorName = GetOverloadableOperatorName(op); @@ -654,16 +891,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType lhsType = NullableType.GetUnderlyingType(lhs.Type); IType rhsType = NullableType.GetUnderlyingType(rhs.Type); - // TODO: find user-defined operators + // the operator is overloadable: + OverloadResolution userDefinedOperatorOR = new OverloadResolution(context, new[] { lhs, rhs }, conversions: conversions); + HashSet userOperatorCandidates = new HashSet(); + userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(lhsType, overloadableOperatorName)); + userOperatorCandidates.UnionWith(GetUserDefinedOperatorCandidates(rhsType, overloadableOperatorName)); + foreach (var candidate in userOperatorCandidates) { + userDefinedOperatorOR.AddCandidate(candidate); + } + if (userDefinedOperatorOR.FoundApplicableCandidate) { + return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR); + } - if (lhsType == SharedTypes.Null && rhsType.IsReferenceType(context) == false - || lhsType.IsReferenceType(context) == false && rhsType == SharedTypes.Null) + if (SharedTypes.Null.Equals(lhsType) && rhsType.IsReferenceType(context) == false + || lhsType.IsReferenceType(context) == false && SharedTypes.Null.Equals(rhsType)) { isNullable = true; } if (op == BinaryOperatorType.ShiftLeft || op == BinaryOperatorType.ShiftRight) { // special case: the shift operators allow "var x = null << null", producing int?. - if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null) + if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType)) isNullable = true; // for shift operators, do unary promotion independently on both arguments lhs = UnaryNumericPromotion(UnaryOperatorType.Plus, ref lhsType, isNullable, lhs); @@ -691,53 +938,91 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver case BinaryOperatorType.Add: methodGroup = CheckForOverflow ? checkedAdditionOperators : uncheckedAdditionOperators; { - Conversions conversions = new Conversions(context); - if (lhsType.IsEnum() && conversions.ImplicitConversion(rhsType, lhsType.GetEnumUnderlyingType(context))) { + if (lhsType.Kind == TypeKind.Enum) { // E operator +(E x, U y); - return HandleEnumAdditionOrSubtraction(isNullable, lhsType, op, lhs, rhs); - } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhsType, rhsType.GetEnumUnderlyingType(context))) { + IType underlyingType = MakeNullable(lhsType.GetEnumUnderlyingType(context), isNullable); + if (TryConvert(ref rhs, underlyingType)) { + return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); + } + } + if (rhsType.Kind == TypeKind.Enum) { // E operator +(U x, E y); - return ResolveBinaryOperator(op, rhs, lhs); // swap arguments + IType underlyingType = MakeNullable(rhsType.GetEnumUnderlyingType(context), isNullable); + if (TryConvert(ref lhs, underlyingType)) { + return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs); + } } - if (lhsType.IsDelegate() && conversions.ImplicitConversion(rhsType, lhsType)) { - return new ResolveResult(lhsType); - } else if (rhsType.IsDelegate() && conversions.ImplicitConversion(lhsType, rhsType)) { - return new ResolveResult(rhsType); + + if (lhsType.Kind == TypeKind.Delegate && TryConvert(ref rhs, lhsType)) { + return new BinaryOperatorResolveResult(lhsType, lhs, op, rhs); + } else if (rhsType.Kind == TypeKind.Delegate && TryConvert(ref lhs, rhsType)) { + return new BinaryOperatorResolveResult(rhsType, lhs, op, rhs); } - if (lhsType is PointerType && IsInteger(ReflectionHelper.GetTypeCode(rhsType))) { - return new ResolveResult(lhsType); - } else if (rhsType is PointerType && IsInteger(ReflectionHelper.GetTypeCode(lhsType))) { - return new ResolveResult(rhsType); + + if (lhsType is PointerType) { + methodGroup = new [] { + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int32), + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt32), + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int64), + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt64) + }; + } else if (rhsType is PointerType) { + methodGroup = new [] { + new PointerArithmeticOperator(rhsType, KnownTypeReference.Int32, rhsType), + new PointerArithmeticOperator(rhsType, KnownTypeReference.UInt32, rhsType), + new PointerArithmeticOperator(rhsType, KnownTypeReference.Int64, rhsType), + new PointerArithmeticOperator(rhsType, KnownTypeReference.UInt64, rhsType) + }; } - if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null) + if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType)) return new ErrorResolveResult(SharedTypes.Null); } break; case BinaryOperatorType.Subtract: methodGroup = CheckForOverflow ? checkedSubtractionOperators : uncheckedSubtractionOperators; { - Conversions conversions = new Conversions(context); - if (lhsType.IsEnum() && conversions.ImplicitConversion(rhsType, lhsType.GetEnumUnderlyingType(context))) { + if (lhsType.Kind == TypeKind.Enum) { // E operator –(E x, U y); - return HandleEnumAdditionOrSubtraction(isNullable, lhsType, op, lhs, rhs); - } else if (lhsType.IsEnum() && conversions.ImplicitConversion(rhs, lhs.Type)) { + IType underlyingType = MakeNullable(lhsType.GetEnumUnderlyingType(context), isNullable); + if (TryConvert(ref rhs, underlyingType)) { + return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); + } // U operator –(E x, E y); - return HandleEnumSubtraction(isNullable, lhsType, lhs, rhs); - } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhs, rhs.Type)) { + if (TryConvert(ref rhs, lhs.Type)) { + return HandleEnumSubtraction(isNullable, lhsType, lhs, rhs); + } + } + if (rhsType.Kind == TypeKind.Enum) { // U operator –(E x, E y); - return HandleEnumSubtraction(isNullable, lhsType, lhs, rhs); + if (TryConvert(ref lhs, rhs.Type)) { + return HandleEnumSubtraction(isNullable, rhsType, lhs, rhs); + } } - if (lhsType.IsDelegate() && conversions.ImplicitConversion(rhsType, lhsType)) { - return new ResolveResult(lhsType); - } else if (rhsType.IsDelegate() && conversions.ImplicitConversion(lhsType, rhsType)) { - return new ResolveResult(rhsType); + + if (lhsType.Kind == TypeKind.Delegate && TryConvert(ref rhs, lhsType)) { + return new BinaryOperatorResolveResult(lhsType, lhs, op, rhs); + } else if (rhsType.Kind == TypeKind.Delegate && TryConvert(ref lhs, rhsType)) { + return new BinaryOperatorResolveResult(rhsType, lhs, op, rhs); } - if (lhsType is PointerType && IsInteger(ReflectionHelper.GetTypeCode(rhsType))) { - return new ResolveResult(lhsType); - } else if (lhsType is PointerType && lhsType.Equals(rhsType)) { - return new ResolveResult(KnownTypeReference.Int64.Resolve(context)); + + if (lhsType is PointerType) { + if (rhsType is PointerType) { + IType int64 = KnownTypeReference.Int64.Resolve(context); + if (lhsType.Equals(rhsType)) { + return new BinaryOperatorResolveResult(int64, lhs, op, rhs); + } else { + return new ErrorResolveResult(int64); + } + } + methodGroup = new [] { + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int32), + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt32), + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.Int64), + new PointerArithmeticOperator(lhsType, lhsType, KnownTypeReference.UInt64) + }; } - if (lhsType == SharedTypes.Null && rhsType == SharedTypes.Null) + + if (SharedTypes.Null.Equals(lhsType) && SharedTypes.Null.Equals(rhsType)) return new ErrorResolveResult(SharedTypes.Null); } break; @@ -754,15 +1039,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver case BinaryOperatorType.LessThanOrEqual: case BinaryOperatorType.GreaterThanOrEqual: { - Conversions conversions = new Conversions(context); - if (lhsType.IsEnum() && conversions.ImplicitConversion(rhs, lhs.Type)) { + if (lhsType.Kind == TypeKind.Enum && TryConvert(ref rhs, lhs.Type)) { // bool operator op(E x, E y); return HandleEnumComparison(op, lhsType, isNullable, lhs, rhs); - } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhs, rhs.Type)) { + } else if (rhsType.Kind == TypeKind.Enum && TryConvert(ref lhs, rhs.Type)) { // bool operator op(E x, E y); return HandleEnumComparison(op, rhsType, isNullable, lhs, rhs); } else if (lhsType is PointerType && rhsType is PointerType) { - return new ResolveResult(KnownTypeReference.Boolean.Resolve(context)); + return new BinaryOperatorResolveResult(KnownTypeReference.Boolean.Resolve(context), lhs, op, rhs); } switch (op) { case BinaryOperatorType.Equality: @@ -792,14 +1076,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver case BinaryOperatorType.BitwiseOr: case BinaryOperatorType.ExclusiveOr: { - Conversions conversions = new Conversions(context); - if (lhsType.IsEnum() && conversions.ImplicitConversion(rhs, lhs.Type)) { - // E operator op(E x, E y); - return HandleEnumAdditionOrSubtraction(isNullable, lhsType, op, lhs, rhs); - } else if (rhsType.IsEnum() && conversions.ImplicitConversion(lhs, rhs.Type)) { - // E operator op(E x, E y); - return HandleEnumAdditionOrSubtraction(isNullable, rhsType, op, lhs, rhs); + if (lhsType.Kind == TypeKind.Enum && TryConvert(ref rhs, lhs.Type)) { + // bool operator op(E x, E y); + return HandleEnumOperator(isNullable, lhsType, op, lhs, rhs); + } else if (rhsType.Kind == TypeKind.Enum && TryConvert(ref lhs, rhs.Type)) { + // bool operator op(E x, E y); + return HandleEnumOperator(isNullable, rhsType, op, lhs, rhs); } + switch (op) { case BinaryOperatorType.BitwiseAnd: methodGroup = bitwiseAndOperators; @@ -824,14 +1108,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver default: throw new InvalidOperationException(); } - OverloadResolution r = new OverloadResolution(context, new[] { lhs, rhs }); + OverloadResolution builtinOperatorOR = new OverloadResolution(context, new[] { lhs, rhs }, conversions: conversions); foreach (var candidate in methodGroup) { - r.AddCandidate(candidate); + builtinOperatorOR.AddCandidate(candidate); } - BinaryOperatorMethod m = (BinaryOperatorMethod)r.BestCandidate; + BinaryOperatorMethod m = (BinaryOperatorMethod)builtinOperatorOR.BestCandidate; IType resultType = m.ReturnType.Resolve(context); - if (r.BestCandidateErrors != OverloadResolutionErrors.None) { - return new ErrorResolveResult(resultType); + if (builtinOperatorOR.BestCandidateErrors != OverloadResolutionErrors.None) { + // If there are any user-defined operators, prefer those over the built-in operators. + // It'll be a more informative error. + if (userDefinedOperatorOR.BestCandidate != null) + return CreateResolveResultForUserDefinedOperator(userDefinedOperatorOR); + else + return new ErrorResolveResult(resultType); } else if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && m.CanEvaluateAtCompileTime) { object val; try { @@ -841,7 +1130,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } return new ConstantResolveResult(resultType, val); } else { - return new ResolveResult(resultType); + lhs = Convert(lhs, m.Parameters[0].Type, builtinOperatorOR.ArgumentConversions[0]); + rhs = Convert(rhs, m.Parameters[1].Type, builtinOperatorOR.ArgumentConversions[1]); + return new BinaryOperatorResolveResult(resultType, lhs, op, rhs); } } #endregion @@ -864,7 +1155,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return rhs; return ResolveBinaryOperator(op, lhs, rhs); } - return new ResolveResult(KnownTypeReference.Boolean.Resolve(context)); + IType resultType = KnownTypeReference.Boolean.Resolve(context); + return new BinaryOperatorResolveResult(resultType, lhs, op, rhs); } /// @@ -884,19 +1176,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return rhs; return CheckErrorAndResolveCast(elementType, ResolveBinaryOperator(BinaryOperatorType.Subtract, lhs, rhs)); } - return new ResolveResult(isNullable ? NullableType.Create(elementType, context) : elementType); + IType resultType = MakeNullable(elementType, isNullable); + return new BinaryOperatorResolveResult(resultType, lhs, BinaryOperatorType.Subtract, rhs); } /// - /// Handle the case where an integral value is added to or subtracted from an enum value, - /// or when two enum values of the same type are combined using a bitwise operator. + /// Handle the following enum operators: /// E operator +(E x, U y); + /// E operator +(U x, E y); /// E operator –(E x, U y); /// E operator &(E x, E y); /// E operator |(E x, E y); /// E operator ^(E x, E y); /// - ResolveResult HandleEnumAdditionOrSubtraction(bool isNullable, IType enumType, BinaryOperatorType op, ResolveResult lhs, ResolveResult rhs) + ResolveResult HandleEnumOperator(bool isNullable, IType enumType, BinaryOperatorType op, ResolveResult lhs, ResolveResult rhs) { // evaluate as (E)((U)x op (U)y) if (lhs.IsCompileTimeConstant && rhs.IsCompileTimeConstant && !isNullable) { @@ -909,7 +1202,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return rhs; return CheckErrorAndResolveCast(enumType, ResolveBinaryOperator(op, lhs, rhs)); } - return new ResolveResult(isNullable ? NullableType.Create(enumType, context) : enumType); + IType resultType = MakeNullable(enumType, isNullable); + return new BinaryOperatorResolveResult(resultType, lhs, op, rhs); + } + + IType MakeNullable(IType type, bool isNullable) + { + if (isNullable) + return NullableType.Create(type, context); + else + return type; } #endregion @@ -920,10 +1222,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver TypeCode lhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(lhs.Type)); TypeCode rhsCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(rhs.Type)); // if one of the inputs is the null literal, promote that to the type of the other operand - if (isNullable && lhs.Type == SharedTypes.Null) { + if (isNullable && SharedTypes.Null.Equals(lhs.Type)) { lhs = CastTo(rhsCode, isNullable, lhs, allowNullableConstants); lhsCode = rhsCode; - } else if (isNullable && rhs.Type == SharedTypes.Null) { + } else if (isNullable && SharedTypes.Null.Equals(rhs.Type)) { rhs = CastTo(lhsCode, isNullable, rhs, allowNullableConstants); rhsCode = lhsCode; } @@ -981,15 +1283,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } - static bool IsInteger(TypeCode code) - { - return code >= TypeCode.SByte && code <= TypeCode.UInt64; - } - ResolveResult CastTo(TypeCode targetType, bool isNullable, ResolveResult expression, bool allowNullableConstants) { IType elementType = targetType.ToTypeReference().Resolve(context); - IType nullableType = isNullable ? NullableType.Create(elementType, context) : elementType; + IType nullableType = MakeNullable(elementType, isNullable); + if (nullableType.Equals(expression.Type)) + return expression; if (allowNullableConstants && expression.IsCompileTimeConstant) { if (expression.ConstantValue == null) return new ConstantResolveResult(nullableType, null); @@ -999,7 +1298,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Debug.Assert(rr.IsCompileTimeConstant); return new ConstantResolveResult(nullableType, rr.ConstantValue); } else { - return ResolveCast(nullableType, expression); + return Convert(expression, nullableType, + isNullable ? Conversion.ImplicitNullableConversion : Conversion.ImplicitNumericConversion); } } #endregion @@ -1053,6 +1353,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public abstract object Invoke(CSharpResolver resolver, object lhs, object rhs); } + sealed class PointerArithmeticOperator : BinaryOperatorMethod + { + public PointerArithmeticOperator(ITypeReference returnType, ITypeReference parameter1, ITypeReference parameter2) + { + this.ReturnType = returnType; + this.Parameters.Add(new DefaultParameter(parameter1, "x")); + this.Parameters.Add(new DefaultParameter(parameter2, "y")); + } + + public override bool CanEvaluateAtCompileTime { + get { return false; } + } + + public override object Invoke(CSharpResolver resolver, object lhs, object rhs) + { + throw new NotSupportedException(); + } + } + sealed class LambdaBinaryOperatorMethod : BinaryOperatorMethod { readonly Func func; @@ -1443,30 +1762,138 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #region Null coalescing operator ResolveResult ResolveNullCoalescingOperator(ResolveResult lhs, ResolveResult rhs) { - Conversions conversions = new Conversions(context); if (NullableType.IsNullable(lhs.Type)) { IType a0 = NullableType.GetUnderlyingType(lhs.Type); - if (conversions.ImplicitConversion(rhs, a0)) - return new ResolveResult(a0); + if (TryConvert(ref rhs, a0)) { + return new BinaryOperatorResolveResult(a0, lhs, BinaryOperatorType.NullCoalescing, rhs); + } } - if (conversions.ImplicitConversion(rhs, lhs.Type)) - return new ResolveResult(lhs.Type); - if (conversions.ImplicitConversion(lhs, rhs.Type)) - return new ResolveResult(rhs.Type); - else + if (TryConvert(ref rhs, lhs.Type)) { + return new BinaryOperatorResolveResult(lhs.Type, lhs, BinaryOperatorType.NullCoalescing, rhs); + } + if (TryConvert(ref lhs, rhs.Type)) { + return new BinaryOperatorResolveResult(rhs.Type, lhs, BinaryOperatorType.NullCoalescing, rhs); + } else { return new ErrorResolveResult(lhs.Type); + } } #endregion + #endregion - object GetUserBinaryOperatorCandidates() + #region Get user-defined operator candidates + IEnumerable GetUserDefinedOperatorCandidates(IType type, string operatorName) { + if (operatorName == null) + return EmptyList.Instance; + TypeCode c = ReflectionHelper.GetTypeCode(type); + if (TypeCode.Boolean <= c && c <= TypeCode.Decimal || c == TypeCode.String) { + // The .NET framework contains some of C#'s built-in operators as user-defined operators. + // However, we must not use those as user-defined operators (we would skip numeric promotion). + return EmptyList.Instance; + } // C# 4.0 spec: §7.3.5 Candidate user-defined operators - // TODO: implement user-defined operators - throw new NotImplementedException(); + var operators = type.GetMethods(context, m => m.IsOperator && m.Name == operatorName).ToList(); + LiftUserDefinedOperators(operators); + return operators; + } + + void LiftUserDefinedOperators(List operators) + { + int nonLiftedMethodCount = operators.Count; + // Construct lifted operators + for (int i = 0; i < nonLiftedMethodCount; i++) { + var liftedMethod = LiftUserDefinedOperator(operators[i]); + if (liftedMethod != null) + operators.Add(liftedMethod); + } + } + + LiftedUserDefinedOperator LiftUserDefinedOperator(IParameterizedMember m) + { + IType returnType = m.ReturnType.Resolve(context); + if (!NullableType.IsNonNullableValueType(returnType, context)) + return null; // cannot lift this operator + LiftedUserDefinedOperator liftedOperator = new LiftedUserDefinedOperator(m); + for (int i = 0; i < m.Parameters.Count; i++) { + IType parameterType = m.Parameters[i].Type.Resolve(context); + if (!NullableType.IsNonNullableValueType(parameterType, context)) + return null; // cannot lift this operator + var p = new DefaultParameter(m.Parameters[i]); + p.Type = NullableType.Create(parameterType, context); + liftedOperator.Parameters.Add(p); + } + liftedOperator.ReturnType = NullableType.Create(returnType, context); + return liftedOperator; + } + + sealed class LiftedUserDefinedOperator : OperatorMethod, OverloadResolution.ILiftedOperator + { + internal readonly IParameterizedMember nonLiftedOperator; + + public LiftedUserDefinedOperator(IParameterizedMember nonLiftedMethod) + { + this.nonLiftedOperator = nonLiftedMethod; + } + + public IList NonLiftedParameters { + get { return nonLiftedOperator.Parameters; } + } + + public override bool Equals(object obj) + { + LiftedUserDefinedOperator op = obj as LiftedUserDefinedOperator; + return op != null && this.nonLiftedOperator.Equals(op.nonLiftedOperator); + } + + public override int GetHashCode() + { + return nonLiftedOperator.GetHashCode() ^ 0x7191254; + } + } + + ResolveResult CreateResolveResultForUserDefinedOperator(OverloadResolution r) + { + LiftedUserDefinedOperator lifted = r.BestCandidate as LiftedUserDefinedOperator; + if (lifted != null) { + return new CSharpInvocationResolveResult( + null, lifted.nonLiftedOperator, lifted.ReturnType.Resolve(context), + r.GetArgumentsWithConversions(), r.BestCandidateErrors, + isLiftedOperatorInvocation: true, + argumentToParameterMap: r.GetArgumentToParameterMap() + ); + } else { + return r.CreateResolveResult(null); + } } #endregion #region ResolveCast + bool TryConvert(ref ResolveResult rr, IType targetType) + { + Conversion c = conversions.ImplicitConversion(rr, targetType); + if (c) { + rr = Convert(rr, targetType, c); + return true; + } else { + return false; + } + } + + ResolveResult Convert(ResolveResult rr, IType targetType) + { + return Convert(rr, targetType, conversions.ImplicitConversion(rr, targetType)); + } + + ResolveResult Convert(ResolveResult rr, ITypeReference targetType, Conversion c) + { + if (c == Conversion.IdentityConversion) + return rr; + else if (rr.IsCompileTimeConstant && c != Conversion.None) + return ResolveCast(targetType.Resolve(context), rr); + else + return new ConversionResolveResult(targetType.Resolve(context), rr, c); + } + public ResolveResult ResolveCast(IType targetType, ResolveResult expression) { cancellationToken.ThrowIfCancellationRequested(); @@ -1485,7 +1912,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return new ConstantResolveResult(targetType, expression.ConstantValue); else return new ErrorResolveResult(targetType); - } else if (targetType.IsEnum()) { + } else if (targetType.Kind == TypeKind.Enum) { code = ReflectionHelper.GetTypeCode(targetType.GetEnumUnderlyingType(context)); if (code >= TypeCode.SByte && code <= TypeCode.UInt64 && expression.ConstantValue != null) { try { @@ -1496,7 +1923,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } } - return new ResolveResult(targetType); + Conversion c = conversions.ExplicitConversion(expression, targetType); + if (c) { + return new ConversionResolveResult(targetType, expression, c); + } else { + return new ErrorResolveResult(targetType); + } } object CSharpPrimitiveCast(TypeCode targetType, object input) @@ -1514,66 +1946,49 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region ResolveSimpleName - enum SimpleNameLookupMode - { - Expression, - InvocationTarget, - Type, - TypeInUsingDeclaration - } - public ResolveResult ResolveSimpleName(string identifier, IList typeArguments, bool isInvocationTarget = false) { // C# 4.0 spec: §7.6.2 Simple Names - if (identifier == null) - throw new ArgumentNullException("identifier"); - if (typeArguments == null) - throw new ArgumentNullException("typeArguments"); - - if (typeArguments.Count == 0) { - foreach (IVariable v in this.LocalVariables) { - if (v.Name == identifier) { - object constantValue = v.IsConst ? v.ConstantValue.GetValue(context) : null; - return new LocalResolveResult(v, v.Type.Resolve(context), constantValue); - } - } - IParameterizedMember parameterizedMember = this.CurrentMember as IParameterizedMember; - if (parameterizedMember != null) { - foreach (IParameter p in parameterizedMember.Parameters) { - if (p.Name == identifier) { - return new LocalResolveResult(p, p.Type.Resolve(context)); - } - } - } - } - return LookupSimpleNameOrTypeName( identifier, typeArguments, isInvocationTarget ? SimpleNameLookupMode.InvocationTarget : SimpleNameLookupMode.Expression); } - public ResolveResult LookupSimpleNamespaceOrTypeName(string identifier, IList typeArguments, bool isUsingDeclaration = false) + public ResolveResult LookupSimpleNameOrTypeName(string identifier, IList typeArguments, SimpleNameLookupMode lookupMode) { + // C# 4.0 spec: §3.8 Namespace and type names; §7.6.2 Simple Names + if (identifier == null) throw new ArgumentNullException("identifier"); if (typeArguments == null) throw new ArgumentNullException("typeArguments"); - return LookupSimpleNameOrTypeName(identifier, typeArguments, - isUsingDeclaration ? SimpleNameLookupMode.TypeInUsingDeclaration : SimpleNameLookupMode.Type); - } - - ResolveResult LookupSimpleNameOrTypeName(string identifier, IList typeArguments, SimpleNameLookupMode lookupMode) - { - // C# 4.0 spec: §3.8 Namespace and type names; §7.6.2 Simple Names - cancellationToken.ThrowIfCancellationRequested(); int k = typeArguments.Count; - // look in type parameters of current method if (k == 0) { + if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) { + // Look in local variables + foreach (IVariable v in this.LocalVariables) { + if (v.Name == identifier) { + object constantValue = v.IsConst ? v.ConstantValue.Resolve(context).ConstantValue : null; + return new LocalResolveResult(v, v.Type.Resolve(context), constantValue); + } + } + // Look in parameters of current method + IParameterizedMember parameterizedMember = this.CurrentMember as IParameterizedMember; + if (parameterizedMember != null) { + foreach (IParameter p in parameterizedMember.Parameters) { + if (p.Name == identifier) { + return new LocalResolveResult(p, p.Type.Resolve(context)); + } + } + } + } + + // look in type parameters of current method IMethod m = this.CurrentMember as IMethod; if (m != null) { foreach (ITypeParameter tp in m.TypeParameters) { @@ -1583,6 +1998,67 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + bool parameterizeResultType = k > 0; + if (parameterizeResultType && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument)) + parameterizeResultType = false; + + ResolveResult r = null; + if (currentTypeDefinition != null) { + Dictionary cache = null; + bool foundInCache = false; + if (k == 0) { + switch (lookupMode) { + case SimpleNameLookupMode.Expression: + cache = currentTypeDefinition.SimpleNameLookupCacheExpression; + break; + case SimpleNameLookupMode.InvocationTarget: + cache = currentTypeDefinition.SimpleNameLookupCacheInvocationTarget; + break; + case SimpleNameLookupMode.Type: + cache = currentTypeDefinition.SimpleTypeLookupCache; + break; + } + if (cache != null) { + foundInCache = cache.TryGetValue(identifier, out r); + } + } + if (!foundInCache) { + r = LookInCurrentType(identifier, typeArguments, lookupMode, parameterizeResultType); + if (cache != null) { + // also cache missing members (r==null) + cache[identifier] = r; + } + } + if (r != null) + return r; + } + + if (currentUsingScope != null) { + if (k == 0 && lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration) { + if (!currentUsingScope.ResolveCache.TryGetValue(identifier, out r)) { + r = LookInCurrentUsingScope(identifier, typeArguments, false, false); + currentUsingScope.ResolveCache[identifier] = r; + } + } else { + r = LookInCurrentUsingScope(identifier, typeArguments, lookupMode == SimpleNameLookupMode.TypeInUsingDeclaration, parameterizeResultType); + } + if (r != null) + return r; + } + + if (typeArguments.Count == 0) { + if (identifier == "dynamic") + return new TypeResolveResult(SharedTypes.Dynamic); + else + return new UnknownIdentifierResolveResult(identifier); + } else { + return ErrorResult; + } + } + + ResolveResult LookInCurrentType(string identifier, IList typeArguments, SimpleNameLookupMode lookupMode, bool parameterizeResultType) + { + int k = typeArguments.Count; // look in current type definitions for (ITypeDefinition t = this.CurrentTypeDefinition; t != null; t = t.DeclaringTypeDefinition) { if (k == 0) { @@ -1595,18 +2071,30 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + if (lookupMode == SimpleNameLookupMode.BaseTypeReference && t == this.CurrentTypeDefinition) { + // don't look in current type when resolving a base type reference + continue; + } + MemberLookup lookup = new MemberLookup(context, t, t.ProjectContent); ResolveResult r; if (lookupMode == SimpleNameLookupMode.Expression || lookupMode == SimpleNameLookupMode.InvocationTarget) { - r = lookup.Lookup(t, identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget); + r = lookup.Lookup(new TypeResolveResult(t), identifier, typeArguments, lookupMode == SimpleNameLookupMode.InvocationTarget); } else { - r = lookup.LookupType(t, identifier, typeArguments); + r = lookup.LookupType(t, identifier, typeArguments, parameterizeResultType); } if (!(r is UnknownMemberResolveResult)) // but do return AmbiguousMemberResolveResult return r; } + return null; + } + + ResolveResult LookInCurrentUsingScope(string identifier, IList typeArguments, bool isInUsingDeclaration, bool parameterizeResultType) + { + int k = typeArguments.Count; // look in current namespace definitions - for (UsingScope n = this.UsingScope; n != null; n = n.Parent) { + UsingScope currentUsingScope = this.CurrentUsingScope; + for (UsingScope n = currentUsingScope; n != null; n = n.Parent) { // first look for a namespace if (k == 0) { string fullName = NamespaceDeclaration.BuildQualifiedName(n.NamespaceName, identifier); @@ -1620,7 +2108,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ITypeDefinition def = context.GetTypeDefinition(n.NamespaceName, identifier, k, StringComparer.Ordinal); if (def != null) { IType result = def; - if (k != 0) { + if (parameterizeResultType) { result = new ParameterizedType(def, typeArguments); } if (n.HasAlias(identifier)) @@ -1633,7 +2121,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (n.ExternAliases.Contains(identifier)) { return ResolveExternAlias(identifier); } - if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.UsingScope) { + if (!(isInUsingDeclaration && n == currentUsingScope)) { foreach (var pair in n.UsingAliases) { if (pair.Key == identifier) { NamespaceResolveResult ns = pair.Value.ResolveNamespace(context); @@ -1646,7 +2134,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } // finally, look in the imported namespaces: - if (lookupMode != SimpleNameLookupMode.TypeInUsingDeclaration || n != this.UsingScope) { + if (!(isInUsingDeclaration && n == currentUsingScope)) { IType firstResult = null; foreach (var u in n.Usings) { NamespaceResolveResult ns = u.ResolveNamespace(context); @@ -1654,10 +2142,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver def = context.GetTypeDefinition(ns.NamespaceName, identifier, k, StringComparer.Ordinal); if (def != null) { if (firstResult == null) { - if (k == 0) - firstResult = def; - else + if (parameterizeResultType) firstResult = new ParameterizedType(def, typeArguments); + else + firstResult = def; } else { return new AmbiguousTypeResolveResult(firstResult); } @@ -1669,14 +2157,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } // if we didn't find anything: repeat lookup with parent namespace } - if (typeArguments.Count == 0) { - if (identifier == "dynamic") - return new TypeResolveResult(SharedTypes.Dynamic); - else - return new UnknownIdentifierResolveResult(identifier); - } else { - return ErrorResult; - } + return null; } /// @@ -1687,7 +2168,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (identifier == "global") return new NamespaceResolveResult(string.Empty); - for (UsingScope n = this.UsingScope; n != null; n = n.Parent) { + for (UsingScope n = this.CurrentUsingScope; n != null; n = n.Parent) { if (n.ExternAliases.Contains(identifier)) { return ResolveExternAlias(identifier); } @@ -1700,7 +2181,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return ErrorResult; } - ResolveResult ResolveExternAlias(string alias) + static ResolveResult ResolveExternAlias(string alias) { // TODO: implement extern alias support return new NamespaceResolveResult(string.Empty); @@ -1716,51 +2197,121 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver NamespaceResolveResult nrr = target as NamespaceResolveResult; if (nrr != null) { - if (typeArguments.Count == 0) { - string fullName = NamespaceDeclaration.BuildQualifiedName(nrr.NamespaceName, identifier); - if (context.GetNamespace(fullName, StringComparer.Ordinal) != null) - return new NamespaceResolveResult(fullName); - } - ITypeDefinition def = context.GetTypeDefinition(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal); - if (def != null) - return new TypeResolveResult(def); - return ErrorResult; + return ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments, typeArguments.Count > 0); } - if (target.Type == SharedTypes.Dynamic) + if (SharedTypes.Dynamic.Equals(target.Type)) return DynamicResult; MemberLookup lookup = CreateMemberLookup(); - ResolveResult result = lookup.Lookup(target.Type, identifier, typeArguments, isInvocationTarget); + ResolveResult result = lookup.Lookup(target, identifier, typeArguments, isInvocationTarget); if (result is UnknownMemberResolveResult) { - var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments.Count); + var extensionMethods = GetExtensionMethods(target.Type, identifier, typeArguments); if (extensionMethods.Count > 0) { - return new MethodGroupResolveResult(target.Type, identifier, EmptyList.Instance, typeArguments) { - ExtensionMethods = extensionMethods + return new MethodGroupResolveResult(target, identifier, EmptyList.Instance, typeArguments) { + extensionMethods = extensionMethods }; } + } else { + MethodGroupResolveResult mgrr = result as MethodGroupResolveResult; + if (mgrr != null) { + Debug.Assert(mgrr.extensionMethods == null); + // set the values that are necessary to make MethodGroupResolveResult.GetExtensionMethods() work + mgrr.usingScope = this.CurrentUsingScope; + mgrr.resolver = this; + } } return result; } - MemberLookup CreateMemberLookup() + public ResolveResult ResolveMemberType(ResolveResult target, string identifier, IList typeArguments) + { + cancellationToken.ThrowIfCancellationRequested(); + + bool parameterizeResultType = typeArguments.Count > 0; + if (parameterizeResultType && typeArguments.All(t => t.Kind == TypeKind.UnboundTypeArgument)) + parameterizeResultType = false; + + NamespaceResolveResult nrr = target as NamespaceResolveResult; + if (nrr != null) { + return ResolveMemberAccessOnNamespace(nrr, identifier, typeArguments, parameterizeResultType); + } + + MemberLookup lookup = CreateMemberLookup(); + return lookup.LookupType(target.Type, identifier, typeArguments, parameterizeResultType); + } + + ResolveResult ResolveMemberAccessOnNamespace(NamespaceResolveResult nrr, string identifier, IList typeArguments, bool parameterizeResultType) + { + if (typeArguments.Count == 0) { + string fullName = NamespaceDeclaration.BuildQualifiedName(nrr.NamespaceName, identifier); + if (context.GetNamespace(fullName, StringComparer.Ordinal) != null) + return new NamespaceResolveResult(fullName); + } + ITypeDefinition def = context.GetTypeDefinition(nrr.NamespaceName, identifier, typeArguments.Count, StringComparer.Ordinal); + if (def != null) { + if (parameterizeResultType) + return new TypeResolveResult(new ParameterizedType(def, typeArguments)); + else + return new TypeResolveResult(def); + } + return ErrorResult; + } + + /// + /// Creates a MemberLookup instance using this resolver's settings. + /// + public MemberLookup CreateMemberLookup() + { + return new MemberLookup(context, this.CurrentTypeDefinition, this.ProjectContent); + } + #endregion + + #region ResolveIdentifierInObjectInitializer + public ResolveResult ResolveIdentifierInObjectInitializer(string identifier) { - return new MemberLookup(context, this.CurrentTypeDefinition, this.UsingScope != null ? this.UsingScope.ProjectContent : null); + 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', and can be called with 'typeArgumentCount' explicit type arguments; + /// Gets the extension methods that are called 'name' /// and are applicable with a first argument type of 'targetType'. /// - List> GetExtensionMethods(IType targetType, string name, int typeArgumentCount) + /// Type of the 'this' argument + /// Name of the extension method + /// Explicitly provided type arguments. + /// An empty list will return all matching extension method definitions; + /// a non-empty list will return s for all extension methods + /// with the matching number of type parameters. + /// + /// The results are stored in nested lists because they are grouped by using scope. + /// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }", + /// the return value will be + /// new List { + /// new List { all extensions from MoreExtensions }, + /// new List { all extensions from SomeExtensions } + /// } + /// + public List> GetExtensionMethods(IType targetType, string name, IList typeArguments = null) { List> extensionMethodGroups = new List>(); foreach (var inputGroup in GetAllExtensionMethods()) { List outputGroup = new List(); foreach (var method in inputGroup) { - if (method.Name == name && (typeArgumentCount == 0 || method.TypeParameters.Count == typeArgumentCount)) { + if (method.Name != name) + continue; + + if (typeArguments != null && typeArguments.Count > 0) { + if (method.TypeParameters.Count != typeArguments.Count) + continue; + SpecializedMethod sm = new SpecializedMethod(method.DeclaringType, method, typeArguments); + // TODO: verify targetType + outputGroup.Add(sm); + } else { // TODO: verify targetType outputGroup.Add(method); } @@ -1771,12 +2322,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return extensionMethodGroups; } - List> GetAllExtensionMethods() + /// + /// Gets all extension methods available in the current using scope. + /// This list includes unaccessible + /// + IList> GetAllExtensionMethods() { - // TODO: maybe cache the result? - List> extensionMethodGroups = new List>(); + if (currentUsingScope == null) + return EmptyList>.Instance; + List> extensionMethodGroups = currentUsingScope.AllExtensionMethods; + if (extensionMethodGroups != null) + return extensionMethodGroups; + extensionMethodGroups = new List>(); List m; - for (UsingScope scope = this.UsingScope; scope != null; scope = scope.Parent) { + for (UsingScope scope = currentUsingScope.UsingScope; scope != null; scope = scope.Parent) { m = GetExtensionMethods(scope.NamespaceName).ToList(); if (m.Count > 0) extensionMethodGroups.Add(m); @@ -1790,6 +2349,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (m.Count > 0) extensionMethodGroups.Add(m); } + currentUsingScope.AllExtensionMethods = extensionMethodGroups; return extensionMethodGroups; } @@ -1797,7 +2357,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { return from c in context.GetTypes(namespaceName, StringComparer.Ordinal) - where c.IsStatic && c.HasExtensionMethods + where c.IsStatic && c.HasExtensionMethods && c.TypeParameters.Count == 0 from m in c.Methods where m.IsExtensionMethod select m; @@ -1805,63 +2365,32 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region ResolveInvocation + /// + /// Resolves an invocation. + /// + /// The target of the invocation. Usually a MethodGroupResolveResult. + /// + /// Arguments passed to the method. + /// The resolver may mutate this array to wrap elements in s! + /// + /// + /// The argument names. Pass the null string for positional arguments. + /// + /// InvocationResolveResult or UnknownMethodResolveResult public ResolveResult ResolveInvocation(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null) { // C# 4.0 spec: §7.6.5 cancellationToken.ThrowIfCancellationRequested(); - if (target.Type == SharedTypes.Dynamic) + if (SharedTypes.Dynamic.Equals(target.Type)) return DynamicResult; MethodGroupResolveResult mgrr = target as MethodGroupResolveResult; if (mgrr != null) { - var typeArgumentArray = mgrr.TypeArguments.ToArray(); - OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, typeArgumentArray); - foreach (IMethod method in mgrr.Methods) { - // TODO: grouping by class definition? - or.AddCandidate(method); - } - if (!or.FoundApplicableCandidate) { - // No applicable match found, so let's try extension methods. - - var extensionMethods = mgrr.ExtensionMethods; - // Look in extension methods pre-calcalculated by ResolveMemberAccess if possible; - // otherwise call GetExtensionMethods(). - if (extensionMethods == null) - extensionMethods = GetExtensionMethods(mgrr.TargetType, mgrr.MethodName, mgrr.TypeArguments.Count); - - if (extensionMethods.Count > 0) { - ResolveResult[] extArguments = new ResolveResult[arguments.Length + 1]; - extArguments[0] = new ResolveResult(mgrr.TargetType); - arguments.CopyTo(extArguments, 1); - string[] extArgumentNames = null; - if (argumentNames != null) { - extArgumentNames = new string[argumentNames.Length + 1]; - argumentNames.CopyTo(extArgumentNames, 1); - } - var extOr = new OverloadResolution(context, extArguments, extArgumentNames, typeArgumentArray); - - foreach (var g in extensionMethods) { - foreach (var m in g) { - extOr.AddCandidate(m); - } - if (extOr.FoundApplicableCandidate) - break; - } - // For the lack of a better comparison function (the one within OverloadResolution - // cannot be used as it depends on the argument set): - if (extOr.FoundApplicableCandidate || or.BestCandidate == null) { - // Consider an extension method result better than the normal result only - // if it's applicable; or if there is no normal result. - or = extOr; - } - } - } + OverloadResolution or = mgrr.PerformOverloadResolution(context, arguments, argumentNames, conversions: conversions); if (or.BestCandidate != null) { - IType returnType = or.BestCandidate.ReturnType.Resolve(context); - returnType = returnType.AcceptVisitor(new MethodTypeParameterSubstitution(or.InferredTypeArguments)); - return new MemberResolveResult(or.BestCandidate, returnType); + return or.CreateResolveResult(mgrr.TargetResult); } else { // No candidate found at all (not even an inapplicable one). // This can happen with empty method groups (as sometimes used with extension methods) @@ -1879,7 +2408,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } IMethod invokeMethod = target.Type.GetDelegateInvokeMethod(); if (invokeMethod != null) { - return new ResolveResult(invokeMethod.ReturnType.Resolve(context)); + OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, conversions: conversions); + or.AddCandidate(invokeMethod); + return new CSharpInvocationResolveResult( + target, invokeMethod, invokeMethod.ReturnType.Resolve(context), + or.GetArgumentsWithConversions(), or.BestCandidateErrors, + isExpandedForm: or.BestCandidateIsExpandedForm, + isDelegateInvocation: true, + argumentToParameterMap: or.GetArgumentToParameterMap()); } return ErrorResult; } @@ -1921,7 +2457,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { // argument might be a lambda or delegate type, so we have to try to guess the delegate type IType type = arguments[i].Type; - if (type == SharedTypes.Null || type == SharedTypes.UnknownType) { + if (SharedTypes.Null.Equals(type) || SharedTypes.UnknownType.Equals(type)) { list.Add(new DefaultParameter(KnownTypeReference.Object, argumentNames[i])); } else { list.Add(new DefaultParameter(type, argumentNames[i])); @@ -1942,8 +2478,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return umrr.MemberName; MethodGroupResolveResult mgrr = rr as MethodGroupResolveResult; - if (mgrr != null && mgrr.Methods.Count > 0) - return mgrr.Methods[0].Name; + if (mgrr != null) + return mgrr.MethodName; LocalResolveResult vrr = rr as LocalResolveResult; if (vrr != null) @@ -1967,36 +2503,87 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #endregion #region ResolveIndexer + /// + /// Resolves an indexer access. + /// + /// Target expression. + /// + /// Arguments passed to the indexer. + /// The resolver may mutate this array to wrap elements in s! + /// + /// + /// The argument names. Pass the null string for positional arguments. + /// + /// ArrayAccessResolveResult, InvocationResolveResult, or ErrorResolveResult public ResolveResult ResolveIndexer(ResolveResult target, ResolveResult[] arguments, string[] argumentNames = null) { cancellationToken.ThrowIfCancellationRequested(); - if (target.Type == SharedTypes.Dynamic) - return DynamicResult; + switch (target.Type.Kind) { + case TypeKind.Dynamic: + for (int i = 0; i < arguments.Length; i++) { + arguments[i] = Convert(arguments[i], SharedTypes.Dynamic); + } + return new ArrayAccessResolveResult(SharedTypes.Dynamic, target, arguments); + + case TypeKind.Array: + case TypeKind.Pointer: + // §7.6.6.1 Array access / §18.5.3 Pointer element access + AdjustArrayAccessArguments(arguments); + return new ArrayAccessResolveResult(((TypeWithElementType)target.Type).ElementType, target, arguments); + } - OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, new IType[0]); + // §7.6.6.2 Indexer access + OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, conversions: conversions); MemberLookup lookup = CreateMemberLookup(); - bool allowProtectedAccess = lookup.IsProtectedAccessAllowed(target.Type); - var indexers = target.Type.GetProperties(context, p => p.IsIndexer && lookup.IsAccessible(p, allowProtectedAccess)); - // TODO: filter indexers hiding other indexers? - foreach (IProperty p in indexers) { - // TODO: grouping by class definition? - or.AddCandidate(p); - } + var indexers = lookup.LookupIndexers(target.Type); + or.AddMethodLists(indexers); if (or.BestCandidate != null) { - return new MemberResolveResult(or.BestCandidate, or.BestCandidate.ReturnType.Resolve(context)); + return or.CreateResolveResult(target); } else { return ErrorResult; } } + + /// + /// Converts all arguments to int,uint,long or ulong. + /// + void AdjustArrayAccessArguments(ResolveResult[] arguments) + { + for (int i = 0; i < arguments.Length; i++) { + if (!(TryConvert(ref arguments[i], KnownTypeReference.Int32.Resolve(context)) || + TryConvert(ref arguments[i], KnownTypeReference.UInt32.Resolve(context)) || + TryConvert(ref arguments[i], KnownTypeReference.Int64.Resolve(context)) || + TryConvert(ref arguments[i], KnownTypeReference.UInt64.Resolve(context)))) + { + // conversion failed + arguments[i] = Convert(arguments[i], KnownTypeReference.Int32, Conversion.None); + } + } + } #endregion #region ResolveObjectCreation + /// + /// Resolves an object creation. + /// + /// Type of the object to create. + /// + /// Arguments passed to the constructor. + /// The resolver may mutate this array to wrap elements in s! + /// + /// + /// The argument names. Pass the null string for positional arguments. + /// + /// InvocationResolveResult or ErrorResolveResult public ResolveResult ResolveObjectCreation(IType type, ResolveResult[] arguments, string[] argumentNames = null) { cancellationToken.ThrowIfCancellationRequested(); - OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, new IType[0]); + if (type.Kind == TypeKind.Delegate && arguments.Length == 1) { + return Convert(arguments[0], type); + } + OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, conversions: conversions); MemberLookup lookup = CreateMemberLookup(); bool allowProtectedAccess = lookup.IsProtectedAccessAllowed(type); var constructors = type.GetConstructors(context, m => lookup.IsAccessible(m, allowProtectedAccess)); @@ -2004,7 +2591,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver or.AddCandidate(ctor); } if (or.BestCandidate != null) { - return new MemberResolveResult(or.BestCandidate, type); + return or.CreateResolveResult(null); } else { return new ErrorResolveResult(type); } @@ -2068,8 +2655,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ITypeDefinition t = CurrentTypeDefinition; if (t != null) { foreach (IType baseType in t.GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && baseTypeDef.ClassType != ClassType.Interface) { + if (baseType.Kind != TypeKind.Unknown && baseType.Kind != TypeKind.Interface) { return new ResolveResult(baseType); } } @@ -2085,38 +2671,48 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver cancellationToken.ThrowIfCancellationRequested(); - Conversions c = new Conversions(context); bool isValid; IType resultType; - if (trueExpression.Type == SharedTypes.Dynamic || falseExpression.Type == SharedTypes.Dynamic) { + if (SharedTypes.Dynamic.Equals(trueExpression.Type) || SharedTypes.Dynamic.Equals(falseExpression.Type)) { resultType = SharedTypes.Dynamic; - isValid = true; + isValid = TryConvert(ref trueExpression, resultType) & TryConvert(ref falseExpression, resultType); } else if (HasType(trueExpression) && HasType(falseExpression)) { - bool t2f = c.ImplicitConversion(trueExpression.Type, falseExpression.Type); - bool f2t = c.ImplicitConversion(falseExpression.Type, trueExpression.Type); - resultType = (f2t && !t2f) ? trueExpression.Type : falseExpression.Type; + Conversion t2f = conversions.ImplicitConversion(trueExpression.Type, falseExpression.Type); + Conversion f2t = conversions.ImplicitConversion(falseExpression.Type, trueExpression.Type); // The operator is valid: // a) if there's a conversion in one direction but not the other // b) if there are conversions in both directions, and the types are equivalent - isValid = (t2f != f2t) || (t2f && f2t && trueExpression.Type.Equals(falseExpression.Type)); + if (t2f && !f2t) { + resultType = falseExpression.Type; + isValid = true; + trueExpression = Convert(trueExpression, resultType, t2f); + } else if (f2t && !t2f) { + resultType = trueExpression.Type; + isValid = true; + falseExpression = Convert(falseExpression, resultType, f2t); + } else { + resultType = trueExpression.Type; + isValid = trueExpression.Type.Equals(falseExpression.Type); + } } else if (HasType(trueExpression)) { resultType = trueExpression.Type; - isValid = c.ImplicitConversion(falseExpression, resultType); + isValid = TryConvert(ref falseExpression, resultType); } else if (HasType(falseExpression)) { resultType = falseExpression.Type; - isValid = c.ImplicitConversion(trueExpression, resultType); + isValid = TryConvert(ref trueExpression, resultType); } else { return ErrorResult; } + isValid &= TryConvert(ref condition, KnownTypeReference.Boolean.Resolve(context)); if (isValid) { if (condition.IsCompileTimeConstant && trueExpression.IsCompileTimeConstant && falseExpression.IsCompileTimeConstant) { bool? val = condition.ConstantValue as bool?; if (val == true) - return ResolveCast(resultType, trueExpression); + return trueExpression; else if (val == false) - return ResolveCast(resultType, falseExpression); + return falseExpression; } - return new ResolveResult(resultType); + return new ConditionalOperatorResolveResult(resultType, condition, trueExpression, falseExpression); } else { return new ErrorResolveResult(resultType); } @@ -2124,7 +2720,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool HasType(ResolveResult r) { - return r.Type != SharedTypes.UnknownType && r.Type != SharedTypes.Null; + return !(SharedTypes.UnknownType.Equals(r.Type) || SharedTypes.Null.Equals(r.Type)); } #endregion @@ -2181,5 +2777,51 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } #endregion + + #region ResolveArrayCreation + /// + /// Resolves an array creation. + /// + /// + /// The array element type. + /// Pass null to resolve an implicitly-typed array creation. + /// + /// + /// The number of array dimensions. + /// + /// + /// The size arguments. May be null if no explicit size was given. + /// The resolver may mutate this array to wrap elements in s! + /// + /// + /// The initializer elements. May be null if no array initializer was specified. + /// The resolver may mutate this array to wrap elements in s! + /// + /// + /// Specifies whether to allow treating single-dimensional arrays like compile-time constants. + /// This is used for attribute arguments. + /// + public ArrayCreateResolveResult ResolveArrayCreation(IType elementType, int dimensions = 1, ResolveResult[] sizeArguments = null, ResolveResult[] initializerElements = null) + { + if (sizeArguments != null && dimensions != Math.Max(1, sizeArguments.Length)) + throw new ArgumentException("dimensions and sizeArguments.Length don't match"); + if (elementType == null) { + TypeInference typeInference = new TypeInference(context, conversions); + bool success; + elementType = typeInference.GetBestCommonType(initializerElements, out success); + } + IType arrayType = new ArrayType(elementType, dimensions); + + if (sizeArguments != null) + AdjustArrayAccessArguments(sizeArguments); + + if (initializerElements != null) { + for (int i = 0; i < initializerElements.Length; i++) { + initializerElements[i] = Convert(initializerElements[i], elementType); + } + } + return new ArrayCreateResolveResult(arrayType, sizeArguments, initializerElements); + } + #endregion } } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/CompositeResolveVisitorNavigator.cs b/ICSharpCode.NRefactory.CSharp/Resolver/CompositeResolveVisitorNavigator.cs new file mode 100644 index 000000000..e810c435a --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/CompositeResolveVisitorNavigator.cs @@ -0,0 +1,63 @@ +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public sealed class CompositeResolveVisitorNavigator : IResolveVisitorNavigator + { + IResolveVisitorNavigator[] navigators; + + public CompositeResolveVisitorNavigator(params IResolveVisitorNavigator[] navigators) + { + if (navigators == null) + throw new ArgumentNullException("navigators"); + this.navigators = navigators; + } + + public ResolveVisitorNavigationMode Scan(AstNode node) + { + bool needsScan = false; + foreach (var navigator in navigators) { + ResolveVisitorNavigationMode mode = navigator.Scan(node); + if (mode == ResolveVisitorNavigationMode.Resolve) + return mode; // resolve has highest priority + else if (mode == ResolveVisitorNavigationMode.Scan) + needsScan = true; + } + return needsScan ? ResolveVisitorNavigationMode.Scan : ResolveVisitorNavigationMode.Skip; + } + + public void Resolved(AstNode node, ResolveResult result) + { + foreach (var navigator in navigators) { + navigator.Resolved(node, result); + } + } + + public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + foreach (var navigator in navigators) { + navigator.ProcessConversion(expression, result, conversion, targetType); + } + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ConstantValues.cs similarity index 77% rename from ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/ConstantValues.cs index 5c5990517..c7d55970e 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantValues.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ConstantValues.cs @@ -1,10 +1,27 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Linq; + using ICSharpCode.NRefactory.CSharp.Analysis; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; @@ -14,6 +31,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; @@ -37,52 +55,60 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues return new CSharpResolver(context) { CheckForOverflow = false, // TODO: get project-wide overflow setting CurrentTypeDefinition = parentTypeDefinition, - UsingScope = parentUsingScope + CurrentUsingScope = parentUsingScope }; } - public IType GetValueType(ITypeResolveContext context) + public ResolveResult Resolve(ITypeResolveContext context) { - CSharpResolver resolver = CreateResolver(context); - IType type = expression.Resolve(resolver).Type; - if (resolver.Context != context) { - // Retrieve the equivalent type in the new resolve context. - // E.g. if the constant is defined in a .NET 2.0 project, type might be Int32 from mscorlib 2.0. - // However, the calling project might be a .NET 4.0 project, so we need to return Int32 from mscorlib 4.0. - return type.AcceptVisitor(new MapTypeIntoNewContext(context)); + CacheManager cache = context.CacheManager; + if (cache != null) { + ResolveResult cachedResult = cache.GetShared(this) as ResolveResult; + if (cachedResult != null) + return cachedResult; } - return type; - } - - public object GetValue(ITypeResolveContext context) - { CSharpResolver resolver = CreateResolver(context); - object val = expression.Resolve(resolver).ConstantValue; - if (resolver.Context != context) { - // If 'val' is a type or an array containing types, we need to map it to the new context. - val = MapToNewContext(val, context); + ResolveResult rr = expression.Resolve(resolver); + // Retrieve the equivalent type in the new resolve context. + // E.g. if the constant is defined in a .NET 2.0 project, type might be Int32 from mscorlib 2.0. + // However, the calling project might be a .NET 4.0 project, so we need to return Int32 from mscorlib 4.0. + rr = MapToNewContext(rr, new MapTypeIntoNewContext(context)); + if (cache != null) + cache.SetShared(this, rr); + return rr; + } + + static ResolveResult MapToNewContext(ResolveResult rr, MapTypeIntoNewContext mapping) + { + if (rr is TypeOfResolveResult) { + return new TypeOfResolveResult( + rr.Type.AcceptVisitor(mapping), + ((TypeOfResolveResult)rr).ReferencedType.AcceptVisitor(mapping)); + } else if (rr is ArrayCreateResolveResult) { + ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr; + return new ArrayCreateResolveResult( + acrr.Type.AcceptVisitor(mapping), + MapToNewContext(acrr.SizeArguments, mapping), + MapToNewContext(acrr.InitializerElements, mapping)); + } else if (rr.IsCompileTimeConstant) { + return new ConstantResolveResult( + rr.Type.AcceptVisitor(mapping), + rr.ConstantValue + ); + } else { + return new ErrorResolveResult(rr.Type.AcceptVisitor(mapping)); } - return val; } - static object MapToNewContext(object val, ITypeResolveContext context) + static ResolveResult[] MapToNewContext(ResolveResult[] input, MapTypeIntoNewContext mapping) { - IType type = val as IType; - if (type != null) { - return type.AcceptVisitor(new MapTypeIntoNewContext(context)); - } - object[] arr = val as object[]; - if (arr != null) { - object[] newArr = new object[arr.Length]; - bool modified = false; - for (int i = 0; i < arr.Length; i++) { - newArr[i] = MapToNewContext(arr[i], context); - modified |= arr[i] != newArr[i]; - } - if (modified) - return newArr; + if (input == null) + return null; + ResolveResult[] output = new ResolveResult[input.Length]; + for (int i = 0; i < input.Length; i++) { + output[i] = MapToNewContext(input[i], mapping); } - return val; + return output; } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) @@ -107,9 +133,31 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + /// + /// Used for constants that could not be converted to IConstantValue. + /// + [Serializable] + public sealed class ErrorConstantValue : Immutable, IConstantValue + { + ITypeReference type; + + public ErrorConstantValue(ITypeReference type) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + } + + public ResolveResult Resolve(ITypeResolveContext context) + { + return new ErrorResolveResult(type.Resolve(context)); + } + } + /// /// Increments an integer by a fixed amount without changing the type. /// + [Serializable] public sealed class IncrementConstantValue : Immutable, IConstantValue, ISupportsInterning { IConstantValue baseValue; @@ -129,21 +177,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } - public IType GetValueType(ITypeResolveContext context) + public ResolveResult Resolve(ITypeResolveContext context) { - return baseValue.GetValueType(context); - } - - public object GetValue(ITypeResolveContext context) - { - object val = baseValue.GetValue(context); - if (val == null) - return null; - TypeCode typeCode = Type.GetTypeCode(val.GetType()); - if (!(typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64)) - return null; - long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false); - return CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false); + ResolveResult rr = baseValue.Resolve(context); + if (rr.IsCompileTimeConstant && rr.ConstantValue != null) { + object val = rr.ConstantValue; + TypeCode typeCode = Type.GetTypeCode(val.GetType()); + if (typeCode >= TypeCode.SByte && typeCode <= TypeCode.UInt64) { + long intVal = (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, val, false); + object newVal = CSharpPrimitiveCast.Cast(typeCode, unchecked(intVal + incrementAmount), false); + return new ConstantResolveResult(rr.Type, newVal); + } + } + return new ErrorResolveResult(rr.Type); } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) @@ -163,6 +209,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public abstract class ConstantExpression { public abstract ResolveResult Resolve(CSharpResolver resolver); @@ -171,6 +218,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues /// /// C#'s equivalent to the SimpleConstantValue. /// + [Serializable] public sealed class PrimitiveConstantExpression : ConstantExpression, ISupportsInterning { ITypeReference type; @@ -218,6 +266,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantCast : ConstantExpression, ISupportsInterning { ITypeReference targetType; @@ -259,6 +308,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantIdentifierReference : ConstantExpression, ISupportsInterning { string identifier; @@ -312,6 +362,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantMemberReference : ConstantExpression, ISupportsInterning { ITypeReference targetType; @@ -383,6 +434,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantCheckedExpression : ConstantExpression, ISupportsInterning { bool checkForOverflow; @@ -426,6 +478,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantDefaultValue : ConstantExpression, ISupportsInterning { ITypeReference type; @@ -459,6 +512,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantUnaryOperator : ConstantExpression, ISupportsInterning { UnaryOperatorType operatorType; @@ -498,6 +552,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantBinaryOperator : ConstantExpression, ISupportsInterning { ConstantExpression left; @@ -544,6 +599,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver.ConstantValues } } + [Serializable] public sealed class ConstantConditionalOperator : ConstantExpression, ISupportsInterning { ConstantExpression condition, trueExpr, falseExpr; @@ -599,40 +655,49 @@ 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 - ITypeReference type; + ITypeReference elementType; IList arrayElements; public ConstantArrayCreation(ITypeReference type, IList arrayElements) { if (arrayElements == null) throw new ArgumentNullException("arrayElements"); - this.type = type; + this.elementType = type; this.arrayElements = arrayElements; } public override ResolveResult Resolve(CSharpResolver resolver) { - throw new NotImplementedException(); + ResolveResult[] elements = new ResolveResult[arrayElements.Count]; + for (int i = 0; i < elements.Length; i++) { + elements[i] = arrayElements[i].Resolve(resolver); + } + if (elementType != null) { + return resolver.ResolveArrayCreation(elementType.Resolve(resolver.Context), 1, null, elements); + } else { + return resolver.ResolveArrayCreation(null, 1, null, elements); + } } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) { - type = provider.Intern(type); + elementType = provider.Intern(elementType); arrayElements = provider.InternList(arrayElements); } int ISupportsInterning.GetHashCodeForInterning() { - return (type != null ? type.GetHashCode() : 0) ^ arrayElements.GetHashCode(); + return (elementType != null ? elementType.GetHashCode() : 0) ^ arrayElements.GetHashCode(); } bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { ConstantArrayCreation cac = other as ConstantArrayCreation; - return cac != null && this.type == cac.type && this.arrayElements == cac.arrayElements; + return cac != null && this.elementType == cac.elementType && this.arrayElements == cac.arrayElements; } } } diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ConversionResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ConversionResolveResult.cs new file mode 100644 index 000000000..13dd7b762 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ConversionResolveResult.cs @@ -0,0 +1,49 @@ +// 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.Collections.Generic; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public class ConversionResolveResult : ResolveResult + { + public readonly ResolveResult Input; + public readonly Conversion Conversion; + + public ConversionResolveResult(IType targetType, ResolveResult input, Conversion conversion) + : base(targetType) + { + if (input == null) + throw new ArgumentNullException("input"); + this.Input = input; + this.Conversion = conversion; + } + + public override bool IsError { + get { return !Conversion.IsValid; } + } + + public override IEnumerable GetChildResults() + { + return new [] { Input }; + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs b/ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs new file mode 100644 index 000000000..e54b87115 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/Conversions.cs @@ -0,0 +1,1140 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Holds information about a conversion between two types. + /// + public struct Conversion : IEquatable + { + public static readonly Conversion None = default(Conversion); + public static readonly Conversion IdentityConversion = new Conversion(1); + public static readonly Conversion ImplicitNumericConversion = new Conversion(2); + public static readonly Conversion ImplicitEnumerationConversion = new Conversion(3); + public static readonly Conversion ImplicitNullableConversion = new Conversion(4); + public static readonly Conversion NullLiteralConversion = new Conversion(5); + public static readonly Conversion ImplicitReferenceConversion = new Conversion(6); + public static readonly Conversion BoxingConversion = new Conversion(7); + public static readonly Conversion ImplicitDynamicConversion = new Conversion(8); + public static readonly Conversion ImplicitConstantExpressionConversion = new Conversion(9); + const int userDefinedImplicitConversionKind = 10; + const int liftedUserDefinedImplicitConversionKind = 11; + public static readonly Conversion ImplicitPointerConversion = new Conversion(12); + const int anonymousFunctionConversionKind = 13; + const int methodGroupConversionKind = 14; + public static readonly Conversion ExplicitNumericConversion = new Conversion(15); + public static readonly Conversion ExplicitEnumerationConversion = new Conversion(16); + public static readonly Conversion ExplicitNullableConversion = new Conversion(17); + public static readonly Conversion ExplicitReferenceConversion = new Conversion(18); + public static readonly Conversion UnboxingConversion = new Conversion(19); + public static readonly Conversion ExplicitDynamicConversion = new Conversion(20); + public static readonly Conversion ExplicitPointerConversion = new Conversion(21); + const int userDefinedExplicitConversionKind = 22; + const int liftedUserDefinedExplicitConversionKind = 23; + + const int lastImplicitConversion = methodGroupConversionKind; + + static readonly string[] conversionNames = { + "None", + "Identity conversion", + "Implicit numeric conversion", + "Implicit enumeration conversion", + "Implicit nullable conversion", + "Null literal conversion", + "Implicit reference conversion", + "Boxing conversion", + "Implicit dynamic conversion", + "Implicit constant expression conversion", + "User-defined implicit conversion", + "Lifted user-defined implicit conversion", + "Implicit pointer conversion", + "Anonymous function conversion", + "Method group conversion", + "Explicit numeric conversion", + "Explicit enumeration conversion", + "Explicit nullable conversion", + "Explicit reference conversion", + "Unboxing conversion", + "Explicit dynamic conversion", + "Explicit pointer conversion", + "User-defined explicit conversion", + "Lifted user-defined explicit conversion" + }; + + public static Conversion UserDefinedImplicitConversion(IMethod operatorMethod, bool isLifted) + { + if (operatorMethod == null) + throw new ArgumentNullException("operatorMethod"); + return new Conversion(isLifted ? liftedUserDefinedImplicitConversionKind : userDefinedImplicitConversionKind, operatorMethod); + } + + public static Conversion UserDefinedExplicitConversion(IMethod operatorMethod, bool isLifted) + { + if (operatorMethod == null) + throw new ArgumentNullException("operatorMethod"); + return new Conversion(isLifted ? liftedUserDefinedExplicitConversionKind : userDefinedExplicitConversionKind, operatorMethod); + } + + public static Conversion MethodGroupConversion(IMethod chosenMethod) + { + if (chosenMethod == null) + throw new ArgumentNullException("chosenMethod"); + return new Conversion(methodGroupConversionKind, chosenMethod); + } + + /// + /// Creates a new anonymous function conversion. + /// + /// Used by ResolveVisitor to pass the LambdaTypeHypothesis. + public static Conversion AnonymousFunctionConversion(object data) + { + return new Conversion(anonymousFunctionConversionKind, data); + } + + readonly int kind; + internal readonly object data; + + public Conversion(int kind, object data = null) + { + this.kind = kind; + this.data = data; + } + + /// + /// Gets whether this conversion is an implicit conversion. + /// + public bool IsImplicitConversion { + get { return kind > 0 && kind <= lastImplicitConversion; } + } + + /// + /// Gets whether this conversion is an explicit conversion. + /// + public bool IsExplicitConversion { + get { return kind > lastImplicitConversion; } + } + + /// + /// Gets whether this conversion is user-defined. + /// + public bool IsUserDefined { + get { + switch (kind) { + case userDefinedImplicitConversionKind: + case liftedUserDefinedImplicitConversionKind: + case userDefinedExplicitConversionKind: + case liftedUserDefinedExplicitConversionKind: + return true; + default: + return false; + } + } + } + + /// + /// Gets whether this conversion is a lifted version of a user-defined conversion operator. + /// + /// Lifted versions of builtin conversion operators are classified as nullable-conversion + public bool IsLifted { + get { + return kind == liftedUserDefinedImplicitConversionKind || kind == liftedUserDefinedExplicitConversionKind; + } + } + + /// + /// Gets whether this conversion is a method group conversion. + /// + public bool IsMethodGroupConversion { + get { return kind == methodGroupConversionKind; } + } + + /// + /// Gets whether this conversion is an anonymous function conversion. + /// + public bool IsAnonymousFunctionConversion { + get { return kind == anonymousFunctionConversionKind; } + } + + /// + /// Gets the method associated with this conversion. + /// For user-defined conversions, this is the method being called. + /// For method-group conversions, this is the method that was chosen from the group. + /// + public IMethod Method { + get { return data as IMethod; } + } + + public override string ToString() + { + string name = conversionNames[kind]; + if (data != null) + return name + " (" + data + ")"; + else + return name; + } + + public bool IsValid { + get { return kind > 0; } + } + + public static implicit operator bool(Conversion conversion) + { + return conversion.kind > 0; + } + + #region Equals and GetHashCode implementation + public override int GetHashCode() + { + if (data != null) + return kind ^ data.GetHashCode(); + else + return kind; + } + + public override bool Equals(object obj) + { + return (obj is Conversion) && Equals((Conversion)obj); + } + + public bool Equals(Conversion other) + { + return this.kind == other.kind && object.Equals(this.data, other.data); + } + + public static bool operator ==(Conversion lhs, Conversion rhs) + { + return lhs.Equals(rhs); + } + + public static bool operator !=(Conversion lhs, Conversion rhs) + { + return !lhs.Equals(rhs); + } + #endregion + } + + /// + /// Contains logic that determines whether an implicit conversion exists between two types. + /// + public class Conversions + { + readonly Dictionary implicitConversionCache = new Dictionary(); + readonly ITypeResolveContext context; + readonly IType objectType; + + public Conversions(ITypeResolveContext context) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + this.objectType = KnownTypeReference.Object.Resolve(context); + this.dynamicErasure = new DynamicErasure(this); + } + + /// + /// Gets the Conversions instance for the specified . + /// This will make use of the context's cache manager (if available) to reuse the Conversions instance. + /// + public static Conversions Get(ITypeResolveContext context) + { + CacheManager cache = context.CacheManager; + if (cache != null) { + Conversions conversions = cache.GetThreadLocal(typeof(Conversions)) as Conversions; + if (conversions == null) { + conversions = new Conversions(context); + cache.SetThreadLocal(typeof(Conversions), conversions); + } + return conversions; + } else { + return new Conversions(context); + } + } + + #region TypePair (for caching) + struct TypePair : IEquatable + { + public readonly IType FromType; + public readonly IType ToType; + + public TypePair(IType fromType, IType toType) + { + this.FromType = fromType; + this.ToType = toType; + } + + public override bool Equals(object obj) + { + return (obj is TypePair) && Equals((TypePair)obj); + } + + public bool Equals(TypePair other) + { + return this.FromType.Equals(other.FromType) && this.ToType.Equals(other.ToType); + } + + public override int GetHashCode() + { + unchecked { + return 1000000007 * FromType.GetHashCode() + 1000000009 * ToType.GetHashCode(); + } + } + } + #endregion + + #region ImplicitConversion + public Conversion ImplicitConversion(ResolveResult resolveResult, IType toType) + { + if (resolveResult == null) + throw new ArgumentNullException("resolveResult"); + if (resolveResult.IsCompileTimeConstant) { + if (ImplicitEnumerationConversion(resolveResult, toType)) + return Conversion.ImplicitEnumerationConversion; + if (ImplicitConstantExpressionConversion(resolveResult, toType)) + return Conversion.ImplicitConstantExpressionConversion; + } + Conversion c; + c = ImplicitConversion(resolveResult.Type, toType); + if (c) return c; + c = AnonymousFunctionConversion(resolveResult, toType); + if (c) return c; + c = MethodGroupConversion(resolveResult, toType); + return c; + } + + public Conversion ImplicitConversion(IType fromType, IType toType) + { + if (fromType == null) + throw new ArgumentNullException("fromType"); + if (toType == null) + throw new ArgumentNullException("toType"); + + TypePair pair = new TypePair(fromType, toType); + Conversion c; + if (implicitConversionCache.TryGetValue(pair, out c)) + return c; + + // C# 4.0 spec: §6.1 + c = StandardImplicitConversion(fromType, toType); + if (!c) { + c = UserDefinedImplicitConversion(fromType, toType); + } + implicitConversionCache[pair] = c; + return c; + } + + public Conversion StandardImplicitConversion(IType fromType, IType toType) + { + if (fromType == null) + throw new ArgumentNullException("fromType"); + if (toType == null) + throw new ArgumentNullException("toType"); + // C# 4.0 spec: §6.3.1 + if (IdentityConversion(fromType, toType)) + return Conversion.IdentityConversion; + if (ImplicitNumericConversion(fromType, toType)) + return Conversion.ImplicitNumericConversion; + if (ImplicitNullableConversion(fromType, toType)) + return Conversion.ImplicitNullableConversion; + if (NullLiteralConversion(fromType, toType)) + return Conversion.NullLiteralConversion; + if (ImplicitReferenceConversion(fromType, toType)) + return Conversion.ImplicitReferenceConversion; + if (BoxingConversion(fromType, toType)) + return Conversion.BoxingConversion; + if (fromType.Kind == TypeKind.Dynamic) + return Conversion.ImplicitDynamicConversion; + if (ImplicitTypeParameterConversion(fromType, toType)) { + // Implicit type parameter conversions that aren't also + // reference conversions are considered to be boxing conversions + return Conversion.BoxingConversion; + } + if (ImplicitPointerConversion(fromType, toType)) + return Conversion.ImplicitPointerConversion; + return Conversion.None; + } + + /// + /// Gets whether the type 'fromType' is convertible to 'toType' + /// using one of the conversions allowed when satisying constraints (§4.4.4) + /// + public bool IsConstraintConvertible(IType fromType, IType toType) + { + if (fromType == null) + throw new ArgumentNullException("fromType"); + if (toType == null) + throw new ArgumentNullException("toType"); + + if (IdentityConversion(fromType, toType)) + return true; + if (ImplicitReferenceConversion(fromType, toType)) + return true; + if (BoxingConversion(fromType, toType) && !NullableType.IsNullable(fromType)) + return true; + if (ImplicitTypeParameterConversion(fromType, toType)) + return true; + return false; + } + #endregion + + #region ExplicitConversion + public Conversion ExplicitConversion(ResolveResult resolveResult, IType toType) + { + if (resolveResult == null) + throw new ArgumentNullException("resolveResult"); + if (toType == null) + throw new ArgumentNullException("toType"); + + if (resolveResult.Type.Kind == TypeKind.Dynamic) + return Conversion.ExplicitDynamicConversion; + Conversion c = ImplicitConversion(resolveResult, toType); + if (c) + return c; + else + return ExplicitConversionImpl(resolveResult.Type, toType); + } + + public Conversion ExplicitConversion(IType fromType, IType toType) + { + if (fromType == null) + throw new ArgumentNullException("fromType"); + if (toType == null) + throw new ArgumentNullException("toType"); + + if (fromType.Kind == TypeKind.Dynamic) + return Conversion.ExplicitDynamicConversion; + Conversion c = ImplicitConversion(fromType, toType); + if (c) + return c; + else + return ExplicitConversionImpl(fromType, toType); + } + + Conversion ExplicitConversionImpl(IType fromType, IType toType) + { + // This method is called after we already checked for implicit conversions, + // so any remaining conversions must be explicit. + if (AnyNumericConversion(fromType, toType)) + return Conversion.ExplicitNumericConversion; + if (ExplicitEnumerationConversion(fromType, toType)) + return Conversion.ExplicitEnumerationConversion; + if (ExplicitNullableConversion(fromType, toType)) + return Conversion.ExplicitNullableConversion; + if (ExplicitReferenceConversion(fromType, toType)) + return Conversion.ExplicitReferenceConversion; + if (UnboxingConversion(fromType, toType)) + return Conversion.UnboxingConversion; + if (ExplicitTypeParameterConversion(fromType, toType)) { + // Explicit type parameter conversions that aren't also + // reference conversions are considered to be unboxing conversions + return Conversion.UnboxingConversion; + } + if (ExplicitPointerConversion(fromType, toType)) + return Conversion.ExplicitPointerConversion; + return UserDefinedExplicitConversion(fromType, toType); + } + #endregion + + #region Identity Conversion + /// + /// Gets whether there is an identity conversion from to + /// + public bool IdentityConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.1 + return fromType.AcceptVisitor(dynamicErasure).Equals(toType.AcceptVisitor(dynamicErasure)); + } + + readonly DynamicErasure dynamicErasure; + + sealed class DynamicErasure : TypeVisitor + { + readonly IType objectType; + + public DynamicErasure(Conversions conversions) + { + this.objectType = conversions.objectType; + } + + public override IType VisitOtherType(IType type) + { + if (type == SharedTypes.Dynamic) + return objectType; + else + return base.VisitOtherType(type); + } + } + #endregion + + #region Numeric Conversions + static readonly bool[,] implicitNumericConversionLookup = { + // to: short ushort int uint long ulong + // from: + /* char */ { false, true , true , true , true , true }, + /* sbyte */ { true , false, true , false, true , false }, + /* byte */ { true , true , true , true , true , true }, + /* short */ { false, false, true , false, true , false }, + /* ushort */ { false, false, true , true , true , true }, + /* int */ { false, false, false, false, true , false }, + /* uint */ { false, false, false, false, true , true }, + }; + + bool ImplicitNumericConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.2 + + TypeCode from = ReflectionHelper.GetTypeCode(fromType); + TypeCode to = ReflectionHelper.GetTypeCode(toType); + if (to >= TypeCode.Single && to <= TypeCode.Decimal) { + // Conversions to float/double/decimal exist from all integral types, + // and there's a conversion from float to double. + return from >= TypeCode.Char && from <= TypeCode.UInt64 + || from == TypeCode.Single && to == TypeCode.Double; + } else { + // Conversions to integral types: look at the table + return from >= TypeCode.Char && from <= TypeCode.UInt32 + && to >= TypeCode.Int16 && to <= TypeCode.UInt64 + && implicitNumericConversionLookup[from - TypeCode.Char, to - TypeCode.Int16]; + } + } + + bool IsNumericType(IType type) + { + TypeCode c = ReflectionHelper.GetTypeCode(type); + return c >= TypeCode.Char && c <= TypeCode.Decimal; + } + + bool AnyNumericConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.2 + §6.2.1 + return IsNumericType(fromType) && IsNumericType(toType); + } + #endregion + + #region Enumeration Conversions + bool ImplicitEnumerationConversion(ResolveResult rr, IType toType) + { + // C# 4.0 spec: §6.1.3 + Debug.Assert(rr.IsCompileTimeConstant); + TypeCode constantType = ReflectionHelper.GetTypeCode(rr.Type); + if (constantType >= TypeCode.SByte && constantType <= TypeCode.Decimal && Convert.ToDouble(rr.ConstantValue) == 0) { + return NullableType.GetUnderlyingType(toType).Kind == TypeKind.Enum; + } + return false; + } + + bool ExplicitEnumerationConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.2.2 + if (fromType.Kind == TypeKind.Enum) { + return toType.Kind == TypeKind.Enum || IsNumericType(toType); + } else if (IsNumericType(fromType)) { + return toType.Kind == TypeKind.Enum; + } + return false; + } + #endregion + + #region Nullable Conversions + bool ImplicitNullableConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.4 + if (NullableType.IsNullable(toType)) { + IType t = NullableType.GetUnderlyingType(toType); + IType s = NullableType.GetUnderlyingType(fromType); // might or might not be nullable + return IdentityConversion(s, t) || ImplicitNumericConversion(s, t); + } else { + return false; + } + } + + bool ExplicitNullableConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.4 + if (NullableType.IsNullable(toType) || NullableType.IsNullable(fromType)) { + IType t = NullableType.GetUnderlyingType(toType); + IType s = NullableType.GetUnderlyingType(fromType); + return IdentityConversion(s, t) || AnyNumericConversion(s, t) || ExplicitEnumerationConversion(s, t); + } else { + return false; + } + } + #endregion + + #region Null Literal Conversion + bool NullLiteralConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.5 + if (SharedTypes.Null.Equals(fromType)) { + return NullableType.IsNullable(toType) || toType.IsReferenceType(context) == true; + } else { + return false; + } + } + #endregion + + #region Implicit Reference Conversion + bool ImplicitReferenceConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.6 + + // reference conversions are possible only if both types are known to be reference types + if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true)) + return false; + + ArrayType fromArray = fromType as ArrayType; + if (fromArray != null) { + ArrayType toArray = toType as ArrayType; + if (toArray != null) { + // array covariance (the broken kind) + return fromArray.Dimensions == toArray.Dimensions + && ImplicitReferenceConversion(fromArray.ElementType, toArray.ElementType); + } + // conversion from single-dimensional array S[] to IList: + ParameterizedType toPT = toType as ParameterizedType; + if (fromArray.Dimensions == 1 && toPT != null && toPT.TypeParameterCount == 1 + && toPT.Namespace == "System.Collections.Generic" + && (toPT.Name == "IList" || toPT.Name == "ICollection" || toPT.Name == "IEnumerable")) + { + // array covariance plays a part here as well (string[] is IList) + return IdentityConversion(fromArray.ElementType, toPT.GetTypeArgument(0)) + || ImplicitReferenceConversion(fromArray.ElementType, toPT.GetTypeArgument(0)); + } + // conversion from any array to System.Array and the interfaces it implements: + ITypeDefinition systemArray = context.GetTypeDefinition("System", "Array", 0, StringComparer.Ordinal); + return systemArray != null && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType)); + } + + // now comes the hard part: traverse the inheritance chain and figure out generics+variance + return IsSubtypeOf(fromType, toType); + } + + // Determines whether s is a subtype of t. + // Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion + + int subtypeCheckNestingDepth; + + bool IsSubtypeOf(IType s, IType t) + { + // conversion to dynamic + object are always possible + if (t.Equals(SharedTypes.Dynamic) || t.Equals(objectType)) + return true; + try { + if (++subtypeCheckNestingDepth > 10) { + // Subtyping in C# is undecidable + // (see "On Decidability of Nominal Subtyping with Variance" by Andrew J. Kennedy and Benjamin C. Pierce), + // so we'll prevent infinite recursions by putting a limit on the nesting depth of variance conversions. + + // No real C# code should use generics nested more than 10 levels deep, and even if they do, most of + // those nestings should not involve variance. + return false; + } + // let GetAllBaseTypes do the work for us + foreach (IType baseType in s.GetAllBaseTypes(context)) { + if (IdentityOrVarianceConversion(baseType, t)) + return true; + } + return false; + } finally { + subtypeCheckNestingDepth--; + } + } + + bool IdentityOrVarianceConversion(IType s, IType t) + { + ITypeDefinition def = s.GetDefinition(); + if (def != null && def.Equals(t.GetDefinition())) { + ParameterizedType ps = s as ParameterizedType; + ParameterizedType pt = t as ParameterizedType; + if (ps != null && pt != null) { + // C# 4.0 spec: §13.1.3.2 Variance Conversion + for (int i = 0; i < def.TypeParameters.Count; i++) { + IType si = ps.GetTypeArgument(i); + IType ti = pt.GetTypeArgument(i); + if (IdentityConversion(si, ti)) + continue; + ITypeParameter xi = def.TypeParameters[i]; + switch (xi.Variance) { + case VarianceModifier.Covariant: + if (!ImplicitReferenceConversion(si, ti)) + return false; + break; + case VarianceModifier.Contravariant: + if (!ImplicitReferenceConversion(ti, si)) + return false; + break; + default: + return false; + } + } + } else if (ps != null || pt != null) { + return false; // only of of them is parameterized, or counts don't match? -> not valid conversion + } + return true; + } + return false; + } + #endregion + + #region Explicit Reference Conversion + bool ExplicitReferenceConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.2.4 + + // reference conversions are possible only if both types are known to be reference types + if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true)) + return false; + + // There's lots of additional rules, but they're not really relevant, + // as they are only used to identify invalid casts, and we don't care about reporting those. + return true; + } + #endregion + + #region Boxing Conversions + bool BoxingConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.1.7 + fromType = NullableType.GetUnderlyingType(fromType); + if (fromType.IsReferenceType(context) == false && toType.IsReferenceType(context) == true) + return IsSubtypeOf(fromType, toType); + else + return false; + } + + bool UnboxingConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §6.2.5 + toType = NullableType.GetUnderlyingType(toType); + if (fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == false) + return IsSubtypeOf(toType, fromType); + else + return false; + } + #endregion + + #region Implicit Constant-Expression Conversion + bool ImplicitConstantExpressionConversion(ResolveResult rr, IType toType) + { + // C# 4.0 spec: §6.1.9 + Debug.Assert(rr.IsCompileTimeConstant); + TypeCode fromTypeCode = ReflectionHelper.GetTypeCode(rr.Type); + TypeCode toTypeCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(toType)); + if (fromTypeCode == TypeCode.Int64) { + long val = (long)rr.ConstantValue; + return val >= 0 && toTypeCode == TypeCode.UInt64; + } else if (fromTypeCode == TypeCode.Int32) { + int val = (int)rr.ConstantValue; + switch (toTypeCode) { + case TypeCode.SByte: + return val >= SByte.MinValue && val <= SByte.MaxValue; + case TypeCode.Byte: + return val >= Byte.MinValue && val <= Byte.MaxValue; + case TypeCode.Int16: + return val >= Int16.MinValue && val <= Int16.MaxValue; + case TypeCode.UInt16: + return val >= UInt16.MinValue && val <= UInt16.MaxValue; + case TypeCode.UInt32: + return val >= 0; + case TypeCode.UInt64: + return val >= 0; + } + } + return false; + } + #endregion + + #region Conversions involving type parameters + /// + /// Implicit conversions involving type parameters. + /// + bool ImplicitTypeParameterConversion(IType fromType, IType toType) + { + if (fromType.Kind != TypeKind.TypeParameter) + return false; // not a type parameter + if (fromType.IsReferenceType(context) == true) + return false; // already handled by ImplicitReferenceConversion + return IsSubtypeOf(fromType, toType); + } + + bool ExplicitTypeParameterConversion(IType fromType, IType toType) + { + if (toType.Kind == TypeKind.TypeParameter) { + return fromType.Kind == TypeKind.TypeParameter || fromType.IsReferenceType(context) == true; + } else { + return fromType.Kind == TypeKind.TypeParameter && toType.Kind == TypeKind.Interface; + } + } + #endregion + + #region Pointer Conversions + bool ImplicitPointerConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §18.4 Pointer conversions + if (fromType is PointerType && toType is PointerType && toType.ReflectionName == "System.Void*") + return true; + if (SharedTypes.Null.Equals(fromType) && toType is PointerType) + return true; + return false; + } + + bool ExplicitPointerConversion(IType fromType, IType toType) + { + // C# 4.0 spec: §18.4 Pointer conversions + if (fromType.Kind == TypeKind.Pointer) { + return toType.Kind == TypeKind.Pointer || IsIntegerType(toType); + } else { + return toType.Kind == TypeKind.Pointer && IsIntegerType(fromType); + } + } + + bool IsIntegerType(IType type) + { + TypeCode c = ReflectionHelper.GetTypeCode(type); + return c >= TypeCode.SByte && c <= TypeCode.UInt64; + } + #endregion + + #region User-Defined Conversions + /// + /// Gets whether type A is encompassed by type B. + /// + bool IsEncompassedBy(IType a, IType b) + { + return a.Kind != TypeKind.Interface && b.Kind != TypeKind.Interface && StandardImplicitConversion(a, b); + } + + bool IsEncompassingOrEncompassedBy(IType a, IType b) + { + return a.Kind != TypeKind.Interface && b.Kind != TypeKind.Interface + && (StandardImplicitConversion(a, b) || StandardImplicitConversion(b, a)); + } + + Conversion UserDefinedImplicitConversion(IType fromType, IType toType) + { + // C# 4.0 spec §6.4.4 User-defined implicit conversions + var operators = GetApplicableConversionOperators(fromType, toType, false); + // TODO: Find most specific conversion + if (operators.Count > 0) + return Conversion.UserDefinedImplicitConversion(operators[0].Method, operators[0].IsLifted); + else + return Conversion.None; + } + + Conversion UserDefinedExplicitConversion(IType fromType, IType toType) + { + // C# 4.0 spec §6.4.5 User-defined implicit conversions + var operators = GetApplicableConversionOperators(fromType, toType, true); + // TODO: Find most specific conversion + if (operators.Count > 0) + return Conversion.UserDefinedExplicitConversion(operators[0].Method, operators[0].IsLifted); + else + return Conversion.None; + } + + class OperatorInfo + { + public readonly IMethod Method; + public readonly IType SourceType; + public readonly IType TargetType; + public readonly bool IsLifted; + + public OperatorInfo(IMethod method, IType sourceType, IType targetType, bool isLifted) + { + this.Method = method; + this.SourceType = sourceType; + this.TargetType = targetType; + this.IsLifted = isLifted; + } + } + + List GetApplicableConversionOperators(IType fromType, IType toType, bool isExplicit) + { + // Find the candidate operators: + Predicate opFilter; + if (isExplicit) + opFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Explicit" && m.Parameters.Count == 1; + else + opFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Implicit" && m.Parameters.Count == 1; + + var operators = NullableType.GetUnderlyingType(fromType).GetMethods(context, opFilter) + .Concat(NullableType.GetUnderlyingType(toType).GetMethods(context, opFilter)).Distinct(); + // Determine whether one of them is applicable: + List result = new List(); + foreach (IMethod op in operators) { + IType sourceType = op.Parameters[0].Type.Resolve(context); + IType targetType = op.ReturnType.Resolve(context); + // Try if the operator is applicable: + bool isApplicable; + if (isExplicit) { + isApplicable = IsEncompassingOrEncompassedBy(fromType, sourceType) + && IsEncompassingOrEncompassedBy(targetType, toType); + } else { + isApplicable = IsEncompassedBy(fromType, sourceType) && IsEncompassedBy(targetType, toType); + } + if (isApplicable) { + result.Add(new OperatorInfo(op, sourceType, targetType, false)); + } + // Try if the operator is applicable in lifted form: + if (NullableType.IsNonNullableValueType(sourceType, context) + && NullableType.IsNonNullableValueType(targetType, context)) + { + IType liftedSourceType = NullableType.Create(sourceType, context); + IType liftedTargetType = NullableType.Create(targetType, context); + if (isExplicit) { + isApplicable = IsEncompassingOrEncompassedBy(fromType, liftedSourceType) + && IsEncompassingOrEncompassedBy(liftedTargetType, toType); + } else { + isApplicable = IsEncompassedBy(fromType, liftedSourceType) && IsEncompassedBy(liftedTargetType, toType); + } + if (isApplicable) { + result.Add(new OperatorInfo(op, liftedSourceType, liftedTargetType, true)); + } + } + } + return result; + } + #endregion + + #region AnonymousFunctionConversion + Conversion AnonymousFunctionConversion(ResolveResult resolveResult, IType toType) + { + // C# 4.0 spec §6.5 Anonymous function conversions + LambdaResolveResult f = resolveResult as LambdaResolveResult; + if (f == null) + return Conversion.None; + if (!f.IsAnonymousMethod) { + // It's a lambda, so conversions to expression trees exist + // (even if the conversion leads to a compile-time error, e.g. for statement lambdas) + toType = UnpackExpressionTreeType(toType); + } + IMethod d = toType.GetDelegateInvokeMethod(); + if (d == null) + return Conversion.None; + + IType[] dParamTypes = new IType[d.Parameters.Count]; + for (int i = 0; i < dParamTypes.Length; i++) { + dParamTypes[i] = d.Parameters[i].Type.Resolve(context); + } + IType dReturnType = d.ReturnType.Resolve(context); + + if (f.HasParameterList) { + // If F contains an anonymous-function-signature, then D and F have the same number of parameters. + if (d.Parameters.Count != f.Parameters.Count) + return Conversion.None; + + if (f.IsImplicitlyTyped) { + // If F has an implicitly typed parameter list, D has no ref or out parameters. + foreach (IParameter p in d.Parameters) { + if (p.IsOut || p.IsRef) + return Conversion.None; + } + } else { + // If F has an explicitly typed parameter list, each parameter in D has the same type + // and modifiers as the corresponding parameter in F. + for (int i = 0; i < f.Parameters.Count; i++) { + IParameter pD = d.Parameters[i]; + IParameter pF = f.Parameters[i]; + if (pD.IsRef != pF.IsRef || pD.IsOut != pF.IsOut) + return Conversion.None; + if (!dParamTypes[i].Equals(pF.Type.Resolve(context))) + return Conversion.None; + } + } + } else { + // If F does not contain an anonymous-function-signature, then D may have zero or more parameters of any + // type, as long as no parameter of D has the out parameter modifier. + foreach (IParameter p in d.Parameters) { + if (p.IsOut) + return Conversion.None; + } + } + + return f.IsValid(dParamTypes, dReturnType, this); + } + + static IType UnpackExpressionTreeType(IType type) + { + ParameterizedType pt = type as ParameterizedType; + if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Expression" && pt.Namespace == "System.Linq.Expressions") { + return pt.GetTypeArgument(0); + } else { + return type; + } + } + #endregion + + #region MethodGroupConversion + Conversion MethodGroupConversion(ResolveResult resolveResult, IType toType) + { + // C# 4.0 spec §6.6 Method group conversions + MethodGroupResolveResult rr = resolveResult as MethodGroupResolveResult; + if (rr == null) + return Conversion.None; + IMethod m = toType.GetDelegateInvokeMethod(); + if (m == null) + return Conversion.None; + + ResolveResult[] args = new ResolveResult[m.Parameters.Count]; + for (int i = 0; i < args.Length; i++) { + IParameter param = m.Parameters[i]; + IType parameterType = param.Type.Resolve(context); + if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { + parameterType = ((ByReferenceType)parameterType).ElementType; + args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); + } else { + args[i] = new ResolveResult(parameterType); + } + } + var or = rr.PerformOverloadResolution(context, args, allowExpandingParams: false, conversions: this); + if (or.FoundApplicableCandidate) + return Conversion.MethodGroupConversion((IMethod)or.BestCandidate); + else + return Conversion.None; + } + #endregion + + #region BetterConversion + /// + /// Gets the better conversion (C# 4.0 spec, §7.5.3.3) + /// + /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better + public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2) + { + LambdaResolveResult lambda = resolveResult as LambdaResolveResult; + if (lambda != null) { + if (!lambda.IsAnonymousMethod) { + t1 = UnpackExpressionTreeType(t1); + t2 = UnpackExpressionTreeType(t2); + } + IMethod m1 = t1.GetDelegateInvokeMethod(); + IMethod m2 = t2.GetDelegateInvokeMethod(); + if (m1 == null || m2 == null) + return 0; + int r = BetterConversionTarget(t1, t2); + if (r != 0) + return r; + if (m1.Parameters.Count != m2.Parameters.Count) + return 0; + IType[] parameterTypes = new IType[m1.Parameters.Count]; + for (int i = 0; i < parameterTypes.Length; i++) { + parameterTypes[i] = m1.Parameters[i].Type.Resolve(context); + if (!parameterTypes[i].Equals(m2.Parameters[i].Type.Resolve(context))) + return 0; + } + if (lambda.HasParameterList && parameterTypes.Length != lambda.Parameters.Count) + return 0; + + IType ret1 = m1.ReturnType.Resolve(context); + IType ret2 = m2.ReturnType.Resolve(context); + if (ret1.Kind == TypeKind.Void && ret2.Kind != TypeKind.Void) + return 1; + if (ret1.Kind != TypeKind.Void && ret2.Kind == TypeKind.Void) + return 2; + + IType inferredRet = lambda.GetInferredReturnType(parameterTypes); + r = BetterConversion(inferredRet, ret1, ret2); + if (r == 0 && lambda.IsAsync) { + ret1 = UnpackTask(ret1); + ret2 = UnpackTask(ret2); + inferredRet = UnpackTask(inferredRet); + if (ret1 != null && ret2 != null && inferredRet != null) + r = BetterConversion(inferredRet, ret1, ret2); + } + return r; + } else { + return BetterConversion(resolveResult.Type, t1, t2); + } + } + + /// + /// Unpacks the generic Task[T]. Returns null if the input is not Task[T]. + /// + static IType UnpackTask(IType type) + { + ParameterizedType pt = type as ParameterizedType; + if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Task" && pt.Namespace == "System.Threading.Tasks") { + return pt.GetTypeArgument(0); + } + return null; + } + + /// + /// Gets the better conversion (C# 4.0 spec, §7.5.3.4) + /// + /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better + public int BetterConversion(IType s, IType t1, IType t2) + { + bool ident1 = IdentityConversion(s, t1); + bool ident2 = IdentityConversion(s, t2); + if (ident1 && !ident2) + return 1; + if (ident2 && !ident1) + return 2; + return BetterConversionTarget(t1, t2); + } + + /// + /// Gets the better conversion target (C# 4.0 spec, §7.5.3.5) + /// + /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better + int BetterConversionTarget(IType t1, IType t2) + { + bool t1To2 = ImplicitConversion(t1, t2); + bool t2To1 = ImplicitConversion(t2, t1); + if (t1To2 && !t2To1) + return 1; + if (t2To1 && !t1To2) + return 2; + TypeCode t1Code = ReflectionHelper.GetTypeCode(t1); + TypeCode t2Code = ReflectionHelper.GetTypeCode(t2); + if (IsBetterIntegralType(t1Code, t2Code)) + return 1; + if (IsBetterIntegralType(t2Code, t1Code)) + return 2; + return 0; + } + + bool IsBetterIntegralType(TypeCode t1, TypeCode t2) + { + // signed types are better than unsigned types + switch (t1) { + case TypeCode.SByte: + return t2 == TypeCode.Byte || t2 == TypeCode.UInt16 || t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; + case TypeCode.Int16: + return t2 == TypeCode.UInt16 || t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; + case TypeCode.Int32: + return t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; + case TypeCode.Int64: + return t2 == TypeCode.UInt64; + default: + return false; + } + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/DetectSkippableNodesNavigator.cs b/ICSharpCode.NRefactory.CSharp/Resolver/DetectSkippableNodesNavigator.cs new file mode 100644 index 000000000..454a30bc9 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/DetectSkippableNodesNavigator.cs @@ -0,0 +1,88 @@ +// 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.Collections.Generic; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// When an is searching for specific nodes + /// (e.g. all IdentifierExpressions), it has to scan the whole compilation unit for those nodes. + /// However, scanning in the ResolveVisitor is expensive (e.g. any lambda that is scanned must be resolved), + /// so it makes sense to detect when a whole subtree is scan-only, and skip that tree instead. + /// + /// The DetectSkippableNodesNavigator performs this job by running the input IResolveVisitorNavigator + /// over the whole AST, and detecting subtrees that are scan-only, and replaces them with Skip. + /// + public sealed class DetectSkippableNodesNavigator : IResolveVisitorNavigator + { + readonly Dictionary dict = new Dictionary(); + IResolveVisitorNavigator navigator; + + public DetectSkippableNodesNavigator(IResolveVisitorNavigator navigator, AstNode root) + { + this.navigator = navigator; + Init(root); + } + + bool Init(AstNode node) + { + var mode = navigator.Scan(node); + if (mode == ResolveVisitorNavigationMode.Skip) + return false; + + bool needsResolve = (mode != ResolveVisitorNavigationMode.Scan); + + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + needsResolve |= Init(child); + } + + if (needsResolve) { + // If this node or any child node needs resolving, store the mode in the dictionary. + dict.Add(node, mode); + } + return needsResolve; + } + + /// + public ResolveVisitorNavigationMode Scan(AstNode node) + { + ResolveVisitorNavigationMode mode; + if (dict.TryGetValue(node, out mode)) { + return mode; + } else { + return ResolveVisitorNavigationMode.Skip; + } + } + + /// + public void Resolved(AstNode node, ResolveResult result) + { + navigator.Resolved(node, result); + } + + /// + public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + navigator.ProcessConversion(expression, result, conversion, targetType); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs new file mode 100644 index 000000000..138453b26 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ErrorResolveResult.cs @@ -0,0 +1,43 @@ +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a resolve error. + /// + public class ErrorResolveResult : ResolveResult + { + /// + /// Gets an ErrorResolveResult instance with Type = SharedTypes.UnknownType. + /// + public static readonly ErrorResolveResult UnknownError = new ErrorResolveResult(SharedTypes.UnknownType); + + public ErrorResolveResult(IType type) : base(type) + { + } + + public override bool IsError { + get { return true; } + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferenceSearchScope.cs b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferenceSearchScope.cs new file mode 100644 index 000000000..80cc8d793 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferenceSearchScope.cs @@ -0,0 +1,51 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a scope in which references are searched. + /// + public interface IFindReferenceSearchScope + { + /// + /// Gets the search term. Only files that contain this identifier need to be parsed. + /// Can return null if all files need to be parsed. + /// + string SearchTerm { get; } + + /// + /// Gets the accessibility that defines the search scope. + /// + Accessibility Accessibility { get; } + + /// + /// Gets the top-level entity that defines the search scope. + /// + ITypeDefinition TopLevelTypeDefinition { get; } + + /// + /// Creates a navigator that can find references to this entity and reports + /// them to the specified callback. + /// + IResolveVisitorNavigator GetNavigator(FoundReferenceCallback callback); + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferencedEntities.cs b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferencedEntities.cs new file mode 100644 index 000000000..38846458c --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferencedEntities.cs @@ -0,0 +1,68 @@ +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Find all entities that are referenced in the scanned AST. + /// + public sealed class FindReferencedEntities : IResolveVisitorNavigator + { + readonly Action referenceFound; + + public FindReferencedEntities(Action referenceFound) + { + if (referenceFound == null) + throw new ArgumentNullException("referenceFound"); + this.referenceFound = referenceFound; + } + + public ResolveVisitorNavigationMode Scan(AstNode node) + { + return ResolveVisitorNavigationMode.Resolve; + } + + public void Resolved(AstNode node, ResolveResult result) + { + if (ResolveVisitor.ActsAsParenthesizedExpression(node)) + return; + + MemberResolveResult mrr = result as MemberResolveResult; + if (mrr != null) { + referenceFound(node, mrr.Member.MemberDefinition); + } + TypeResolveResult trr = result as TypeResolveResult; + if (trr != null) { + ITypeDefinition typeDef = trr.Type.GetDefinition(); + if (typeDef != null) + referenceFound(node, typeDef); + } + } + + public void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + if (conversion.IsUserDefined || conversion.IsMethodGroupConversion) { + referenceFound(expression, conversion.Method.MemberDefinition); + } + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs new file mode 100644 index 000000000..f35b56be9 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/FindReferences.cs @@ -0,0 +1,787 @@ +// 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.Collections.Generic; +using System.Linq; +using System.Threading; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public delegate void FoundReferenceCallback(AstNode astNode, ResolveResult result); + + /// + /// 'Find references' implementation. + /// + /// + /// This class is thread-safe. + /// The intended multi-threaded usage is to call GetSearchScopes() once, and then + /// call FindReferencesInFile() concurrently on multiple threads (parallel foreach over all interesting files). + /// + public sealed class FindReferences + { + #region Properties + /// + /// Gets/Sets the cancellation token. + /// + public CancellationToken CancellationToken { get; set; } + + /// + /// Gets/Sets whether to find type references even if an alias is being used. + /// + public bool FindTypeReferencesEvenIfAliased { get; set; } + #endregion + + #region GetEffectiveAccessibility + /// + /// Gets the effective accessibility of the specified entity - + /// that is, the accessibility viewed from the top level. + /// + /// + /// internal member in public class -> internal + /// public member in internal class -> internal + /// protected member in public class -> protected + /// protected member in internal class -> protected and internal + /// + public static Accessibility GetEffectiveAccessibility(IEntity entity) + { + if (entity == null) + throw new ArgumentNullException("entity"); + Accessibility a = entity.Accessibility; + for (ITypeDefinition declType = entity.DeclaringTypeDefinition; declType != null; declType = declType.DeclaringTypeDefinition) { + a = MergeAccessibility(declType.Accessibility, a); + } + return a; + } + + static Accessibility MergeAccessibility(Accessibility outer, Accessibility inner) + { + if (outer == inner) + return inner; + if (outer == Accessibility.None || inner == Accessibility.None) + return Accessibility.None; + if (outer == Accessibility.Private || inner == Accessibility.Private) + return Accessibility.Private; + if (outer == Accessibility.Public) + return inner; + if (inner == Accessibility.Public) + return outer; + // Inner and outer are both in { protected, internal, protected and internal, protected or internal } + // (but they aren't both the same) + if (outer == Accessibility.ProtectedOrInternal) + return inner; + if (inner == Accessibility.ProtectedOrInternal) + return outer; + // Inner and outer are both in { protected, internal, protected and internal }, + // but aren't both the same, so the result is protected and internal. + return Accessibility.ProtectedAndInternal; + } + #endregion + + #region class SearchScope + abstract class SearchScope : IResolveVisitorNavigator, IFindReferenceSearchScope + { + protected string searchTerm; + internal Accessibility accessibility; + internal ITypeDefinition topLevelTypeDefinition; + + FoundReferenceCallback callback; + + IResolveVisitorNavigator IFindReferenceSearchScope.GetNavigator(FoundReferenceCallback callback) + { + SearchScope n = (SearchScope)MemberwiseClone(); + n.callback = callback; + return n; + } + + string IFindReferenceSearchScope.SearchTerm { + get { return searchTerm; } + } + + Accessibility IFindReferenceSearchScope.Accessibility { + get { return accessibility; } + } + + ITypeDefinition IFindReferenceSearchScope.TopLevelTypeDefinition { + get { return topLevelTypeDefinition; } + } + + internal abstract bool CanMatch(AstNode node); + internal abstract bool IsMatch(ResolveResult rr); + + ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node) + { + if (CanMatch(node)) + return ResolveVisitorNavigationMode.Resolve; + else + return ResolveVisitorNavigationMode.Scan; + } + + void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result) + { + if (CanMatch(node) && IsMatch(result)) { + ReportMatch(node, result); + } + } + + void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + ProcessConversion(expression, result, conversion, targetType); + } + + internal virtual void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + } + + protected void ReportMatch(AstNode node, ResolveResult result) + { + if (callback != null) + callback(node, result); + } + } + #endregion + + #region GetSearchScopes + public IList GetSearchScopes(IEntity entity) + { + if (entity == null) + throw new ArgumentNullException("entity"); + Accessibility effectiveAccessibility = GetEffectiveAccessibility(entity); + ITypeDefinition topLevelTypeDefinition = entity.DeclaringTypeDefinition; + while (topLevelTypeDefinition != null && topLevelTypeDefinition.DeclaringTypeDefinition != null) + topLevelTypeDefinition = topLevelTypeDefinition.DeclaringTypeDefinition; + SearchScope scope; + SearchScope additionalScope = null; + switch (entity.EntityType) { + case EntityType.TypeDefinition: + scope = new FindTypeDefinitionReferences((ITypeDefinition)entity, this.FindTypeReferencesEvenIfAliased); + break; + case EntityType.Field: + if (entity.DeclaringTypeDefinition != null && entity.DeclaringTypeDefinition.Kind == TypeKind.Enum) + scope = new FindEnumMemberReferences((IField)entity); + else + scope = new FindFieldReferences((IField)entity); + break; + case EntityType.Property: + scope = new FindPropertyReferences((IProperty)entity); + break; + case EntityType.Event: + scope = new FindEventReferences((IEvent)entity); + break; + case EntityType.Method: + scope = GetSearchScopeForMethod((IMethod)entity); + break; + case EntityType.Indexer: + scope = new FindIndexerReferences((IProperty)entity); + break; + case EntityType.Operator: + scope = GetSearchScopeForOperator((IMethod)entity); + break; + case EntityType.Constructor: + IMethod ctor = (IMethod)entity; + scope = new FindObjectCreateReferences(ctor); + additionalScope = new FindChainedConstructorReferences(ctor); + break; + case EntityType.Destructor: + return EmptyList.Instance; + default: + throw new ArgumentException("Unknown entity type " + entity.EntityType); + } + if (scope.accessibility == Accessibility.None) + scope.accessibility = effectiveAccessibility; + scope.topLevelTypeDefinition = topLevelTypeDefinition; + if (additionalScope != null) { + if (additionalScope.accessibility == Accessibility.None) + additionalScope.accessibility = effectiveAccessibility; + additionalScope.topLevelTypeDefinition = topLevelTypeDefinition; + return new[] { scope, additionalScope }; + } else { + return new[] { scope }; + } + } + #endregion + + #region GetInterestingFileNames + /// + /// Gets the file names that possibly contain references to the element being searched for. + /// + public IList GetInterestingFileNames(IFindReferenceSearchScope searchScope, IEnumerable allTypes, ITypeResolveContext context) + { + IEnumerable interestingTypes; + if (searchScope.TopLevelTypeDefinition != null) { + switch (searchScope.Accessibility) { + case Accessibility.None: + case Accessibility.Private: + interestingTypes = new [] { searchScope.TopLevelTypeDefinition.GetDefinition() }; + break; + case Accessibility.Protected: + interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition); + break; + case Accessibility.Internal: + interestingTypes = GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent); + break; + case Accessibility.ProtectedAndInternal: + interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition) + .Intersect(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent)); + break; + case Accessibility.ProtectedOrInternal: + interestingTypes = GetInterestingTypesProtected(allTypes, context, searchScope.TopLevelTypeDefinition) + .Union(GetInterestingTypesInternal(allTypes, context, searchScope.TopLevelTypeDefinition.ProjectContent)); + break; + default: + interestingTypes = allTypes; + break; + } + } else { + interestingTypes = allTypes; + } + return (from typeDef in interestingTypes + from part in typeDef.GetParts() + where part.ParsedFile != null + select part.ParsedFile.FileName + ).Distinct(Platform.FileNameComparer).ToList(); + } + + IEnumerable GetInterestingTypesProtected(IEnumerable allTypes, ITypeResolveContext context, ITypeDefinition referencedTypeDefinition) + { + return allTypes.Where(t => t.IsDerivedFrom(referencedTypeDefinition, context)); + } + + IEnumerable GetInterestingTypesInternal(IEnumerable allTypes, ITypeResolveContext context, IProjectContent referencedProjectContent) + { + return allTypes.Where(t => referencedProjectContent.InternalsVisibleTo(t.ProjectContent, context)); + } + #endregion + + #region FindReferencesInFile + /// + /// Finds all references in the given file. + /// + /// The search scope for which to look. + /// The type system representation of the file being searched. + /// The compilation unit of the file being searched. + /// The type resolve context to use for resolving the file. + /// Callback used to report the references that were found. + public void FindReferencesInFile(IFindReferenceSearchScope searchScope, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, + ITypeResolveContext context, FoundReferenceCallback callback) + { + if (searchScope == null) + throw new ArgumentNullException("searchScope"); + FindReferencesInFile(new[] { searchScope }, parsedFile, compilationUnit, context, callback); + } + + /// + /// Finds all references in the given file. + /// + /// The search scopes for which to look. + /// The type system representation of the file being searched. + /// The compilation unit of the file being searched. + /// The type resolve context to use for resolving the file. + /// Callback used to report the references that were found. + public void FindReferencesInFile(IList searchScopes, CSharpParsedFile parsedFile, CompilationUnit compilationUnit, + ITypeResolveContext context, FoundReferenceCallback callback) + { + if (searchScopes == null) + throw new ArgumentNullException("searchScopes"); + if (parsedFile == null) + throw new ArgumentNullException("parsedFile"); + if (compilationUnit == null) + throw new ArgumentNullException("compilationUnit"); + if (context == null) + throw new ArgumentNullException("context"); + this.CancellationToken.ThrowIfCancellationRequested(); + if (searchScopes.Count == 0) + return; + using (var ctx = context.Synchronize()) { + IResolveVisitorNavigator navigator; + if (searchScopes.Count == 1) + navigator = searchScopes[0].GetNavigator(callback); + else + navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); + navigator = new DetectSkippableNodesNavigator(navigator, compilationUnit); + CSharpResolver resolver = new CSharpResolver(ctx, this.CancellationToken); + ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); + v.Scan(compilationUnit); + } + } + #endregion + + #region Find TypeDefinition References + sealed class FindTypeDefinitionReferences : SearchScope + { + ITypeDefinition typeDefinition; + + public FindTypeDefinitionReferences(ITypeDefinition typeDefinition, bool findTypeReferencesEvenIfAliased) + { + this.typeDefinition = typeDefinition; + if (!findTypeReferencesEvenIfAliased && ReflectionHelper.GetTypeCode(typeDefinition) == TypeCode.Empty) { + // not a built-in type + this.searchTerm = typeDefinition.Name; + } + } + + internal override bool CanMatch(AstNode node) + { + IdentifierExpression ident = node as IdentifierExpression; + if (ident != null) + return searchTerm == null || ident.Identifier == searchTerm; + + MemberReferenceExpression mre = node as MemberReferenceExpression; + if (mre != null) + return searchTerm == null || mre.MemberName == searchTerm; + + SimpleType st = node as SimpleType; + if (st != null) + return searchTerm == null || st.Identifier == searchTerm; + + MemberType mt = node as MemberType; + if (mt != null) + return searchTerm == null || mt.MemberName == searchTerm; + + if (searchTerm == null && node is PrimitiveType) + return true; + + return node is TypeDeclaration; + } + + internal override bool IsMatch(ResolveResult rr) + { + TypeResolveResult trr = rr as TypeResolveResult; + return trr != null && typeDefinition.Equals(trr.Type.GetDefinition()); + } + } + #endregion + + #region Find Member References + class FindMemberReferences : SearchScope + { + readonly IMember member; + + public FindMemberReferences(IMember member) + { + this.member = member.MemberDefinition; + this.searchTerm = member.Name; + } + + internal override bool CanMatch(AstNode node) + { + IdentifierExpression ident = node as IdentifierExpression; + if (ident != null) + return ident.Identifier == searchTerm; + + MemberReferenceExpression mre = node as MemberReferenceExpression; + if (mre != null) + return mre.MemberName == searchTerm; + + PointerReferenceExpression pre = node as PointerReferenceExpression; + if (pre != null) + return pre.MemberName == searchTerm; + + NamedExpression ne = node as NamedExpression; + if (ne != null) + return ne.Identifier == searchTerm; + + return false; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && member == mrr.Member.MemberDefinition; + } + } + + sealed class FindFieldReferences : FindMemberReferences + { + public FindFieldReferences(IField field) : base(field) + { + } + + internal override bool CanMatch(AstNode node) + { + return node is FieldDeclaration || node is VariableInitializer || base.CanMatch(node); + } + } + + sealed class FindEnumMemberReferences : FindMemberReferences + { + public FindEnumMemberReferences(IField field) : base(field) + { + } + + internal override bool CanMatch(AstNode node) + { + return node is EnumMemberDeclaration || base.CanMatch(node); + } + } + + sealed class FindPropertyReferences : FindMemberReferences + { + public FindPropertyReferences(IProperty property) : base(property) + { + } + + internal override bool CanMatch(AstNode node) + { + return node is PropertyDeclaration || base.CanMatch(node); + } + } + + sealed class FindEventReferences : FindMemberReferences + { + public FindEventReferences(IEvent ev) : base(ev) + { + } + + internal override bool CanMatch(AstNode node) + { + return node is EventDeclaration || base.CanMatch(node); + } + } + #endregion + + #region Find Method References + SearchScope GetSearchScopeForMethod(IMethod method) + { + switch (method.Name) { + case "Add": + return new FindMethodReferences(method, typeof(ArrayInitializerExpression)); + case "Where": + return new FindMethodReferences(method, typeof(QueryWhereClause)); + case "Select": + return new FindMethodReferences(method, typeof(QuerySelectClause)); + case "SelectMany": + return new FindMethodReferences(method, typeof(QueryFromClause)); + case "Join": + case "GroupJoin": + return new FindMethodReferences(method, typeof(QueryJoinClause)); + case "OrderBy": + case "OrderByDescending": + case "ThenBy": + case "ThenByDescending": + return new FindMethodReferences(method, typeof(QueryOrdering)); + case "GroupBy": + return new FindMethodReferences(method, typeof(QueryGroupClause)); + default: + return new FindMethodReferences(method); + } + } + + sealed class FindMethodReferences : SearchScope + { + readonly IMethod method; + readonly Type specialNodeType; + + public FindMethodReferences(IMethod method, Type specialNodeType = null) + { + this.method = (IMethod)method.MemberDefinition; + this.specialNodeType = specialNodeType; + if (specialNodeType == null) + this.searchTerm = method.Name; + } + + internal override bool CanMatch(AstNode node) + { + InvocationExpression ie = node as InvocationExpression; + if (ie != null) { + Expression target = ResolveVisitor.UnpackParenthesizedExpression(ie.Target); + + IdentifierExpression ident = target as IdentifierExpression; + if (ident != null) + return ident.Identifier == method.Name; + + MemberReferenceExpression mre = target as MemberReferenceExpression; + if (mre != null) + return mre.MemberName == method.Name; + + PointerReferenceExpression pre = target as PointerReferenceExpression; + if (pre != null) + return pre.MemberName == method.Name; + } + if (node is MethodDeclaration) + return true; + if (specialNodeType != null) + return specialNodeType.IsInstanceOfType(node); + else + return false; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && method == mrr.Member.MemberDefinition; + } + } + #endregion + + #region Find Indexer References + sealed class FindIndexerReferences : SearchScope + { + readonly IProperty indexer; + + public FindIndexerReferences(IProperty indexer) + { + this.indexer = (IProperty)indexer.MemberDefinition; + } + + internal override bool CanMatch(AstNode node) + { + return node is IndexerExpression || node is IndexerDeclaration; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && indexer == mrr.Member.MemberDefinition; + } + } + #endregion + + #region Find Operator References + SearchScope GetSearchScopeForOperator(IMethod op) + { + OperatorType? opType = OperatorDeclaration.GetOperatorType(op.Name); + if (opType == null) + return new FindMethodReferences(op); + switch (opType.Value) { + case OperatorType.LogicalNot: + return new FindUnaryOperator(op, UnaryOperatorType.Not); + case OperatorType.OnesComplement: + return new FindUnaryOperator(op, UnaryOperatorType.BitNot); + case OperatorType.UnaryPlus: + return new FindUnaryOperator(op, UnaryOperatorType.Plus); + case OperatorType.UnaryNegation: + return new FindUnaryOperator(op, UnaryOperatorType.Minus); + case OperatorType.Increment: + return new FindUnaryOperator(op, UnaryOperatorType.Increment); + case OperatorType.Decrement: + return new FindUnaryOperator(op, UnaryOperatorType.Decrement); + case OperatorType.True: + case OperatorType.False: + // TODO: implement search for op_True/op_False correctly + return new FindMethodReferences(op); + case OperatorType.Addition: + return new FindBinaryOperator(op, BinaryOperatorType.Add); + case OperatorType.Subtraction: + return new FindBinaryOperator(op, BinaryOperatorType.Subtract); + case OperatorType.Multiply: + return new FindBinaryOperator(op, BinaryOperatorType.Multiply); + case OperatorType.Division: + return new FindBinaryOperator(op, BinaryOperatorType.Divide); + case OperatorType.Modulus: + return new FindBinaryOperator(op, BinaryOperatorType.Modulus); + case OperatorType.BitwiseAnd: + // TODO: an overloaded bitwise operator can also be called using the corresponding logical operator + // (if op_True/op_False is defined) + return new FindBinaryOperator(op, BinaryOperatorType.BitwiseAnd); + case OperatorType.BitwiseOr: + return new FindBinaryOperator(op, BinaryOperatorType.BitwiseOr); + case OperatorType.ExclusiveOr: + return new FindBinaryOperator(op, BinaryOperatorType.ExclusiveOr); + case OperatorType.LeftShift: + return new FindBinaryOperator(op, BinaryOperatorType.ShiftLeft); + case OperatorType.RightShift: + return new FindBinaryOperator(op, BinaryOperatorType.ShiftRight); + case OperatorType.Equality: + return new FindBinaryOperator(op, BinaryOperatorType.Equality); + case OperatorType.Inequality: + return new FindBinaryOperator(op, BinaryOperatorType.InEquality); + case OperatorType.GreaterThan: + return new FindBinaryOperator(op, BinaryOperatorType.GreaterThan); + case OperatorType.LessThan: + return new FindBinaryOperator(op, BinaryOperatorType.LessThan); + case OperatorType.GreaterThanOrEqual: + return new FindBinaryOperator(op, BinaryOperatorType.GreaterThanOrEqual); + case OperatorType.LessThanOrEqual: + return new FindBinaryOperator(op, BinaryOperatorType.LessThanOrEqual); + case OperatorType.Implicit: + return new FindImplicitOperator(op); + case OperatorType.Explicit: + return new FindExplicitOperator(op); + default: + throw new InvalidOperationException("Invalid value for OperatorType"); + } + } + + sealed class FindUnaryOperator : SearchScope + { + readonly IMethod op; + readonly UnaryOperatorType operatorType; + + public FindUnaryOperator(IMethod op, UnaryOperatorType operatorType) + { + this.op = op; + this.operatorType = operatorType; + } + + internal override bool CanMatch(AstNode node) + { + UnaryOperatorExpression uoe = node as UnaryOperatorExpression; + if (uoe != null) { + if (operatorType == UnaryOperatorType.Increment) + return uoe.Operator == UnaryOperatorType.Increment || uoe.Operator == UnaryOperatorType.PostIncrement; + else if (operatorType == UnaryOperatorType.Decrement) + return uoe.Operator == UnaryOperatorType.Decrement || uoe.Operator == UnaryOperatorType.PostDecrement; + else + return uoe.Operator == operatorType; + } + return node is OperatorDeclaration; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && op == mrr.Member.MemberDefinition; + } + } + + sealed class FindBinaryOperator : SearchScope + { + readonly IMethod op; + readonly BinaryOperatorType operatorType; + + public FindBinaryOperator(IMethod op, BinaryOperatorType operatorType) + { + this.op = op; + this.operatorType = operatorType; + } + + internal override bool CanMatch(AstNode node) + { + BinaryOperatorExpression boe = node as BinaryOperatorExpression; + if (boe != null) { + return boe.Operator == operatorType; + } + return node is OperatorDeclaration; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && op == mrr.Member.MemberDefinition; + } + } + + sealed class FindImplicitOperator : SearchScope + { + readonly IMethod op; + + public FindImplicitOperator(IMethod op) + { + this.op = op; + } + + internal override bool CanMatch(AstNode node) + { + return true; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && op == mrr.Member.MemberDefinition; + } + + internal override void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + if (conversion.IsUserDefined && conversion.Method.MemberDefinition == op) { + ReportMatch(expression, result); + } + } + } + + sealed class FindExplicitOperator : SearchScope + { + readonly IMethod op; + + public FindExplicitOperator(IMethod op) + { + this.op = op; + } + + internal override bool CanMatch(AstNode node) + { + return node is CastExpression; + } + + internal override bool IsMatch(ResolveResult rr) + { + ConversionResolveResult crr = rr as ConversionResolveResult; + return crr != null && crr.Conversion.IsUserDefined && crr.Conversion.Method.MemberDefinition == op; + } + } + #endregion + + #region Find Constructor References + sealed class FindObjectCreateReferences : SearchScope + { + readonly IMethod ctor; + + public FindObjectCreateReferences(IMethod ctor) + { + this.ctor = (IMethod)ctor.MemberDefinition; + if (ReflectionHelper.GetTypeCode(ctor.DeclaringTypeDefinition) == TypeCode.Empty) { + // not a built-in type + this.searchTerm = ctor.DeclaringTypeDefinition.Name; + } + } + + internal override bool CanMatch(AstNode node) + { + return node is ObjectCreateExpression || node is ConstructorDeclaration; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && ctor == mrr.Member.MemberDefinition; + } + } + + sealed class FindChainedConstructorReferences : SearchScope + { + readonly IMethod ctor; + + public FindChainedConstructorReferences(IMethod ctor) + { + this.ctor = (IMethod)ctor.MemberDefinition; + if (ctor.DeclaringTypeDefinition.IsSealed) + this.accessibility = Accessibility.Private; + else + this.accessibility = Accessibility.Protected; + this.accessibility = MergeAccessibility(GetEffectiveAccessibility(ctor), this.accessibility); + } + + internal override bool CanMatch(AstNode node) + { + return node is ConstructorInitializer; + } + + internal override bool IsMatch(ResolveResult rr) + { + MemberResolveResult mrr = rr as MemberResolveResult; + return mrr != null && ctor == mrr.Member.MemberDefinition; + } + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/IResolveVisitorNavigator.cs b/ICSharpCode.NRefactory.CSharp/Resolver/IResolveVisitorNavigator.cs new file mode 100644 index 000000000..7a568cc41 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/IResolveVisitorNavigator.cs @@ -0,0 +1,104 @@ +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Allows controlling which nodes are resolved by the resolve visitor. + /// + /// + public interface IResolveVisitorNavigator + { + /// + /// Asks the navigator whether to scan, skip, or resolve a node. + /// + ResolveVisitorNavigationMode Scan(AstNode node); + + /// + /// Notifies the navigator that a node was resolved. + /// + /// The node that was resolved + /// Resolve result + void Resolved(AstNode node, ResolveResult result); + + /// + /// Notifies the navigator that a conversion was applied. + /// + /// The expression that was resolved. + /// The resolve result of the expression. + /// The conversion applied to the expressed. + /// The target type of the conversion. + void ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType); + } + + /// + /// Represents the operation mode of the resolve visitor. + /// + /// + public enum ResolveVisitorNavigationMode + { + /// + /// Scan into the children of the current node, without resolving the current node. + /// + Scan, + /// + /// Skip the current node - do not scan into it; do not resolve it. + /// + Skip, + /// + /// Resolve the current node. + /// Subnodes which are not required for resolving the current node + /// will ask the navigator again whether they should be resolved. + /// + Resolve + } + + sealed class ConstantModeResolveVisitorNavigator : IResolveVisitorNavigator + { + readonly ResolveVisitorNavigationMode mode; + readonly IResolveVisitorNavigator targetForResolveCalls; + + public ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode mode, IResolveVisitorNavigator targetForResolveCalls) + { + this.mode = mode; + this.targetForResolveCalls = targetForResolveCalls; + } + + + ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node) + { + return mode; + } + + void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result) + { + if (targetForResolveCalls != null) + targetForResolveCalls.Resolved(node, result); + } + + void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + if (targetForResolveCalls != null) + targetForResolveCalls.ProcessConversion(expression, result, conversion, targetType); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ITypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ITypeOrNamespaceReference.cs new file mode 100644 index 000000000..f5ebaf384 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ITypeOrNamespaceReference.cs @@ -0,0 +1,40 @@ +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents a reference which could point to a type or namespace. + /// + public interface ITypeOrNamespaceReference : ITypeReference + { + /// + /// Resolves the reference and returns the ResolveResult. + /// + ResolveResult DoResolve(ITypeResolveContext context); + + /// + /// Returns the namespace that is referenced; or null if no such namespace is found. + /// + NamespaceResolveResult ResolveNamespace(ITypeResolveContext context); + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs new file mode 100644 index 000000000..5c25cd5c2 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/LambdaResolveResult.cs @@ -0,0 +1,77 @@ +// 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.Collections.Generic; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Represents an anonymous method or lambda expression. + /// + public abstract class LambdaResolveResult : ResolveResult + { + protected LambdaResolveResult() : base(SharedTypes.UnknownType) + { + } + + /// + /// Gets whether there is a parameter list. + /// This property always returns true for C# 3.0-lambdas, but may return false + /// for C# 2.0 anonymous methods. + /// + public abstract bool HasParameterList { get; } + + /// + /// Gets whether this lambda is using the C# 2.0 anonymous method syntax. + /// + public abstract bool IsAnonymousMethod { get; } + + /// + /// Gets whether the lambda parameters are implicitly typed. + /// + /// This property returns false for anonymous methods without parameter list. + public abstract bool IsImplicitlyTyped { get; } + + /// + /// Gets whether the lambda is async. + /// + public abstract bool IsAsync { get; } + + /// + /// Gets the return type inferred when the parameter types are inferred to be + /// + public abstract IType GetInferredReturnType(IType[] parameterTypes); + + /// + /// Gets the list of parameters. + /// + public abstract IList Parameters { get; } + + /// + /// Gets whether the lambda body is valid for the given parameter types and return type. + /// + /// + /// Produces a if the lambda is valid; + /// otherwise returns . + /// + public abstract Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions); + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/Log.cs b/ICSharpCode.NRefactory.CSharp/Resolver/Log.cs new file mode 100644 index 000000000..d0cf0a868 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/Log.cs @@ -0,0 +1,80 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Resolver logging helper. + /// Wraps System.Diagnostics.Debug so that resolver-specific logging can be enabled/disabled on demand. + /// (it's a huge amount of debug spew and slows down the resolver quite a bit) + /// + static class Log + { + const bool logEnabled = false; + +// [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] + internal static void WriteLine(string text) + { + Debug.WriteLine(text); + } + +// [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] + internal static void WriteLine(string format, params object[] args) + { + Debug.WriteLine(format, args); + } + +// [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] + internal static void WriteCollection(string text, IEnumerable lines) + { + #if DEBUG + T[] arr = lines.ToArray(); + if (arr.Length == 0) { + Debug.WriteLine(text + ""); + } else { + Debug.WriteLine(text + (arr[0] != null ? arr[0].ToString() : "")); + for (int i = 1; i < arr.Length; i++) { + Debug.WriteLine(new string(' ', text.Length) + (arr[i] != null ? arr[i].ToString() : "")); + } + } + #endif + } + +// [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] + public static void Indent() + { + Debug.Indent(); + } + +// [Conditional(logEnabled ? "DEBUG" : "LOG_DISABLED")] + public static void Unindent() + { + Debug.Unindent(); + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MapTypeIntoNewContext.cs similarity index 56% rename from ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/MapTypeIntoNewContext.cs index 14cc7ccb1..c4c03a7c9 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MapTypeIntoNewContext.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/MapTypeIntoNewContext.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.TypeSystem; diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs new file mode 100644 index 000000000..5b924bb79 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/MemberLookup.cs @@ -0,0 +1,569 @@ +// 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.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Implementation of member lookup (C# 4.0 spec, §7.4). + /// + public class MemberLookup + { + #region Static helper methods + /// + /// Gets whether the member is considered to be invocable. + /// + public static bool IsInvocable(IMember member, ITypeResolveContext context) + { + if (member == null) + throw new ArgumentNullException("member"); + // C# 4.0 spec, §7.4 member lookup + if (member is IEvent || member is IMethod) + return true; + IType returnType = member.ReturnType.Resolve(context); + if (returnType == SharedTypes.Dynamic) + return true; + return returnType.Kind == TypeKind.Delegate; + } + #endregion + + ITypeResolveContext context; + ITypeDefinition currentTypeDefinition; + IProjectContent currentProject; + + public MemberLookup(ITypeResolveContext context, ITypeDefinition currentTypeDefinition, IProjectContent currentProject) + { + if (context == null) + throw new ArgumentNullException("context"); + this.context = context; + this.currentTypeDefinition = currentTypeDefinition; + this.currentProject = currentProject; + } + + #region IsAccessible + /// + /// Gets whether access to protected instance members of the target type is possible. + /// + public bool IsProtectedAccessAllowed(IType targetType) + { + ITypeDefinition typeDef = targetType.GetDefinition(); + return typeDef != null && typeDef.IsDerivedFrom(currentTypeDefinition, context); + } + + /// + /// Gets whether is accessible in the current class. + /// + /// The entity to test + /// + /// Whether protected access to instance members is allowed. + /// True if the type of the reference is derived from the current class. + /// Protected static members may be accessibe even if false is passed for this parameter. + /// + public bool IsAccessible(IEntity entity, bool allowProtectedAccess) + { + if (entity == null) + throw new ArgumentNullException("entity"); + // C# 4.0 spec, §3.5.2 Accessiblity domains + switch (entity.Accessibility) { + case Accessibility.None: + return false; + case Accessibility.Private: + // check for members of outer classes (private members of outer classes can be accessed) + var lookupTypeDefinition = currentTypeDefinition; + while (lookupTypeDefinition != null) { + if (entity.DeclaringTypeDefinition.Equals (lookupTypeDefinition)) + return true; + lookupTypeDefinition = lookupTypeDefinition.DeclaringTypeDefinition; + } + return false; + case Accessibility.Public: + return true; + case Accessibility.Protected: + // For static members and type definitions, we do not require the qualifying reference + // to be derived from the current class (allowProtectedAccess). + return (allowProtectedAccess || entity.IsStatic || entity.EntityType == EntityType.TypeDefinition) + && IsProtectedAccessible(entity.DeclaringTypeDefinition); + case Accessibility.Internal: + return IsInternalAccessible(entity.ProjectContent); + case Accessibility.ProtectedOrInternal: + return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) + || IsInternalAccessible(entity.ProjectContent); + case Accessibility.ProtectedAndInternal: + return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) + && IsInternalAccessible(entity.ProjectContent); + default: + throw new Exception("Invalid value for Accessibility"); + } + } + + bool IsInternalAccessible(IProjectContent declaringProject) + { + return declaringProject != null && currentProject != null && declaringProject.InternalsVisibleTo(currentProject, context); + } + + bool IsProtectedAccessible(ITypeDefinition declaringType) + { + if (declaringType.Equals (currentTypeDefinition)) + return true; + // PERF: this might hurt performance as this method is called several times (once for each member) + // make sure resolving base types is cheap (caches?) or cache within the MemberLookup instance + return currentTypeDefinition != null && currentTypeDefinition.IsDerivedFrom(declaringType, context); + } + #endregion + + #region class LookupGroup + sealed class LookupGroup + { + public readonly IType DeclaringType; + + // When a nested type is hidden, it is simply removed from the list. + public List NestedTypes; + + // When members are hidden, they are merely marked as hidden. + // We still need to store the hidden methods so that the 'override' processing can + // find them, so that it won't introduce the override as a new method. + public readonly List Methods; + public bool MethodsAreHidden; + + public IMember NonMethod; + public bool NonMethodIsHidden; + + public LookupGroup(IType declaringType, List nestedTypes, List methods, IMember nonMethod) + { + this.DeclaringType = declaringType; + this.NestedTypes = nestedTypes; + this.Methods = methods; + this.NonMethod = nonMethod; + this.MethodsAreHidden = (methods == null || methods.Count == 0); + this.NonMethodIsHidden = (nonMethod == null); + } + + public bool AllHidden { + get { + if (NestedTypes != null && NestedTypes.Count > 0) + return false; + return NonMethodIsHidden && MethodsAreHidden; + } + } + } + #endregion + + #region LookupType + public ResolveResult LookupType(IType declaringType, string name, IList typeArguments, bool parameterizeResultType = true) + { + if (declaringType == null) + throw new ArgumentNullException("declaringType"); + if (name == null) + throw new ArgumentNullException("name"); + if (typeArguments == null) + throw new ArgumentNullException("typeArguments"); + + int typeArgumentCount = typeArguments.Count; + Predicate filter = delegate (ITypeDefinition d) { + return InnerTypeParameterCount(d) == typeArgumentCount && d.Name == name && IsAccessible(d, true); + }; + + List lookupGroups = new List(); + if (declaringType.Kind != TypeKind.TypeParameter) { + foreach (IType type in declaringType.GetNonInterfaceBaseTypes(context)) { + List newNestedTypes = null; + IEnumerable typeBaseTypes = null; + + IEnumerable nestedTypes; + if (parameterizeResultType) { + nestedTypes = type.GetNestedTypes(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); + } else { + nestedTypes = type.GetNestedTypes(context, filter, GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions); + } + AddNestedTypes(type, nestedTypes, typeArgumentCount, lookupGroups, ref typeBaseTypes, ref newNestedTypes); + + if (newNestedTypes != null) + lookupGroups.Add(new LookupGroup(type, newNestedTypes, null, null)); + } + } + + lookupGroups.RemoveAll(g => g.AllHidden); + Debug.Assert(lookupGroups.All(g => g.NestedTypes != null && g.NestedTypes.Count > 0)); + + if (lookupGroups.Count == 0) { + return new UnknownMemberResolveResult(declaringType, name, typeArguments); + } + + LookupGroup resultGroup = lookupGroups[lookupGroups.Count - 1]; + + if (resultGroup.NestedTypes.Count > 1 || lookupGroups.Count > 1) + return new AmbiguousTypeResolveResult(resultGroup.NestedTypes[0]); + else + return new TypeResolveResult(resultGroup.NestedTypes[0]); + } + + static int InnerTypeParameterCount(IType type) + { + // inner types contain the type parameters of outer types. therefore this count has to been adjusted. + return type.TypeParameterCount - (type.DeclaringType != null ? type.DeclaringType.TypeParameterCount : 0); + } + #endregion + + #region Lookup + /// + /// Performs a member lookup. + /// + public ResolveResult Lookup(ResolveResult targetResolveResult, string name, IList typeArguments, bool isInvocation) + { + if (targetResolveResult == null) + throw new ArgumentNullException("targetResolveResult"); + if (name == null) + throw new ArgumentNullException("name"); + if (typeArguments == null) + throw new ArgumentNullException("typeArguments"); + + bool targetIsTypeParameter = targetResolveResult.Type.Kind == TypeKind.TypeParameter; + + bool allowProtectedAccess = IsProtectedAccessAllowed(targetResolveResult.Type); + Predicate filter = delegate(IEntity entity) { + return entity.Name == name && IsAccessible(entity, allowProtectedAccess); + }; + + List lookupGroups = new List(); + // This loop will handle base types before derived types. + // The loop performs three jobs: + // 1) It marks entries in lookup groups from base classes as removed when those members + // are hidden by a derived class. + // 2) It adds a new lookup group with the members from a declaring type. + // 3) It replaces virtual members with the overridden version, placing the override in the + // lookup group belonging to the base class. + foreach (IType type in targetResolveResult.Type.GetNonInterfaceBaseTypes(context)) { + + List newNestedTypes = null; + List newMethods = null; + IMember newNonMethod = null; + + IEnumerable typeBaseTypes = null; + + if (!isInvocation && !targetIsTypeParameter) { + // Consider nested types only if it's not an invocation. + // type.GetNestedTypes() is checking the type parameter count for an exact match, + // so we don't need to do that in our filter. + var nestedTypes = type.GetNestedTypes(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); + AddNestedTypes(type, nestedTypes, typeArguments.Count, lookupGroups, ref typeBaseTypes, ref newNestedTypes); + } + + IEnumerable members; + if (typeArguments.Count == 0) { + // Note: IsInvocable-checking cannot be done as part of the filter; + // because it must be done after type substitution. + members = type.GetMembers(context, filter, GetMemberOptions.IgnoreInheritedMembers); + if (isInvocation) + members = members.Where(m => IsInvocable(m, context)); + } else { + // No need to check for isInvocation/isInvocable here: + // we only fetch methods + members = type.GetMethods(typeArguments, context, filter, GetMemberOptions.IgnoreInheritedMembers); + } + AddMembers(type, members, lookupGroups, false, ref typeBaseTypes, ref newMethods, ref newNonMethod); + + if (newNestedTypes != null || newMethods != null || newNonMethod != null) + lookupGroups.Add(new LookupGroup(type, newNestedTypes, newMethods, newNonMethod)); + } + + // Remove interface members hidden by class members. + if (targetIsTypeParameter) { + // This can happen only with type parameters. + RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); + } + + return CreateResult(targetResolveResult, lookupGroups, name, typeArguments); + } + #endregion + + #region Lookup Indexer + /// + /// Looks up the indexers on the target type. + /// + public IList LookupIndexers(IType targetType) + { + if (targetType == null) + throw new ArgumentNullException("targetType"); + + bool allowProtectedAccess = IsProtectedAccessAllowed(targetType); + Predicate filter = delegate(IProperty property) { + return property.IsIndexer && IsAccessible(property, allowProtectedAccess); + }; + + List lookupGroups = new List(); + foreach (IType type in targetType.GetNonInterfaceBaseTypes(context)) { + List newMethods = null; + IMember newNonMethod = null; + + IEnumerable typeBaseTypes = null; + + var members = type.GetProperties(context, filter, GetMemberOptions.IgnoreInheritedMembers); + AddMembers(type, members, lookupGroups, true, ref typeBaseTypes, ref newMethods, ref newNonMethod); + + if (newMethods != null || newNonMethod != null) + lookupGroups.Add(new LookupGroup(type, null, newMethods, newNonMethod)); + } + + // Remove interface members hidden by class members. + if (targetType.Kind == TypeKind.TypeParameter) { + // This can happen only with type parameters. + RemoveInterfaceMembersHiddenByClassMembers(lookupGroups); + } + + // Remove all hidden groups + lookupGroups.RemoveAll(g => g.MethodsAreHidden || g.Methods.Count == 0); + + MethodListWithDeclaringType[] methodLists = new MethodListWithDeclaringType[lookupGroups.Count]; + for (int i = 0; i < methodLists.Length; i++) { + methodLists[i] = new MethodListWithDeclaringType(lookupGroups[i].DeclaringType, lookupGroups[i].Methods); + } + return methodLists; + } + #endregion + + #region AddNestedTypes + /// + /// Adds the nested types to 'newNestedTypes' and removes any hidden members from the existing lookup groups. + /// + /// Declaring type of the nested types + /// List of nested types to add. + /// The number of type arguments - used for hiding types from the base class + /// List of existing lookup groups + /// The base types of 'type' (initialized on demand) + /// The target list (created on demand). + void AddNestedTypes(IType type, IEnumerable nestedTypes, int typeArgumentCount, + List lookupGroups, + ref IEnumerable typeBaseTypes, + ref List newNestedTypes) + { + foreach (IType nestedType in nestedTypes) { + // Remove all non-types declared in a base type of 'type', + // and all types with same number of type parameters declared in a base type of 'type'. + foreach (var lookupGroup in lookupGroups) { + if (lookupGroup.AllHidden) + continue; // everything is already hidden + if (typeBaseTypes == null) + typeBaseTypes = type.GetNonInterfaceBaseTypes(context); + + if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { + lookupGroup.MethodsAreHidden = true; + lookupGroup.NonMethodIsHidden = true; + if (lookupGroup.NestedTypes != null) + lookupGroup.NestedTypes.RemoveAll(t => InnerTypeParameterCount(t) == typeArgumentCount); + } + } + + // Add the new nested type. + if (newNestedTypes == null) + newNestedTypes = new List(); + newNestedTypes.Add(nestedType); + } + } + #endregion + + #region AddMembers + /// + /// Adds members to 'newMethods'/'newNonMethod'. + /// Removes any members in the existing lookup groups that were hidden by added members. + /// Substitutes 'virtual' members in the existing lookup groups for added 'override' members. + /// + /// Declaring type of the members + /// List of members to add. + /// List of existing lookup groups + /// Whether to treat properties as methods + /// The base types of 'type' (initialized on demand) + /// The target list for methods (created on demand). + /// The target variable for non-method members. + void AddMembers(IType type, IEnumerable members, List lookupGroups, + bool treatAllParameterizedMembersAsMethods, + ref IEnumerable typeBaseTypes, ref List newMethods, ref IMember newNonMethod) + { + foreach (IMember member in members) { + IParameterizedMember method; + if (treatAllParameterizedMembersAsMethods) + method = member as IParameterizedMember; + else + method = member as IMethod; + + bool replacedVirtualMemberWithOverride = false; + if (member.IsOverride) { + // Replacing virtual member with override: + + // Go backwards so that we find the corresponding virtual member + // in the most-derived type + for (int i = lookupGroups.Count - 1; i >= 0 && !replacedVirtualMemberWithOverride; i--) { + if (typeBaseTypes == null) + typeBaseTypes = type.GetNonInterfaceBaseTypes(context); + + var lookupGroup = lookupGroups[i]; + if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { + if (method != null) { + // Find the matching method, and replace it with the override + for (int j = 0; j < lookupGroup.Methods.Count; j++) { + if (ParameterListComparer.Compare(context, method, lookupGroup.Methods[j])) { + lookupGroup.Methods[j] = method; + replacedVirtualMemberWithOverride = true; + break; + } + } + } else { + // If the member type matches, replace it with the override + if (lookupGroup.NonMethod != null && lookupGroup.NonMethod.EntityType == member.EntityType) { + lookupGroup.NonMethod = member; + replacedVirtualMemberWithOverride = true; + break; + } + } + } + } + } + // If the member wasn't an override, or if we didn't find any matching virtual method, + // proceed to add the member. + if (!replacedVirtualMemberWithOverride) { + // Make the member hide other members: + foreach (var lookupGroup in lookupGroups) { + if (lookupGroup.AllHidden) + continue; // everything is already hidden + if (typeBaseTypes == null) + typeBaseTypes = type.GetNonInterfaceBaseTypes(context); + + if (typeBaseTypes.Contains(lookupGroup.DeclaringType)) { + // Methods hide all non-methods; Non-methods hide everything + lookupGroup.NestedTypes = null; + lookupGroup.NonMethodIsHidden = true; + if (method == null) { // !(member is IMethod) + lookupGroup.MethodsAreHidden = true; + } + } + } + + // Add the new member + if (method != null) { + if (newMethods == null) + newMethods = new List(); + newMethods.Add(method); + } else { + newNonMethod = member; + } + } + } + } + #endregion + + #region RemoveInterfaceMembersHiddenByClassMembers + void RemoveInterfaceMembersHiddenByClassMembers(List lookupGroups) + { + foreach (var classLookupGroup in lookupGroups) { + if (IsInterfaceOrSystemObject(classLookupGroup.DeclaringType)) + continue; + // The current lookup groups contains class members that might hide interface members + bool hasNestedTypes = classLookupGroup.NestedTypes != null && classLookupGroup.NestedTypes.Count > 0; + if (hasNestedTypes || !classLookupGroup.NonMethodIsHidden) { + // Hide all members from interface types + foreach (var interfaceLookupGroup in lookupGroups) { + if (IsInterfaceOrSystemObject(interfaceLookupGroup.DeclaringType)) { + interfaceLookupGroup.NestedTypes = null; + interfaceLookupGroup.NonMethodIsHidden = true; + interfaceLookupGroup.MethodsAreHidden = true; + } + } + } else if (!classLookupGroup.MethodsAreHidden) { + foreach (IMethod classMethod in classLookupGroup.Methods) { + // Hide all non-methods from interface types, and all methods with the same signature + // as a method in this class type. + foreach (var interfaceLookupGroup in lookupGroups) { + if (IsInterfaceOrSystemObject(interfaceLookupGroup.DeclaringType)) { + interfaceLookupGroup.NestedTypes = null; + interfaceLookupGroup.NonMethodIsHidden = true; + if (interfaceLookupGroup.Methods != null && !interfaceLookupGroup.MethodsAreHidden) { + // The mapping of virtual to overridden methods is already done, + // so we can simply remove the methods from the collection + interfaceLookupGroup.Methods.RemoveAll( + m => ParameterListComparer.Compare(context, classMethod, m)); + } + } + } + } + } + } + } + + static bool IsInterfaceOrSystemObject(IType type) + { + // return if type is an interface or System.Object + return type.Kind == TypeKind.Interface + || (type.Name == "Object" && type.Namespace == "System" && type.TypeParameterCount == 0); + } + #endregion + + #region CreateResult + ResolveResult CreateResult(ResolveResult targetResolveResult, List lookupGroups, string name, IList typeArguments) + { + // Remove all hidden groups + lookupGroups.RemoveAll(g => g.AllHidden); + + if (lookupGroups.Count == 0) { + // No members found + return new UnknownMemberResolveResult(targetResolveResult.Type, name, typeArguments); + } + + if (lookupGroups.Any(g => !g.MethodsAreHidden && g.Methods.Count > 0)) { + // If there are methods, make a MethodGroupResolveResult. + // Note that a conflict between a member and a method (possible with multiple interface inheritance) + // is only a warning, not an error, and the C# compiler will prefer the method group. + List methodLists = new List(); + foreach (var lookupGroup in lookupGroups) { + if (!lookupGroup.MethodsAreHidden && lookupGroup.Methods.Count > 0) { + var methodListWithDeclType = new MethodListWithDeclaringType(lookupGroup.DeclaringType); + foreach (var method in lookupGroup.Methods) { + methodListWithDeclType.Add((IMethod)method); + } + methodLists.Add(methodListWithDeclType); + } + } + + return new MethodGroupResolveResult(targetResolveResult, name, methodLists, typeArguments); + } + + // If there are ambiguities, report the most-derived result (last group) + LookupGroup resultGroup = lookupGroups[lookupGroups.Count - 1]; + if (resultGroup.NestedTypes != null && resultGroup.NestedTypes.Count > 0) { + if (resultGroup.NestedTypes.Count > 1 || !resultGroup.NonMethodIsHidden || lookupGroups.Count > 1) + return new AmbiguousTypeResolveResult(resultGroup.NestedTypes[0]); + else + return new TypeResolveResult(resultGroup.NestedTypes[0]); + } + + if (lookupGroups.Count > 1) { + return new AmbiguousMemberResolveResult(targetResolveResult, resultGroup.NonMethod, + resultGroup.NonMethod.ReturnType.Resolve(context)); + } else { + return new MemberResolveResult(targetResolveResult, resultGroup.NonMethod, context); + } + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs new file mode 100644 index 000000000..6bc3ea87e --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/MemberTypeOrNamespaceReference.cs @@ -0,0 +1,151 @@ +// 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.Collections.Generic; +using System.Collections.ObjectModel; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Reference to a qualified type or namespace name. + /// + [Serializable] + public sealed class MemberTypeOrNamespaceReference : ITypeOrNamespaceReference, ISupportsInterning + { + ITypeOrNamespaceReference target; + readonly ITypeDefinition parentTypeDefinition; + readonly UsingScope parentUsingScope; + string identifier; + IList typeArguments; + + public MemberTypeOrNamespaceReference(ITypeOrNamespaceReference target, string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope) + { + if (target == null) + throw new ArgumentNullException("target"); + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.target = target; + this.identifier = identifier; + this.typeArguments = typeArguments ?? EmptyList.Instance; + this.parentTypeDefinition = parentTypeDefinition; + this.parentUsingScope = parentUsingScope; + } + + public string Identifier { + get { return identifier; } + } + + public ITypeOrNamespaceReference Target { + get { return target; } + } + + public IList TypeArguments { + get { return new ReadOnlyCollection(typeArguments); } + } + + /// + /// Adds a suffix to the identifier. + /// Does not modify the existing type reference, but returns a new one. + /// + public MemberTypeOrNamespaceReference AddSuffix(string suffix) + { + return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope); + } + + public ResolveResult DoResolve(ITypeResolveContext context) + { + CacheManager cacheManager = context.CacheManager; + if (cacheManager != null) { + ResolveResult cachedResult = cacheManager.GetShared(this) as ResolveResult;; + if (cachedResult != null) + return cachedResult; + } + + ResolveResult targetRR = target.DoResolve(context); + if (targetRR.IsError) + return targetRR; + CSharpResolver r = new CSharpResolver(context); + r.CurrentTypeDefinition = parentTypeDefinition; + r.CurrentUsingScope = parentUsingScope; + IType[] typeArgs = new IType[typeArguments.Count]; + for (int i = 0; i < typeArgs.Length; i++) { + typeArgs[i] = typeArguments[i].Resolve(context); + } + ResolveResult rr = r.ResolveMemberType(targetRR, identifier, typeArgs); + if (cacheManager != null) + cacheManager.SetShared(this, rr); + return rr; + } + + public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible + return DoResolve(context) as NamespaceResolveResult; + } + + public IType Resolve(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible; then map the result type into the new context + TypeResolveResult rr = DoResolve(context) as TypeResolveResult; + return rr != null ? rr.Type : SharedTypes.UnknownType; + } + + public override string ToString() + { + if (typeArguments.Count == 0) + return target.ToString() + "." + identifier; + else + return target.ToString() + "." + identifier + "<" + string.Join(",", typeArguments) + ">"; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + target = provider.Intern(target); + identifier = provider.Intern(identifier); + typeArguments = provider.InternList(typeArguments); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + int hashCode = 0; + unchecked { + hashCode += 1000000007 * target.GetHashCode(); + if (parentTypeDefinition != null) + hashCode += 1000000009 * parentTypeDefinition.GetHashCode(); + if (parentUsingScope != null) + hashCode += 1000000021 * parentUsingScope.GetHashCode(); + hashCode += 1000000033 * identifier.GetHashCode(); + hashCode += 1000000087 * typeArguments.GetHashCode(); + } + return hashCode; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + MemberTypeOrNamespaceReference o = other as MemberTypeOrNamespaceReference; + return o != null && this.target == o.target && this.parentTypeDefinition == o.parentTypeDefinition + && this.parentUsingScope == o.parentUsingScope && this.identifier == o.identifier + && this.typeArguments == o.typeArguments; + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs new file mode 100644 index 000000000..5af732ddb --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/MethodGroupResolveResult.cs @@ -0,0 +1,222 @@ +// 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.Collections.Generic; +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Linq; +using System.Text; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public class MethodListWithDeclaringType : List + { + readonly IType declaringType; + + public IType DeclaringType { + get { return declaringType; } + } + + public MethodListWithDeclaringType(IType declaringType) + { + this.declaringType = declaringType; + } + + public MethodListWithDeclaringType(IType declaringType, IEnumerable methods) + : base(methods) + { + this.declaringType = declaringType; + } + } + + /// + /// Represents a group of methods. + /// + public class MethodGroupResolveResult : ResolveResult + { + readonly IList methodLists; + readonly IList typeArguments; + readonly ResolveResult targetResult; + readonly string methodName; + + public MethodGroupResolveResult(ResolveResult targetResult, string methodName, IList methods, IList typeArguments) : base(SharedTypes.UnknownType) + { + if (targetResult == null) + throw new ArgumentNullException("targetResult"); + if (methods == null) + throw new ArgumentNullException("methods"); + this.targetResult = targetResult; + this.methodName = methodName; + this.methodLists = methods; + this.typeArguments = typeArguments ?? EmptyList.Instance; + } + + /// + /// Gets the resolve result for the target object. + /// + public ResolveResult TargetResult { + get { return targetResult; } + } + + /// + /// Gets the type of the reference to the target object. + /// + public IType TargetType { + get { return targetResult.Type; } + } + + /// + /// Gets the name of the methods in this group. + /// + public string MethodName { + get { return methodName; } + } + + /// + /// Gets the methods that were found. + /// This list does not include extension methods. + /// + public IEnumerable Methods { + get { return methodLists.SelectMany(m => m.Cast()); } + } + + /// + /// Gets the methods that were found. + /// This list does not include extension methods. + /// + public IEnumerable MethodsGroupedByDeclaringType { + get { return methodLists; } + } + + /// + /// Gets the type arguments that were explicitly provided. + /// + public IList TypeArguments { + get { return typeArguments; } + } + + /// + /// List of extension methods, used to avoid re-calculating it in ResolveInvocation() when it was already + /// calculated by ResolveMemberAccess(). + /// + internal List> extensionMethods; + + // Resolver+UsingScope are used to fetch extension methods on demand + internal CSharpResolver resolver; + internal UsingScope usingScope; + + /// + /// Gets all candidate extension methods. + /// + /// + /// The results are stored in nested lists because they are grouped by using scope. + /// That is, for "using SomeExtensions; namespace X { using MoreExtensions; ... }", + /// the return value will be + /// new List { + /// new List { all extensions from MoreExtensions }, + /// new List { all extensions from SomeExtensions } + /// } + /// + public IList> GetExtensionMethods() + { + if (resolver != null) { + Debug.Assert(extensionMethods == null); + UsingScope oldUsingScope = resolver.CurrentUsingScope; + try { + resolver.CurrentUsingScope = usingScope; + extensionMethods = resolver.GetExtensionMethods(this.TargetType, methodName, typeArguments); + } finally { + resolver.CurrentUsingScope = oldUsingScope; + resolver = null; + usingScope = null; + } + } + return extensionMethods ?? EmptyList>.Instance; + } + + public override string ToString() + { + return string.Format("[{0} with {1} method(s)]", GetType().Name, this.Methods.Count()); + } + + public OverloadResolution PerformOverloadResolution(ITypeResolveContext context, ResolveResult[] arguments, string[] argumentNames = null, bool allowExtensionMethods = true, bool allowExpandingParams = true, Conversions conversions = null) + { + Log.WriteLine("Performing overload resolution for " + this); + Log.WriteCollection(" Arguments: ", arguments); + + var typeArgumentArray = this.TypeArguments.ToArray(); + OverloadResolution or = new OverloadResolution(context, arguments, argumentNames, typeArgumentArray, conversions); + or.AllowExpandingParams = allowExpandingParams; + + or.AddMethodLists(methodLists); + + if (allowExtensionMethods && !or.FoundApplicableCandidate) { + // No applicable match found, so let's try extension methods. + + var extensionMethods = this.GetExtensionMethods(); + + if (extensionMethods.Count > 0) { + Log.WriteLine("No candidate is applicable, trying {0} extension methods groups...", extensionMethods.Count); + ResolveResult[] extArguments = new ResolveResult[arguments.Length + 1]; + extArguments[0] = new ResolveResult(this.TargetType); + arguments.CopyTo(extArguments, 1); + string[] extArgumentNames = null; + if (argumentNames != null) { + extArgumentNames = new string[argumentNames.Length + 1]; + argumentNames.CopyTo(extArgumentNames, 1); + } + var extOr = new OverloadResolution(context, extArguments, extArgumentNames, typeArgumentArray, conversions); + extOr.AllowExpandingParams = allowExpandingParams; + extOr.IsExtensionMethodInvocation = true; + + foreach (var g in extensionMethods) { + foreach (var method in g) { + Log.Indent(); + OverloadResolutionErrors errors = extOr.AddCandidate(method); + Log.Unindent(); + or.LogCandidateAddingResult(" Extension", method, errors); + } + if (extOr.FoundApplicableCandidate) + break; + } + // For the lack of a better comparison function (the one within OverloadResolution + // cannot be used as it depends on the argument set): + if (extOr.FoundApplicableCandidate || or.BestCandidate == null) { + // Consider an extension method result better than the normal result only + // if it's applicable; or if there is no normal result. + or = extOr; + } + } + } + Log.WriteLine("Overload resolution finished, best candidate is {0}.", or.GetBestCandidateWithSubstitutedTypeArguments()); + return or; + } + + public override IEnumerable GetChildResults() + { + if (targetResult != null) + return new[] { targetResult }; + else + return Enumerable.Empty(); + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/NodeListResolveVisitorNavigator.cs b/ICSharpCode.NRefactory.CSharp/Resolver/NodeListResolveVisitorNavigator.cs new file mode 100644 index 000000000..6737c1064 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/NodeListResolveVisitorNavigator.cs @@ -0,0 +1,76 @@ +// 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.Collections.Generic; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// implementation that resolves a list of nodes. + /// We will skip all nodes which are not the target nodes or ancestors of the target nodes. + /// + public sealed class NodeListResolveVisitorNavigator : IResolveVisitorNavigator + { + readonly Dictionary dict = new Dictionary(); + + /// + /// Creates a new NodeListResolveVisitorNavigator that resolves the specified nodes. + /// + public NodeListResolveVisitorNavigator(params AstNode[] nodes) + : this((IEnumerable)nodes) + { + } + + /// + /// Creates a new NodeListResolveVisitorNavigator that resolves the specified nodes. + /// + public NodeListResolveVisitorNavigator(IEnumerable nodes, bool scanOnly = false) + { + if (nodes == null) + throw new ArgumentNullException("nodes"); + foreach (var node in nodes) { + dict[node] = scanOnly ? ResolveVisitorNavigationMode.Scan : ResolveVisitorNavigationMode.Resolve; + for (var ancestor = node.Parent; ancestor != null && !dict.ContainsKey(ancestor); ancestor = ancestor.Parent) { + dict.Add(ancestor, ResolveVisitorNavigationMode.Scan); + } + } + } + + /// + public ResolveVisitorNavigationMode Scan(AstNode node) + { + ResolveVisitorNavigationMode mode; + if (dict.TryGetValue(node, out mode)) { + return mode; + } else { + return ResolveVisitorNavigationMode.Skip; + } + } + + void IResolveVisitorNavigator.Resolved(AstNode node, ResolveResult result) + { + } + + void IResolveVisitorNavigator.ProcessConversion(Expression expression, ResolveResult result, Conversion conversion, IType targetType) + { + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/OperatorResolveResult.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OperatorResolveResult.cs new file mode 100644 index 000000000..524d73451 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/OperatorResolveResult.cs @@ -0,0 +1,109 @@ +// 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.Collections.Generic; +using System.Linq; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Resolve result representing a built-in unary operator. + /// (user-defined operators use InvocationResolveResult) + /// + public class UnaryOperatorResolveResult : ResolveResult + { + public readonly UnaryOperatorType Operator; + public readonly ResolveResult Input; + + public UnaryOperatorResolveResult(IType resultType, UnaryOperatorType op, ResolveResult input) + : base(resultType) + { + if (input == null) + throw new ArgumentNullException("input"); + this.Operator = op; + this.Input = input; + } + + public override IEnumerable GetChildResults() + { + return new [] { Input }; + } + } + + /// + /// Resolve result representing a built-in binary operator. + /// (user-defined operators use InvocationResolveResult) + /// + public class BinaryOperatorResolveResult : ResolveResult + { + public readonly BinaryOperatorType Operator; + public readonly ResolveResult Left; + public readonly ResolveResult Right; + + public BinaryOperatorResolveResult(IType resultType, ResolveResult lhs, BinaryOperatorType op, ResolveResult rhs) + : base(resultType) + { + if (lhs == null) + throw new ArgumentNullException("lhs"); + if (rhs == null) + throw new ArgumentNullException("rhs"); + this.Left = lhs; + this.Operator = op; + this.Right = rhs; + } + + public override IEnumerable GetChildResults() + { + return new [] { Left, Right }; + } + } + + /// + /// Resolve result representing the conditional operator. + /// + public class ConditionalOperatorResolveResult : ResolveResult + { + public readonly ResolveResult Condition; + public readonly ResolveResult True; + public readonly ResolveResult False; + + public ConditionalOperatorResolveResult(IType targetType, ResolveResult condition, ResolveResult @true, ResolveResult @false) + : base(targetType) + { + if (condition == null) + throw new ArgumentNullException("condition"); + if (@true == null) + throw new ArgumentNullException("true"); + if (@false == null) + throw new ArgumentNullException("false"); + this.Condition = condition; + this.True = @true; + this.False = @false; + } + + public override IEnumerable GetChildResults() + { + return new [] { Condition, True, False }; + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs similarity index 60% rename from ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs index e3942491a..7ce0e0406 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolution.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolution.cs @@ -1,10 +1,28 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; +using System.Diagnostics; using System.Linq; +using System.Text; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -38,7 +56,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public IType[] InferredTypes; - public IList Parameters { get { return Member.Parameters; } } + /// + /// Gets the original member parameters (before any substitution!) + /// + public readonly IList Parameters; + + /// + /// Conversions applied to the arguments. + /// This field is set by the CheckApplicability step. + /// + public Conversion[] ArgumentConversions; public bool IsGenericMethod { get { @@ -65,7 +92,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { this.Member = member; this.IsExpandedForm = isExpanded; - this.ParameterTypes = new IType[member.Parameters.Count]; + if (this.IsGenericMethod) { + // For generic methods, go back to the original parameters + // (without any type parameter substitution, not even class type parameters) + // We'll re-substitute them as part of RunTypeInference(). + this.Parameters = ((IParameterizedMember)member.MemberDefinition).Parameters; + } else { + this.Parameters = member.Parameters; + } + this.ParameterTypes = new IType[this.Parameters.Count]; } public void AddError(OverloadResolutionErrors newError) @@ -85,7 +120,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType[] explicitlyGivenTypeArguments; #region Constructor - public OverloadResolution(ITypeResolveContext context, ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null) + public OverloadResolution(ITypeResolveContext context, ResolveResult[] arguments, string[] argumentNames = null, IType[] typeArguments = null, Conversions conversions = null) { if (context == null) throw new ArgumentNullException("context"); @@ -103,10 +138,33 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (typeArguments != null && typeArguments.Length > 0) this.explicitlyGivenTypeArguments = typeArguments; - this.conversions = new Conversions(context); + this.conversions = conversions ?? Conversions.Get(context); + this.AllowExpandingParams = true; } #endregion + /// + /// Gets/Sets whether the methods are extension methods that are being called using extension method syntax. + /// + /// + /// Setting this property to true restricts the possible conversions on the first argument to + /// implicit identity, reference, or boxing conversions. + /// + public bool IsExtensionMethodInvocation { get; set; } + + /// + /// Gets/Sets whether expanding 'params' into individual elements is allowed. + /// The default value is true. + /// + public bool AllowExpandingParams { get; set; } + + /// + /// Gets the arguments for which this OverloadResolution instance was created. + /// + public IList Arguments { + get { return arguments; } + } + #region AddCandidate public OverloadResolutionErrors AddCandidate(IParameterizedMember member) { @@ -118,7 +176,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver //candidates.Add(c); } - if (member.Parameters.Count > 0 && member.Parameters[member.Parameters.Count - 1].IsParams) { + if (this.AllowExpandingParams && member.Parameters.Count > 0 + && member.Parameters[member.Parameters.Count - 1].IsParams) + { Candidate expandedCandidate = new Candidate(member, true); // consider expanded form only if it isn't obviously wrong if (CalculateCandidate(expandedCandidate)) { @@ -131,6 +191,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return c.Errors; } + public static bool IsApplicable(OverloadResolutionErrors errors) + { + return (errors & ~OverloadResolutionErrors.AmbiguousMatch) == OverloadResolutionErrors.None; + } + /// /// Calculates applicability etc. for the candidate. /// @@ -163,6 +228,75 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion + #region AddMethodLists + /// + /// Adds all candidates from the method lists. + /// + /// This method implements the logic that causes applicable methods in derived types to hide + /// all methods in base types. + /// + public void AddMethodLists(IList methodLists) + { + if (methodLists == null) + throw new ArgumentNullException("methodLists"); + // Base types come first, so go through the list backwards (derived types first) + bool[] isHiddenByDerivedType; + if (methodLists.Count > 1) + isHiddenByDerivedType = new bool[methodLists.Count]; + else + isHiddenByDerivedType = null; + for (int i = methodLists.Count - 1; i >= 0; i--) { + if (isHiddenByDerivedType != null && isHiddenByDerivedType[i]) { + Log.WriteLine(" Skipping methods in {0} because they are hidden by an applicable method in a derived type", methodLists[i].DeclaringType); + continue; + } + + MethodListWithDeclaringType methodList = methodLists[i]; + bool foundApplicableCandidateInCurrentList = false; + + for (int j = 0; j < methodList.Count; j++) { + IParameterizedMember method = methodList[j]; + Log.Indent(); + OverloadResolutionErrors errors = AddCandidate(method); + Log.Unindent(); + LogCandidateAddingResult(" Candidate", method, errors); + + foundApplicableCandidateInCurrentList |= IsApplicable(errors); + } + + if (foundApplicableCandidateInCurrentList && i > 0) { + foreach (IType baseType in methodList.DeclaringType.GetAllBaseTypes(context)) { + for (int j = 0; j < i; j++) { + if (!isHiddenByDerivedType[j] && baseType.Equals(methodLists[j].DeclaringType)) + isHiddenByDerivedType[j] = true; + } + } + } + } + } + + [Conditional("DEBUG")] + internal void LogCandidateAddingResult(string text, IParameterizedMember method, OverloadResolutionErrors errors) + { + #if DEBUG + StringBuilder b = new StringBuilder(text); + b.Append(' '); + b.Append(method); + b.Append(" = "); + if (errors == OverloadResolutionErrors.None) + b.Append("Success"); + else + b.Append(errors); + if (this.BestCandidate == method) { + b.Append(" (best candidate so far)"); + } else if (this.BestCandidateAmbiguousWith == method) { + b.Append(" (ambiguous)"); + } + Log.WriteLine(b.ToString()); + #endif + } + #endregion + #region MapCorrespondingParameters void MapCorrespondingParameters(Candidate candidate) { @@ -181,8 +315,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } else { // named argument - for (int j = 0; j < candidate.Member.Parameters.Count; j++) { - if (argumentNames[i] == candidate.Member.Parameters[j].Name) { + for (int j = 0; j < candidate.Parameters.Count; j++) { + if (argumentNames[i] == candidate.Parameters[j].Name) { candidate.ArgumentToParameterMap[i] = j; } } @@ -204,6 +338,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } return; } + ParameterizedType parameterizedDeclaringType = candidate.Member.DeclaringType as ParameterizedType; + IList classTypeArguments; + if (parameterizedDeclaringType != null) { + classTypeArguments = parameterizedDeclaringType.TypeArguments; + } else { + classTypeArguments = null; + } // The method is generic: if (explicitlyGivenTypeArguments != null) { if (explicitlyGivenTypeArguments.Length == method.TypeParameters.Count) { @@ -222,12 +363,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { TypeInference ti = new TypeInference(context, conversions); bool success; - candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success); + candidate.InferredTypes = ti.InferTypeArguments(method.TypeParameters, arguments, candidate.ParameterTypes, out success, classTypeArguments); if (!success) candidate.AddError(OverloadResolutionErrors.TypeInferenceFailed); } // Now substitute in the formal parameters: - var substitution = new ConstraintValidatingSubstitution(candidate.InferredTypes, this); + var substitution = new ConstraintValidatingSubstitution(classTypeArguments, candidate.InferredTypes, this); for (int i = 0; i < candidate.ParameterTypes.Length; i++) { candidate.ParameterTypes[i] = candidate.ParameterTypes[i].AcceptVisitor(substitution); } @@ -235,15 +376,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver candidate.AddError(OverloadResolutionErrors.ConstructedTypeDoesNotSatisfyConstraint); } - sealed class ConstraintValidatingSubstitution : MethodTypeParameterSubstitution + sealed class ConstraintValidatingSubstitution : TypeParameterSubstitution { - readonly OverloadResolution overloadResolution; + readonly Conversions conversions; + readonly ITypeResolveContext context; public bool ConstraintsValid = true; - public ConstraintValidatingSubstitution(IType[] typeArguments, OverloadResolution overloadResolution) - : base(typeArguments) + public ConstraintValidatingSubstitution(IList classTypeArguments, IList methodTypeArguments, OverloadResolution overloadResolution) + : base(classTypeArguments, methodTypeArguments) { - this.overloadResolution = overloadResolution; + this.context = overloadResolution.context; + this.conversions = overloadResolution.conversions; } public override IType VisitParameterizedType(ParameterizedType type) @@ -257,15 +400,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver var typeParameters = newParameterizedType.GetDefinition().TypeParameters; for (int i = 0; i < typeParameters.Count; i++) { ITypeParameter tp = typeParameters[i]; - IType typeArg = newParameterizedType.TypeArguments[i]; + IType typeArg = newParameterizedType.GetTypeArgument(i); + switch (typeArg.Kind) { // void, null, and pointers cannot be used as type arguments + case TypeKind.Void: + case TypeKind.Null: + case TypeKind.Pointer: + ConstraintsValid = false; + break; + } if (tp.HasReferenceTypeConstraint) { - if (typeArg.IsReferenceType(overloadResolution.context) != true) + if (typeArg.IsReferenceType(context) != true) ConstraintsValid = false; } if (tp.HasValueTypeConstraint) { - if (typeArg.IsReferenceType(overloadResolution.context) != false) - ConstraintsValid = false; - if (NullableType.IsNullable(typeArg)) + if (!NullableType.IsNonNullableValueType(typeArg, context)) ConstraintsValid = false; } if (tp.HasDefaultConstructorConstraint) { @@ -273,13 +421,14 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (def != null && def.IsAbstract) ConstraintsValid = false; ConstraintsValid &= typeArg.GetConstructors( - overloadResolution.context, - m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public + context, + m => m.Parameters.Count == 0 && m.Accessibility == Accessibility.Public, + GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions ).Any(); } foreach (IType constraintType in tp.Constraints) { IType c = newParameterizedType.SubstituteInType(constraintType); - ConstraintsValid &= overloadResolution.IsConstraintConvertible(typeArg, c); + ConstraintsValid &= conversions.IsConstraintConvertible(typeArg, c); } } } @@ -287,12 +436,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return newType; } } - - bool IsConstraintConvertible(IType typeArg, IType constraintType) - { - // TODO: this isn't exactly correct; not all kinds of implicit conversions are allowed here - return conversions.ImplicitConversion(typeArg, constraintType); - } #endregion #region CheckApplicability @@ -319,6 +462,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } + candidate.ArgumentConversions = new Conversion[arguments.Length]; // Test whether argument passing mode matches the parameter passing mode for (int i = 0; i < arguments.Length; i++) { int parameterIndex = candidate.ArgumentToParameterMap[i]; @@ -332,8 +476,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (candidate.Parameters[parameterIndex].IsOut || candidate.Parameters[parameterIndex].IsRef) candidate.AddError(OverloadResolutionErrors.ParameterPassingModeMismatch); } - if (!conversions.ImplicitConversion(arguments[i], candidate.ParameterTypes[parameterIndex])) - candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); + IType parameterType = candidate.ParameterTypes[parameterIndex]; + Conversion c = conversions.ImplicitConversion(arguments[i], parameterType); + candidate.ArgumentConversions[i] = c; + if (IsExtensionMethodInvocation && parameterIndex == 0) { + // First parameter to extension method must be an identity, reference or boxing conversion + if (!(c == Conversion.IdentityConversion || c == Conversion.ImplicitReferenceConversion || c == Conversion.BoxingConversion)) + candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); + } else { + if (!c) + candidate.AddError(OverloadResolutionErrors.ArgumentTypeMismatch); + } } } #endregion @@ -494,8 +647,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } else { switch (BetterFunctionMember(candidate, bestCandidate)) { case 0: - if (bestCandidateAmbiguousWith == null) - bestCandidateAmbiguousWith = candidate; + // Overwrite 'bestCandidateAmbiguousWith' so that API users can + // detect the set of all ambiguous methods if they look at + // bestCandidateAmbiguousWith after each step. + bestCandidateAmbiguousWith = candidate; break; case 1: bestCandidate = candidate; @@ -541,10 +696,89 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public IList InferredTypeArguments { get { if (bestCandidate != null && bestCandidate.InferredTypes != null) - return Array.AsReadOnly(bestCandidate.InferredTypes); + return bestCandidate.InferredTypes; else return EmptyList.Instance; } } + + /// + /// Gets the implicit conversions that are being applied to the arguments. + /// + public IList ArgumentConversions { + get { + if (bestCandidate != null && bestCandidate.ArgumentConversions != null) + return bestCandidate.ArgumentConversions; + else + return new Conversion[arguments.Length]; + } + } + + /// + /// Gets an array that maps argument indices to parameter indices. + /// For arguments that could not be mapped to any parameter, the value will be -1. + /// + /// parameterIndex = GetArgumentToParameterMap()[argumentIndex] + /// + public IList GetArgumentToParameterMap() + { + if (bestCandidate != null) + return bestCandidate.ArgumentToParameterMap; + else + return null; + } + + public IList GetArgumentsWithConversions() + { + if (bestCandidate == null) + return arguments; + var conversions = this.ArgumentConversions; + ResolveResult[] args = new ResolveResult[arguments.Length]; + for (int i = 0; i < args.Length; i++) { + if (conversions[i] == Conversion.IdentityConversion || conversions[i] == Conversion.None) { + args[i] = arguments[i]; + } else { + int parameterIndex = bestCandidate.ArgumentToParameterMap[i]; + IType parameterType; + if (parameterIndex >= 0) + parameterType = bestCandidate.ParameterTypes[parameterIndex]; + else + parameterType = SharedTypes.UnknownType; + args[i] = new ConversionResolveResult(parameterType, arguments[i], conversions[i]); + } + } + return args; + } + + public IParameterizedMember GetBestCandidateWithSubstitutedTypeArguments() + { + if (bestCandidate == null) + return null; + IMethod method = bestCandidate.Member as IMethod; + if (method != null && method.TypeParameters.Count > 0) { + return new SpecializedMethod(method.DeclaringType, (IMethod)method.MemberDefinition, bestCandidate.InferredTypes); + } else { + return bestCandidate.Member; + } + } + + public CSharpInvocationResolveResult CreateResolveResult(ResolveResult targetResolveResult) + { + IParameterizedMember member = GetBestCandidateWithSubstitutedTypeArguments(); + if (member == null) + throw new InvalidOperationException(); + + return new CSharpInvocationResolveResult( + targetResolveResult, + member, + member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType.Resolve(context), + GetArgumentsWithConversions(), + this.BestCandidateErrors, + this.IsExtensionMethodInvocation, + this.BestCandidateIsExpandedForm, + member is ILiftedOperator, + isDelegateInvocation: false, + argumentToParameterMap: this.GetArgumentToParameterMap()); + } } } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolutionErrors.cs b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolutionErrors.cs similarity index 58% rename from ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolutionErrors.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolutionErrors.cs index a9de1e4cd..f724cb0f1 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/OverloadResolutionErrors.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/OverloadResolutionErrors.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs new file mode 100644 index 000000000..adc2d572f --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveAtLocation.cs @@ -0,0 +1,87 @@ +// 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.Threading; +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Helper class that resolves the node at a specified location. + /// Can be used for implementing tool tips. + /// + public static class ResolveAtLocation + { + public static ResolveResult Resolve(ITypeResolveContext context, CSharpParsedFile parsedFile, CompilationUnit cu, TextLocation location, + CancellationToken cancellationToken = default(CancellationToken)) + { + AstNode node = cu.GetNodeAt(location); + if (node == null) + return null; + AstNode resolvableNode; + if (node is AstType) { + resolvableNode = node; + if (resolvableNode.Parent is ComposedType) { + while (resolvableNode.Parent is ComposedType) + resolvableNode = resolvableNode.Parent; + //node is preffered over the resolvable node. Which shouldn't be done in the case of nullables, arrays etc. + node = resolvableNode; + } + } else if (node is Identifier) { + resolvableNode = node.Parent; + } else if (node.NodeType == NodeType.Token) { + if (node.Parent is ConstructorInitializer) { + resolvableNode = node.Parent; + } else { + return null; + } + } else { + // don't resolve arbitrary nodes - we don't want to show tooltips for everything + return null; + } + + InvocationExpression parentInvocation = null; + if ((resolvableNode is IdentifierExpression || resolvableNode is MemberReferenceExpression || resolvableNode is PointerReferenceExpression)) { + // we also need to resolve the invocation + parentInvocation = resolvableNode.Parent as InvocationExpression; + } + + IResolveVisitorNavigator navigator; + if (parentInvocation != null) + navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode, parentInvocation }); + else + navigator = new NodeListResolveVisitorNavigator(new[] { resolvableNode }); + + using (var ctx = context.Synchronize()) { + CSharpResolver resolver = new CSharpResolver(ctx, cancellationToken); + ResolveVisitor v = new ResolveVisitor(resolver, parsedFile, navigator); + v.Scan(cu); + + // Prefer the RR from the token itself, if it was assigned a ResolveResult + // (this can happen with the identifiers in various nodes such as catch clauses or foreach statements) + ResolveResult rr = v.GetResolveResult(node) ?? v.GetResolveResult(resolvableNode); + if (rr is MethodGroupResolveResult && parentInvocation != null) + return v.GetResolveResult(parentInvocation); + else + return rr; + } + } + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs new file mode 100644 index 000000000..2bfed6013 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/ResolveVisitor.cs @@ -0,0 +1,3383 @@ +// 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.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + /// + /// Traverses the DOM and resolves expressions. + /// + /// + /// The ResolveVisitor does two jobs at the same time: it tracks the resolve context (properties on CSharpResolver) + /// and it resolves the expressions visited. + /// To allow using the context tracking without having to resolve every expression in the file (e.g. when you want to resolve + /// only a single node deep within the DOM), you can use the interface. + /// The navigator allows you to switch the between scanning mode and resolving mode. + /// In scanning mode, the context is tracked (local variables registered etc.), but nodes are not resolved. + /// While scanning, the navigator will get asked about every node that the resolve visitor is about to enter. + /// This allows the navigator whether to keep scanning, whether switch to resolving mode, or whether to completely skip the + /// subtree rooted at that node. + /// + /// In resolving mode, the context is tracked and nodes will be resolved. + /// The resolve visitor may decide that it needs to resolve other nodes as well in order to resolve the current node. + /// In this case, those nodes will be resolved automatically, without asking the navigator interface. + /// For child nodes that are not essential to resolving, the resolve visitor will switch back to scanning mode (and thus will + /// ask the navigator for further instructions). + /// + /// Moreover, there is the ResolveAll mode - it works similar to resolving mode, but will not switch back to scanning mode. + /// The whole subtree will be resolved without notifying the navigator. + /// + public sealed class ResolveVisitor : IAstVisitor + { + // The ResolveVisitor is also responsible for handling lambda expressions. + + static readonly ResolveResult errorResult = ErrorResolveResult.UnknownError; + static readonly ResolveResult transparentIdentifierResolveResult = new ResolveResult(SharedTypes.UnboundTypeArgument); + readonly ResolveResult voidResult; + + CSharpResolver resolver; + SimpleNameLookupMode currentTypeLookupMode = SimpleNameLookupMode.Type; + /// Resolve result of the current LINQ query + ResolveResult currentQueryResult; + readonly CSharpParsedFile parsedFile; + readonly Dictionary resolveResultCache = new Dictionary(); + readonly Dictionary resolverBeforeDict = new Dictionary(); + + IResolveVisitorNavigator navigator; + bool resolverEnabled; + List undecidedLambdas; + + #region Constructor + /// + /// Creates a new ResolveVisitor instance. + /// + /// + /// The CSharpResolver, describing the initial resolve context. + /// If you visit a whole CompilationUnit with the resolve visitor, you can simply pass + /// new CSharpResolver(typeResolveContext) without setting up the context. + /// If you only visit a subtree, you need to pass a CSharpResolver initialized to the context for that subtree. + /// + /// + /// Result of the for the file being passed. This is used for setting up the context on the resolver. + /// You may pass null if you are only visiting a part of a method body and have already set up the context in the . + /// + /// + /// The navigator, which controls where the resolve visitor will switch between scanning mode and resolving mode. + /// If you pass null, then nothing will be resolved on the initial scan, and the resolver + /// will resolve additional nodes on demand (when one of the Get-methods is called). + /// + public ResolveVisitor(CSharpResolver resolver, CSharpParsedFile parsedFile, IResolveVisitorNavigator navigator = null) + { + if (resolver == null) + throw new ArgumentNullException("resolver"); + this.resolver = resolver; + this.parsedFile = parsedFile; + this.navigator = navigator ?? new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Skip, null); + this.voidResult = new ResolveResult(KnownTypeReference.Void.Resolve(resolver.Context)); + } + #endregion + + #region Properties + /// + /// Gets the TypeResolveContext used by this ResolveVisitor. + /// + public ITypeResolveContext TypeResolveContext { + get { return resolver.Context; } + } + + /// + /// Gets the CancellationToken used by this ResolveVisitor. + /// + public CancellationToken CancellationToken { + get { return resolver.cancellationToken; } + } + #endregion + + #region ResetContext + /// + /// Resets the visitor to the stored position, runs the action, and then reverts the visitor to the previous position. + /// + void ResetContext(CSharpResolver storedContext, Action action) + { + var oldResolverEnabled = this.resolverEnabled; + var oldResolver = this.resolver; + var oldTypeLookupMode = this.currentTypeLookupMode; + var oldQueryType = this.currentQueryResult; + try { + this.resolverEnabled = false; + this.resolver = storedContext; + this.currentTypeLookupMode = SimpleNameLookupMode.Type; + this.currentQueryResult = null; + + action(); + } finally { + this.resolverEnabled = oldResolverEnabled; + this.resolver = oldResolver; + this.currentTypeLookupMode = oldTypeLookupMode; + this.currentQueryResult = oldQueryType; + } + } + #endregion + + #region Scan / Resolve + /// + /// Scans the AST rooted at the given node. + /// + public void Scan(AstNode node) + { + if (node == null || node.IsNull) + return; + switch (node.NodeType) { + case NodeType.Token: + case NodeType.Whitespace: + return; // skip tokens, identifiers, comments, etc. + } + + var mode = navigator.Scan(node); + switch (mode) { + case ResolveVisitorNavigationMode.Skip: + if (node is VariableDeclarationStatement) { + // Enforce scanning of variable declarations. + goto case ResolveVisitorNavigationMode.Scan; + } + if (resolverBeforeDict.Count == 0) { + // If we're just starting to resolve and haven't any context cached yet, + // make sure to cache the root node. + StoreState(node, resolver.Clone()); + } + break; + case ResolveVisitorNavigationMode.Scan: + if (node is LambdaExpression || node is AnonymousMethodExpression) { + // lambdas must be resolved so that they get stored in the 'undecided' list only once + goto case ResolveVisitorNavigationMode.Resolve; + } + + // We shouldn't scan nodes that were already resolved. + Debug.Assert(!resolveResultCache.ContainsKey(node)); + // Doing so should be harmless since we allow scanning twice, but it indicates + // a bug in the logic that causes the scan. + + bool oldResolverEnabled = resolverEnabled; + resolverEnabled = false; + StoreState(node, resolver.Clone()); + node.AcceptVisitor(this, null); + resolverEnabled = oldResolverEnabled; + break; + case ResolveVisitorNavigationMode.Resolve: + Resolve(node); + break; + default: + throw new InvalidOperationException("Invalid value for ResolveVisitorNavigationMode"); + } + } + + /// + /// Equivalent to 'Scan', but also resolves the node at the same time. + /// This method should be only used if the CSharpResolver passed to the ResolveVisitor was manually set + /// to the correct state. + /// Otherwise, use resolver.Scan(compilationUnit); var result = resolver.GetResolveResult(node); + /// instead. + /// + public ResolveResult Resolve(AstNode node) + { + if (node == null || node.IsNull) + return errorResult; + bool oldResolverEnabled = resolverEnabled; + resolverEnabled = true; + ResolveResult result; + if (!resolveResultCache.TryGetValue(node, out result)) { + resolver.cancellationToken.ThrowIfCancellationRequested(); + StoreState(node, resolver.Clone()); + result = node.AcceptVisitor(this, null) ?? errorResult; + Log.WriteLine("Resolved '{0}' to {1}", node, result); + StoreResult(node, result); + } + resolverEnabled = oldResolverEnabled; + return result; + } + + IType ResolveType(AstType type) + { + return Resolve(type).Type; + } + + void StoreState(AstNode node, CSharpResolver resolverState) + { + Debug.Assert(resolverState != null); + // It's possible that we re-visit an expression that we scanned over earlier, + // so we might have to overwrite an existing state. + resolverBeforeDict[node] = resolverState; + } + + void StoreResult(AstNode node, ResolveResult result) + { + Debug.Assert(result != null); + if (node.IsNull) + return; + Debug.Assert(!resolveResultCache.ContainsKey(node)); + resolveResultCache.Add(node, result); + if (navigator != null) + navigator.Resolved(node, result); + } + + void ScanChildren(AstNode node) + { + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + Scan(child); + } + } + #endregion + + #region Process Conversions + sealed class AnonymousFunctionConversionData + { + public readonly IType ReturnType; + public readonly ExplicitlyTypedLambda ExplicitlyTypedLambda; + public readonly LambdaTypeHypothesis Hypothesis; + + public AnonymousFunctionConversionData(IType returnType, LambdaTypeHypothesis hypothesis) + { + if (returnType == null) + throw new ArgumentNullException("returnType"); + this.ReturnType = returnType; + this.Hypothesis = hypothesis; + } + + public AnonymousFunctionConversionData(IType returnType, ExplicitlyTypedLambda explicitlyTypedLambda) + { + if (returnType == null) + throw new ArgumentNullException("returnType"); + this.ReturnType = returnType; + this.ExplicitlyTypedLambda = explicitlyTypedLambda; + } + } + + /// + /// Convert 'rr' to the target type using the specified conversion. + /// + void ProcessConversion(Expression expr, ResolveResult rr, Conversion conversion, IType targetType) + { + if (conversion.IsAnonymousFunctionConversion) { + Log.WriteLine("Processing conversion of anonymous function to " + targetType + "..."); + AnonymousFunctionConversionData data = conversion.data as AnonymousFunctionConversionData; + if (data != null) { + Log.Indent(); + if (data.Hypothesis != null) + data.Hypothesis.MergeInto(this, data.ReturnType); + if (data.ExplicitlyTypedLambda != null) + data.ExplicitlyTypedLambda.ApplyReturnType(this, data.ReturnType); + Log.Unindent(); + } else { + Log.WriteLine(" Data not found."); + } + } + if (expr != null && conversion != Conversion.IdentityConversion) + navigator.ProcessConversion(expr, rr, conversion, targetType); + } + + /// + /// Convert 'rr' to the target type. + /// + void ProcessConversion(Expression expr, ResolveResult rr, IType targetType) + { + ProcessConversion(expr, rr, resolver.conversions.ImplicitConversion(rr, targetType), targetType); + } + + /// + /// Resolves the specified expression and processes the conversion to targetType. + /// + void ResolveAndProcessConversion(Expression expr, IType targetType) + { + if (targetType.Kind == TypeKind.Unknown || targetType.Kind == TypeKind.Void) { + // no need to resolve the expression right now + Scan(expr); + } else { + ProcessConversion(expr, Resolve(expr), targetType); + } + } + + void ProcessConversionResult(Expression expr, ConversionResolveResult rr) + { + if (rr != null) + ProcessConversion(expr, rr.Input, rr.Conversion, rr.Type); + } + + void ProcessConversionResults(IEnumerable expr, IEnumerable conversionResolveResults) + { + Debug.Assert(expr.Count() == conversionResolveResults.Count()); + using (var e1 = expr.GetEnumerator()) { + using (var e2 = conversionResolveResults.GetEnumerator()) { + while (e1.MoveNext() && e2.MoveNext()) { + ProcessConversionResult(e1.Current, e2.Current as ConversionResolveResult); + } + } + } + } + + void ProcessConversionsInInvocation(Expression target, IEnumerable arguments, CSharpInvocationResolveResult invocation) + { + if (invocation == null) + return; + int i = 0; + if (invocation.IsExtensionMethodInvocation) { + Debug.Assert(arguments.Count() + 1 == invocation.Arguments.Count); + ProcessConversionResult(target, invocation.Arguments[0] as ConversionResolveResult); + i = 1; + } else { + Debug.Assert(arguments.Count() == invocation.Arguments.Count); + } + foreach (Expression arg in arguments) { + NamedArgumentExpression nae = arg as NamedArgumentExpression; + if (nae != null) + ProcessConversionResult(nae.Expression, invocation.Arguments[i++] as ConversionResolveResult); + else + ProcessConversionResult(arg, invocation.Arguments[i++] as ConversionResolveResult); + } + } + #endregion + + #region GetResolveResult + /// + /// Gets the resolve result for the specified node. + /// If the node was not resolved by the navigator, this method will resolve it. + /// + public ResolveResult GetResolveResult(AstNode node) + { + if (IsUnresolvableNode(node)) + return null; + + MergeUndecidedLambdas(); + ResolveResult result; + if (resolveResultCache.TryGetValue(node, out result)) + return result; + + bool needResolveParent = (node.NodeType == NodeType.Token || IsVar(node)); + + AstNode nodeToResolve = node; + if (needResolveParent) { + nodeToResolve = node.Parent; + if (resolveResultCache.ContainsKey(nodeToResolve)) + return null; + } + + AstNode parent; + CSharpResolver storedResolver = GetPreviouslyScannedContext(nodeToResolve, out parent); + ResetContext( + storedResolver.Clone(), + delegate { + navigator = new NodeListResolveVisitorNavigator(nodeToResolve); + if (parent == nodeToResolve) { + Resolve(nodeToResolve); + } else { + Debug.Assert(!resolverEnabled); + parent.AcceptVisitor(this, null); + } + }); + + MergeUndecidedLambdas(); + if (resolveResultCache.TryGetValue(node, out result)) + return result; + else + return null; + } + + /// + /// Gets whether the specified node is unresolvable. + /// + public static bool IsUnresolvableNode(AstNode node) + { + return (node.NodeType == NodeType.Whitespace || node is ArraySpecifier || node is NamedArgumentExpression); + } + + /// + /// Gets the resolve result for the specified node. + /// If the node was not resolved by the navigator, this method will return null. + /// + public ResolveResult GetResolveResultIfResolved(AstNode node) + { + MergeUndecidedLambdas(); + ResolveResult result; + if (resolveResultCache.TryGetValue(node, out result)) + return result; + else + return null; + } + + CSharpResolver GetPreviouslyScannedContext(AstNode node, out AstNode parent) + { + parent = node; + CSharpResolver storedResolver; + while (!resolverBeforeDict.TryGetValue(parent, out storedResolver)) { + parent = parent.Parent; + if (parent == null) + throw new InvalidOperationException("Could not find a resolver state for any parent of the specified node. Did you forget to call 'Scan(compilationUnit);'?"); + } + return storedResolver; + } + + /// + /// Gets the resolver state in front of the specified node. + /// If the node was not visited by a previous scanning process, the + /// AST will be scanned again to determine the state. + /// + public CSharpResolver GetResolverStateBefore(AstNode node) + { + MergeUndecidedLambdas(); + CSharpResolver r; + if (resolverBeforeDict.TryGetValue(node, out r)) + return r; + + AstNode parent; + CSharpResolver storedResolver = GetPreviouslyScannedContext(node, out parent); + ResetContext( + storedResolver.Clone(), + delegate { + navigator = new NodeListResolveVisitorNavigator(new[] { node }, scanOnly: true); + Debug.Assert(!resolverEnabled); + parent.AcceptVisitor(this, null); + }); + + MergeUndecidedLambdas(); + while (node != null) { + if (resolverBeforeDict.TryGetValue(node, out r)) + return r; + node = node.Parent; + } + return null; + } + #endregion + + #region Track UsingScope + ResolveResult IAstVisitor.VisitCompilationUnit(CompilationUnit unit, object data) + { + UsingScope previousUsingScope = resolver.CurrentUsingScope; + try { + if (parsedFile != null) + resolver.CurrentUsingScope = parsedFile.RootUsingScope; + ScanChildren(unit); + return voidResult; + } finally { + resolver.CurrentUsingScope = previousUsingScope; + } + } + + ResolveResult IAstVisitor.VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + { + UsingScope previousUsingScope = resolver.CurrentUsingScope; + try { + if (parsedFile != null) { + resolver.CurrentUsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation); + } + ScanChildren(namespaceDeclaration); + // merge undecided lambdas before leaving the using scope so that + // the resolver can make better use of its cache + MergeUndecidedLambdas(); + if (resolver.CurrentUsingScope != null) + return new NamespaceResolveResult(resolver.CurrentUsingScope.NamespaceName); + else + return null; + } finally { + resolver.CurrentUsingScope = previousUsingScope; + } + } + #endregion + + #region Track CurrentTypeDefinition + ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration) + { + ITypeDefinition previousTypeDefinition = resolver.CurrentTypeDefinition; + try { + ITypeDefinition newTypeDefinition = null; + if (resolver.CurrentTypeDefinition != null) { + foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) { + if (nestedType.Region.IsInside(typeDeclaration.StartLocation)) { + newTypeDefinition = nestedType; + break; + } + } + } else if (parsedFile != null) { + newTypeDefinition = parsedFile.GetTopLevelTypeDefinition(typeDeclaration.StartLocation); + } + if (newTypeDefinition != null) + resolver.CurrentTypeDefinition = newTypeDefinition; + + for (AstNode child = typeDeclaration.FirstChild; child != null; child = child.NextSibling) { + if (child.Role == TypeDeclaration.BaseTypeRole) { + currentTypeLookupMode = SimpleNameLookupMode.BaseTypeReference; + Scan(child); + currentTypeLookupMode = SimpleNameLookupMode.Type; + } else { + Scan(child); + } + } + + // merge undecided lambdas before leaving the type definition so that + // the resolver can make better use of its cache + MergeUndecidedLambdas(); + + return newTypeDefinition != null ? new TypeResolveResult(newTypeDefinition) : errorResult; + } finally { + resolver.CurrentTypeDefinition = previousTypeDefinition; + } + } + + ResolveResult IAstVisitor.VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) + { + return VisitTypeOrDelegate(typeDeclaration); + } + + ResolveResult IAstVisitor.VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) + { + return VisitTypeOrDelegate(delegateDeclaration); + } + #endregion + + #region Track CurrentMember + ResolveResult IAstVisitor.VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + { + return VisitFieldOrEventDeclaration(fieldDeclaration); + } + + ResolveResult IAstVisitor.VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) + { + return VisitFieldOrEventDeclaration(fixedFieldDeclaration); + } + + ResolveResult IAstVisitor.VisitEventDeclaration(EventDeclaration eventDeclaration, object data) + { + return VisitFieldOrEventDeclaration(eventDeclaration); + } + + ResolveResult VisitFieldOrEventDeclaration(AttributedNode fieldOrEventDeclaration) + { + int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count; + ResolveResult result = null; + for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == FieldDeclaration.Roles.Variable) { + if (resolver.CurrentTypeDefinition != null) { + IEnumerable members; + if (fieldOrEventDeclaration is EventDeclaration) + members = resolver.CurrentTypeDefinition.Events; + else + members = resolver.CurrentTypeDefinition.Fields; + resolver.CurrentMember = members.FirstOrDefault(f => f.Region.IsInside(node.StartLocation)); + } + + if (resolverEnabled && initializerCount == 1) { + result = Resolve(node); + } else { + Scan(node); + } + + resolver.CurrentMember = null; + } else { + Scan(node); + } + } + return result; + } + + ResolveResult IAstVisitor.VisitVariableInitializer(VariableInitializer variableInitializer, object data) + { + if (resolverEnabled) { + ResolveResult result = errorResult; + if (variableInitializer.Parent is FieldDeclaration || variableInitializer.Parent is EventDeclaration) { + if (resolver.CurrentMember != null) { + result = new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + } + } else { + string identifier = variableInitializer.Name; + foreach (IVariable v in resolver.LocalVariables) { + if (v.Name == identifier) { + object constantValue = v.IsConst ? v.ConstantValue.Resolve(resolver.Context).ConstantValue : null; + result = new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue); + break; + } + } + } + ArrayInitializerExpression aie = variableInitializer.Initializer as ArrayInitializerExpression; + ArrayType arrayType = result.Type as ArrayType; + if (aie != null && arrayType != null) { + StoreState(aie, resolver.Clone()); + List initializerElements = new List(); + UnpackArrayInitializer(initializerElements, aie, arrayType.Dimensions, true); + ResolveResult[] initializerElementResults = new ResolveResult[initializerElements.Count]; + for (int i = 0; i < initializerElementResults.Length; i++) { + initializerElementResults[i] = Resolve(initializerElements[i]); + } + var arrayCreation = resolver.ResolveArrayCreation(arrayType.ElementType, arrayType.Dimensions, null, initializerElementResults); + StoreResult(aie, arrayCreation); + ProcessConversionResults(initializerElements, arrayCreation.InitializerElements); + } else { + ResolveAndProcessConversion(variableInitializer.Initializer, result.Type); + } + return result; + } else { + ScanChildren(variableInitializer); + return null; + } + } + + ResolveResult IAstVisitor.VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data) + { + if (resolverEnabled) { + ResolveResult result = errorResult; + if (resolver.CurrentMember != null) { + result = new MemberResolveResult(null, resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); + } + ResolveAndProcessConversion(fixedVariableInitializer.CountExpression, KnownTypeReference.Int32.Resolve(resolver.Context)); + return result; + } else { + ScanChildren(fixedVariableInitializer); + return null; + } + } + + ResolveResult VisitMethodMember(AttributedNode member) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.FirstOrDefault(m => m.Region.IsInside(member.StartLocation)); + } + + ScanChildren(member); + + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + + ResolveResult IAstVisitor.VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + { + return VisitMethodMember(methodDeclaration); + } + + ResolveResult IAstVisitor.VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) + { + return VisitMethodMember(operatorDeclaration); + } + + ResolveResult IAstVisitor.VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + return VisitMethodMember(constructorDeclaration); + } + + ResolveResult IAstVisitor.VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) + { + return VisitMethodMember(destructorDeclaration); + } + + // handle properties/indexers + ResolveResult VisitPropertyMember(MemberDeclaration propertyOrIndexerDeclaration) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Properties.FirstOrDefault(p => p.Region.IsInside(propertyOrIndexerDeclaration.StartLocation)); + } + + for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == PropertyDeclaration.SetterRole && resolver.CurrentMember != null) { + resolver.PushBlock(); + resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); + Scan(node); + resolver.PopBlock(); + } else { + Scan(node); + } + } + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + + ResolveResult IAstVisitor.VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) + { + return VisitPropertyMember(propertyDeclaration); + } + + ResolveResult IAstVisitor.VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) + { + return VisitPropertyMember(indexerDeclaration); + } + + ResolveResult IAstVisitor.VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Events.FirstOrDefault(e => e.Region.IsInside(eventDeclaration.StartLocation)); + } + + if (resolver.CurrentMember != null) { + resolver.PushBlock(); + resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); + ScanChildren(eventDeclaration); + resolver.PopBlock(); + } else { + ScanChildren(eventDeclaration); + } + + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + + ResolveResult IAstVisitor.VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data) + { + ScanChildren(parameterDeclaration); + if (resolverEnabled) { + string name = parameterDeclaration.Name; + // Look in lambda parameters: + foreach (IParameter p in resolver.LocalVariables.OfType()) { + if (p.Name == name) + return new LocalResolveResult(p, p.Type.Resolve(resolver.Context)); + } + + IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember; + if (pm != null) { + foreach (IParameter p in pm.Parameters) { + if (p.Name == name) { + return new LocalResolveResult(p, p.Type.Resolve(resolver.Context)); + } + } + } + return errorResult; + } else { + return null; + } + } + + ResolveResult IAstVisitor.VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) + { + ScanChildren(typeParameterDeclaration); + if (resolverEnabled) { + string name = typeParameterDeclaration.Name; + IMethod m = resolver.CurrentMember as IMethod; + if (m != null) { + foreach (var tp in m.TypeParameters) { + if (tp.Name == name) + return new TypeResolveResult(tp); + } + } + if (resolver.CurrentTypeDefinition != null) { + var typeParameters = resolver.CurrentTypeDefinition.TypeParameters; + // look backwards so that TPs in the current type take precedence over those copied from outer types + for (int i = typeParameters.Count - 1; i >= 0; i--) { + if (typeParameters[i].Name == name) + return new TypeResolveResult(typeParameters[i]); + } + } + return errorResult; + } else { + return null; + } + } + + ResolveResult IAstVisitor.VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) + { + try { + if (resolver.CurrentTypeDefinition != null) { + resolver.CurrentMember = resolver.CurrentTypeDefinition.Fields.FirstOrDefault(f => f.Region.IsInside(enumMemberDeclaration.StartLocation)); + } + + ScanChildren(enumMemberDeclaration); + + if (resolverEnabled && resolver.CurrentMember != null) + return new MemberResolveResult(null, resolver.CurrentMember, resolver.Context); + else + return errorResult; + } finally { + resolver.CurrentMember = null; + } + } + #endregion + + #region Track CheckForOverflow + ResolveResult IAstVisitor.VisitCheckedExpression(CheckedExpression checkedExpression, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = true; + if (resolverEnabled) { + return Resolve(checkedExpression.Expression); + } else { + ScanChildren(checkedExpression); + return null; + } + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + ResolveResult IAstVisitor.VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = false; + if (resolverEnabled) { + return Resolve(uncheckedExpression.Expression); + } else { + ScanChildren(uncheckedExpression); + return null; + } + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + ResolveResult IAstVisitor.VisitCheckedStatement(CheckedStatement checkedStatement, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = true; + ScanChildren(checkedStatement); + return voidResult; + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + + ResolveResult IAstVisitor.VisitUncheckedStatement(UncheckedStatement uncheckedStatement, object data) + { + bool oldCheckForOverflow = resolver.CheckForOverflow; + try { + resolver.CheckForOverflow = false; + ScanChildren(uncheckedStatement); + return voidResult; + } finally { + resolver.CheckForOverflow = oldCheckForOverflow; + } + } + #endregion + + #region Visit Expressions + static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr) + { + if (expr is NamedExpression) { + var namedArgExpr = (NamedExpression)expr; + resolveExpr = namedArgExpr.Expression; + return namedArgExpr.Identifier; + } + // no name given, so it's a projection initializer + if (expr is MemberReferenceExpression) { + resolveExpr = expr; + return ((MemberReferenceExpression)expr).MemberName; + } + if (expr is IdentifierExpression) { + resolveExpr = expr; + return ((IdentifierExpression)expr).Identifier; + } + resolveExpr = null; + return null; + } + + ResolveResult IAstVisitor.VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) + { + // 7.6.10.6 Anonymous object creation expressions + if (resolver.ProjectContent == null) { + ScanChildren(anonymousTypeCreateExpression); + return errorResult; + } + var anonymousType = new DefaultTypeDefinition(resolver.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)) { + 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); + } + + ResolveResult IAstVisitor.VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) + { + if (!resolverEnabled) { + ScanChildren(arrayCreateExpression); + return null; + } + + int dimensions = arrayCreateExpression.Arguments.Count; + ResolveResult[] sizeArguments; + IEnumerable additionalArraySpecifiers; + if (dimensions == 0) { + var firstSpecifier = arrayCreateExpression.AdditionalArraySpecifiers.FirstOrDefault(); + if (firstSpecifier != null) { + dimensions = firstSpecifier.Dimensions; + additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers.Skip(1); + } else { + dimensions = 0; + additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers; + } + sizeArguments = null; + } else { + sizeArguments = new ResolveResult[dimensions]; + int pos = 0; + foreach (var node in arrayCreateExpression.Arguments) + sizeArguments[pos++] = Resolve(node); + additionalArraySpecifiers = arrayCreateExpression.AdditionalArraySpecifiers; + } + + List initializerElements; + ResolveResult[] initializerElementResults; + if (arrayCreateExpression.Initializer.IsNull) { + initializerElements = null; + initializerElementResults = null; + } else { + initializerElements = new List(); + UnpackArrayInitializer(initializerElements, arrayCreateExpression.Initializer, dimensions, true); + initializerElementResults = new ResolveResult[initializerElements.Count]; + for (int i = 0; i < initializerElementResults.Length; i++) { + initializerElementResults[i] = Resolve(initializerElements[i]); + } + if (!resolveResultCache.ContainsKey(arrayCreateExpression.Initializer)) + StoreResult(arrayCreateExpression.Initializer, voidResult); + } + + ArrayCreateResolveResult acrr; + if (arrayCreateExpression.Type.IsNull) { + acrr = resolver.ResolveArrayCreation(null, dimensions, sizeArguments, initializerElementResults); + } else { + IType elementType = ResolveType(arrayCreateExpression.Type); + foreach (var spec in additionalArraySpecifiers.Reverse()) { + elementType = new ArrayType(elementType, spec.Dimensions); + } + acrr = resolver.ResolveArrayCreation(elementType, dimensions, sizeArguments, initializerElementResults); + } + return acrr; + } + + void UnpackArrayInitializer(List elementList, ArrayInitializerExpression initializer, int dimensions, bool resolveNestedInitializesToVoid) + { + Debug.Assert(dimensions >= 1); + if (dimensions > 1) { + foreach (var node in initializer.Elements) { + ArrayInitializerExpression aie = node as ArrayInitializerExpression; + if (aie != null) { + if (resolveNestedInitializesToVoid) + StoreResult(aie, voidResult); + UnpackArrayInitializer(elementList, aie, dimensions - 1, resolveNestedInitializesToVoid); + } else { + elementList.Add(node); + } + } + } else { + foreach (var expr in initializer.Elements) + elementList.Add(expr); + } + } + + ResolveResult IAstVisitor.VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data) + { + // Array initializers are handled by their parent expression. + ScanChildren(arrayInitializerExpression); + return errorResult; + } + + ResolveResult IAstVisitor.VisitAsExpression(AsExpression asExpression, object data) + { + if (resolverEnabled) { + Scan(asExpression.Expression); + return new ResolveResult(ResolveType(asExpression.Type)); + } else { + ScanChildren(asExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) + { + if (resolverEnabled) { + ResolveResult left = Resolve(assignmentExpression.Left); + ResolveAndProcessConversion(assignmentExpression.Right, left.Type); + return new ResolveResult(left.Type); + } else { + ScanChildren(assignmentExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveBaseReference(); + } else { + ScanChildren(baseReferenceExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + { + if (resolverEnabled) { + Expression left = binaryOperatorExpression.Left; + Expression right = binaryOperatorExpression.Right; + ResolveResult leftResult = Resolve(left); + ResolveResult rightResult = Resolve(right); + ResolveResult rr = resolver.ResolveBinaryOperator(binaryOperatorExpression.Operator, leftResult, rightResult); + BinaryOperatorResolveResult borr = rr as BinaryOperatorResolveResult; + if (borr != null) { + ProcessConversionResult(left, borr.Left as ConversionResolveResult); + ProcessConversionResult(right, borr.Right as ConversionResolveResult); + } else { + InvocationResolveResult irr = rr as InvocationResolveResult; + if (irr != null && irr.Arguments.Count == 2) { + ProcessConversionResult(left, irr.Arguments[0] as ConversionResolveResult); + ProcessConversionResult(right, irr.Arguments[1] as ConversionResolveResult); + } + } + return rr; + } else { + ScanChildren(binaryOperatorExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitCastExpression(CastExpression castExpression, object data) + { + if (resolverEnabled) { + IType targetType = ResolveType(castExpression.Type); + Expression expr = castExpression.Expression; + ResolveResult rr = resolver.ResolveCast(targetType, Resolve(expr)); + ProcessConversionResult(expr, rr as ConversionResolveResult); + return rr; + } else { + ScanChildren(castExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) + { + if (resolverEnabled) { + Expression condition = conditionalExpression.Condition; + Expression trueExpr = conditionalExpression.TrueExpression; + Expression falseExpr = conditionalExpression.FalseExpression; + + ResolveResult rr = resolver.ResolveConditional(Resolve(condition), Resolve(trueExpr), Resolve(falseExpr)); + ConditionalOperatorResolveResult corr = rr as ConditionalOperatorResolveResult; + if (corr != null) { + ProcessConversionResult(condition, corr.Condition as ConversionResolveResult); + ProcessConversionResult(trueExpr, corr.True as ConversionResolveResult); + ProcessConversionResult(falseExpr, corr.False as ConversionResolveResult); + } + return rr; + } else { + ScanChildren(conditionalExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveDefaultValue(ResolveType(defaultValueExpression.Type)); + } else { + ScanChildren(defaultValueExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitDirectionExpression(DirectionExpression directionExpression, object data) + { + if (resolverEnabled) { + ResolveResult rr = Resolve(directionExpression.Expression); + return new ByReferenceResolveResult(rr, directionExpression.FieldDirection == FieldDirection.Out); + } else { + ScanChildren(directionExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitEmptyExpression(EmptyExpression emptyExpression, object data) + { + return errorResult; + } + + ResolveResult IAstVisitor.VisitIndexerExpression(IndexerExpression indexerExpression, object data) + { + if (resolverEnabled) { + Expression target = indexerExpression.Target; + ResolveResult targetResult = Resolve(target); + string[] argumentNames; + ResolveResult[] arguments = GetArguments(indexerExpression.Arguments, out argumentNames); + ResolveResult rr = resolver.ResolveIndexer(targetResult, arguments, argumentNames); + ArrayAccessResolveResult aarr = rr as ArrayAccessResolveResult; + if (aarr != null) { + ProcessConversionResults(indexerExpression.Arguments, aarr.Indices); + } else { + ProcessConversionsInInvocation(target, indexerExpression.Arguments, rr as CSharpInvocationResolveResult); + } + return rr; + } else { + ScanChildren(indexerExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitIsExpression(IsExpression isExpression, object data) + { + ScanChildren(isExpression); + if (resolverEnabled) + return new ResolveResult(KnownTypeReference.Boolean.Resolve(resolver.Context)); + else + return null; + } + + // NamedArgumentExpression is "identifier: Expression" + ResolveResult IAstVisitor.VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) + { + // The parent expression takes care of handling NamedArgumentExpressions + // by calling GetArguments(). + // 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 + ResolveResult IAstVisitor.VisitNamedExpression(NamedExpression namedExpression, object data) + { + Expression rhs = namedExpression.Expression; + if (rhs is ArrayInitializerExpression) { + ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier); + HandleObjectInitializer(result.Type, (ArrayInitializerExpression)rhs); + return result; + } else { + if (resolverEnabled) { + ResolveResult result = resolver.ResolveIdentifierInObjectInitializer(namedExpression.Identifier); + ResolveAndProcessConversion(rhs, result.Type); + return result; + } else { + ScanChildren(namedExpression); + return null; + } + } + } + + ResolveResult IAstVisitor.VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolvePrimitive(null); + } else { + return null; + } + } + + ResolveResult IAstVisitor.VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) + { + if (resolverEnabled || !objectCreateExpression.Initializer.IsNull) { + IType type = ResolveType(objectCreateExpression.Type); + + var initializer = objectCreateExpression.Initializer; + if (!initializer.IsNull) { + HandleObjectInitializer(type, initializer); + } + + if (resolverEnabled) { + string[] argumentNames; + ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames); + + ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames); + ProcessConversionsInInvocation(null, objectCreateExpression.Arguments, rr as CSharpInvocationResolveResult); + return rr; + } else { + foreach (AstNode node in objectCreateExpression.Arguments) { + Scan(node); + } + return null; + } + } else { + ScanChildren(objectCreateExpression); + return null; + } + } + + 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, resolver.conversions); + var invocationRR = or.CreateResolveResult(targetResult); + StoreResult(aie, invocationRR); + ProcessConversionsInInvocation(null, aie.Elements, invocationRR); + } else { + StoreResult(aie, addRR); + } + } else { + // assignment in object initializer (NamedExpression), + // or some unknown kind of expression + Scan(element); + } + } + resolver.PopInitializerType(); + if (!resolveResultCache.ContainsKey(initializer)) + StoreResult(initializer, voidResult); + } + + ResolveResult IAstVisitor.VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) + { + if (resolverEnabled) { + return Resolve(parenthesizedExpression.Expression); + } else { + Scan(parenthesizedExpression.Expression); + return null; + } + } + + ResolveResult IAstVisitor.VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) + { + if (resolverEnabled) { + ResolveResult target = Resolve(pointerReferenceExpression.Target); + ResolveResult deferencedTarget = resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, target); + List typeArguments = new List(); + foreach (AstType typeArgument in pointerReferenceExpression.TypeArguments) { + typeArguments.Add(ResolveType(typeArgument)); + } + return resolver.ResolveMemberAccess(deferencedTarget, pointerReferenceExpression.MemberName, + typeArguments, + IsTargetOfInvocation(pointerReferenceExpression)); + } else { + ScanChildren(pointerReferenceExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolvePrimitive(primitiveExpression.Value); + } else { + return null; + } + } + + ResolveResult IAstVisitor.VisitSizeOfExpression(SizeOfExpression sizeOfExpression, object data) + { + if (resolverEnabled) { + return resolver.ResolveSizeOf(ResolveType(sizeOfExpression.Type)); + } else { + ScanChildren(sizeOfExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data) + { + if (resolverEnabled) { + ResolveAndProcessConversion(stackAllocExpression.CountExpression, KnownTypeReference.Int32.Resolve(resolver.Context)); + return new ResolveResult(new PointerType(ResolveType(stackAllocExpression.Type))); + } else { + ScanChildren(stackAllocExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) + { + if (resolverEnabled) + return resolver.ResolveThisReference(); + else + return null; + } + + ResolveResult IAstVisitor.VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) + { + ScanChildren(typeOfExpression); + if (resolverEnabled) + return new ResolveResult(KnownTypeReference.Type.Resolve(resolver.Context)); + else + return null; + } + + ResolveResult IAstVisitor.VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) + { + if (resolverEnabled) { + return Resolve(typeReferenceExpression.Type); + } else { + Scan(typeReferenceExpression.Type); + return null; + } + } + + ResolveResult IAstVisitor.VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + { + if (resolverEnabled) { + Expression expr = unaryOperatorExpression.Expression; + ResolveResult input = Resolve(expr); + ResolveResult rr = resolver.ResolveUnaryOperator(unaryOperatorExpression.Operator, input); + UnaryOperatorResolveResult uorr = rr as UnaryOperatorResolveResult; + if (uorr != null) { + ProcessConversionResult(expr, uorr.Input as ConversionResolveResult); + } else { + InvocationResolveResult irr = rr as InvocationResolveResult; + if (irr != null && irr.Arguments.Count == 1) { + ProcessConversionResult(expr, irr.Arguments[0] as ConversionResolveResult); + } + } + return rr; + } else { + ScanChildren(unaryOperatorExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, object data) + { + ScanChildren(undocumentedExpression); + if (resolverEnabled) { + ITypeReference resultType; + switch (undocumentedExpression.UndocumentedExpressionType) { + case UndocumentedExpressionType.ArgListAccess: + case UndocumentedExpressionType.ArgList: + resultType = typeof(RuntimeArgumentHandle).ToTypeReference(); + break; + case UndocumentedExpressionType.RefValue: + var tre = undocumentedExpression.Arguments.ElementAtOrDefault(1) as TypeReferenceExpression; + if (tre != null) + resultType = ResolveType(tre.Type); + else + resultType = SharedTypes.UnknownType; + break; + case UndocumentedExpressionType.RefType: + resultType = KnownTypeReference.Type; + break; + case UndocumentedExpressionType.MakeRef: + resultType = typeof(TypedReference).ToTypeReference(); + break; + default: + throw new InvalidOperationException("Invalid value for UndocumentedExpressionType"); + } + return new ResolveResult(resultType.Resolve(resolver.Context)); + } else { + return null; + } + } + #endregion + + #region Visit Identifier/MemberReference/Invocation-Expression + // IdentifierExpression, MemberReferenceExpression and InvocationExpression + // are grouped together because they have to work together for + // "7.6.4.1 Identical simple names and type names" support + List GetTypeArguments(IEnumerable typeArguments) + { + List result = new List(); + foreach (AstType typeArgument in typeArguments) { + result.Add(ResolveType(typeArgument)); + } + return result; + } + + ResolveResult[] GetArguments(IEnumerable argumentExpressions, out string[] argumentNames) + { + argumentNames = null; + ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()]; + int i = 0; + foreach (AstNode argument in argumentExpressions) { + NamedArgumentExpression nae = argument as NamedArgumentExpression; + AstNode argumentValue; + if (nae != null) { + if (argumentNames == null) + argumentNames = new string[arguments.Length]; + argumentNames[i] = nae.Identifier; + argumentValue = nae.Expression; + } else { + argumentValue = argument; + } + arguments[i++] = Resolve(argumentValue); + } + return arguments; + } + + static bool IsTargetOfInvocation(AstNode node) + { + InvocationExpression ie = node.Parent as InvocationExpression; + return ie != null && ie.Target == node; + } + + bool IsVariableReferenceWithSameType(ResolveResult rr, string identifier, out TypeResolveResult trr) + { + if (!(rr is MemberResolveResult || rr is LocalResolveResult)) { + trr = null; + return false; + } + trr = resolver.LookupSimpleNameOrTypeName(identifier, EmptyList.Instance, SimpleNameLookupMode.Type) as TypeResolveResult; + return trr != null && trr.Type.Equals(rr.Type); + } + + /// + /// Gets whether 'rr' is considered a static access on the target identifier. + /// + /// Resolve Result of the MemberReferenceExpression + /// Resolve Result of the InvocationExpression + bool IsStaticResult(ResolveResult rr, ResolveResult invocationRR) + { + if (rr is TypeResolveResult) + return true; + MemberResolveResult mrr = (rr is MethodGroupResolveResult ? invocationRR : rr) as MemberResolveResult; + return mrr != null && mrr.Member.IsStatic; + } + + ResolveResult IAstVisitor.VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + { + // Note: this method is not called when it occurs in a situation where an ambiguity between + // simple names and type names might occur. + if (resolverEnabled) { + var typeArguments = GetTypeArguments(identifierExpression.TypeArguments); + return resolver.ResolveSimpleName(identifierExpression.Identifier, typeArguments, + IsTargetOfInvocation(identifierExpression)); + } else { + ScanChildren(identifierExpression); + return null; + } + } + + ResolveResult IAstVisitor.VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) + { + // target = Resolve(identifierExpression = memberReferenceExpression.Target) + // trr = ResolveType(identifierExpression) + // rr = Resolve(memberReferenceExpression) + + IdentifierExpression identifierExpression = memberReferenceExpression.Target as IdentifierExpression; + if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0 + && !resolveResultCache.ContainsKey(identifierExpression)) + { + // Special handling for §7.6.4.1 Identicial simple names and type names + StoreState(identifierExpression, resolver.Clone()); + ResolveResult target = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList.Instance); + TypeResolveResult trr; + if (IsVariableReferenceWithSameType(target, identifierExpression.Identifier, out trr)) { + // It's ambiguous + ResolveResult rr = ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression); + ResolveResult simpleNameRR = IsStaticResult(rr, null) ? trr : target; + Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}", identifierExpression, simpleNameRR); + StoreResult(identifierExpression, simpleNameRR); + return rr; + } else { + // It's not ambiguous + Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, target); + StoreResult(identifierExpression, target); + if (resolverEnabled) { + return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression); + } else { + // Scan children (but not the IdentifierExpression which we already resolved) + for (AstNode child = memberReferenceExpression.FirstChild; child != null; child = child.NextSibling) { + if (child != identifierExpression) + Scan(child); + } + return null; + } + } + } else { + // Regular code path + if (resolverEnabled) { + ResolveResult target = Resolve(memberReferenceExpression.Target); + return ResolveMemberReferenceOnGivenTarget(target, memberReferenceExpression); + } else { + ScanChildren(memberReferenceExpression); + return null; + } + } + } + + ResolveResult ResolveMemberReferenceOnGivenTarget(ResolveResult target, MemberReferenceExpression memberReferenceExpression) + { + var typeArguments = GetTypeArguments(memberReferenceExpression.TypeArguments); + return resolver.ResolveMemberAccess( + target, memberReferenceExpression.MemberName, typeArguments, + IsTargetOfInvocation(memberReferenceExpression)); + } + + ResolveResult IAstVisitor.VisitInvocationExpression(InvocationExpression invocationExpression, object data) + { + // rr = Resolve(invocationExpression) + // target = Resolve(memberReferenceExpression = invocationExpression.Target) + // idRR = Resolve(identifierExpression = memberReferenceExpression.Target) + // trr = ResolveType(identifierExpression) + + MemberReferenceExpression mre = invocationExpression.Target as MemberReferenceExpression; + IdentifierExpression identifierExpression = mre != null ? mre.Target as IdentifierExpression : null; + if (identifierExpression != null && identifierExpression.TypeArguments.Count == 0 + && !resolveResultCache.ContainsKey(identifierExpression)) + { + // Special handling for §7.6.4.1 Identicial simple names and type names + ResolveResult idRR = resolver.ResolveSimpleName(identifierExpression.Identifier, EmptyList.Instance); + ResolveResult target = ResolveMemberReferenceOnGivenTarget(idRR, mre); + Log.WriteLine("Member reference '{0}' on potentially-ambiguous simple-name was resolved to {1}", mre, target); + StoreResult(mre, target); + TypeResolveResult trr; + if (IsVariableReferenceWithSameType(idRR, identifierExpression.Identifier, out trr)) { + // It's ambiguous + ResolveResult rr = ResolveInvocationOnGivenTarget(target, invocationExpression); + ResolveResult simpleNameRR = IsStaticResult(target, rr) ? trr : idRR; + Log.WriteLine("Ambiguous simple name '{0}' was resolved to {1}", + identifierExpression, simpleNameRR); + StoreResult(identifierExpression, simpleNameRR); + return rr; + } else { + // It's not ambiguous + Log.WriteLine("Simple name '{0}' was resolved to {1}", identifierExpression, idRR); + StoreResult(identifierExpression, idRR); + if (resolverEnabled) { + return ResolveInvocationOnGivenTarget(target, invocationExpression); + } else { + // Scan children (but not the MRE which we already resolved) + for (AstNode child = invocationExpression.FirstChild; child != null; child = child.NextSibling) { + if (child != mre) + Scan(child); + } + return null; + } + } + } else { + // Regular code path + if (resolverEnabled) { + ResolveResult target = Resolve(invocationExpression.Target); + return ResolveInvocationOnGivenTarget(target, invocationExpression); + } else { + ScanChildren(invocationExpression); + return null; + } + } + } + + ResolveResult ResolveInvocationOnGivenTarget(ResolveResult target, InvocationExpression invocationExpression) + { + string[] argumentNames; + ResolveResult[] arguments = GetArguments(invocationExpression.Arguments, out argumentNames); + ResolveResult rr = resolver.ResolveInvocation(target, arguments, argumentNames); + ProcessConversionsInInvocation(invocationExpression.Target, invocationExpression.Arguments, rr as CSharpInvocationResolveResult); + return rr; + } + #endregion + + #region Lamdbas / Anonymous Functions + ResolveResult IAstVisitor.VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) + { + return HandleExplicitlyTypedLambda( + anonymousMethodExpression.Parameters, anonymousMethodExpression.Body, + isAnonymousMethod: true, + hasParameterList: anonymousMethodExpression.HasParameterList, + isAsync: anonymousMethodExpression.IsAsync); + } + + ResolveResult IAstVisitor.VisitLambdaExpression(LambdaExpression lambdaExpression, object data) + { + Debug.Assert(resolverEnabled); + bool isExplicitlyTyped = false; + bool isImplicitlyTyped = false; + foreach (var p in lambdaExpression.Parameters) { + isImplicitlyTyped |= p.Type.IsNull; + isExplicitlyTyped |= !p.Type.IsNull; + } + if (isExplicitlyTyped || !isImplicitlyTyped) { + return HandleExplicitlyTypedLambda( + lambdaExpression.Parameters, lambdaExpression.Body, + isAnonymousMethod: false, hasParameterList: true, isAsync: lambdaExpression.IsAsync); + } else { + return new ImplicitlyTypedLambda(lambdaExpression, this); + } + } + + #region Explicitly typed + ExplicitlyTypedLambda HandleExplicitlyTypedLambda( + AstNodeCollection parameterDeclarations, + AstNode body, bool isAnonymousMethod, bool hasParameterList, bool isAsync) + { + List parameters = new List(); + resolver.PushLambdaBlock(); + foreach (var pd in parameterDeclarations) { + ITypeReference type = MakeTypeReference(pd.Type); + if (pd.ParameterModifier == ParameterModifier.Ref || pd.ParameterModifier == ParameterModifier.Out) + type = ByReferenceTypeReference.Create(type); + + var p = resolver.AddLambdaParameter(type, MakeRegion(pd), pd.Name, + isRef: pd.ParameterModifier == ParameterModifier.Ref, + isOut: pd.ParameterModifier == ParameterModifier.Out); + parameters.Add(p); + Scan(pd); + } + + var lambda = new ExplicitlyTypedLambda(parameters, isAnonymousMethod, isAsync, resolver.Clone(), this, body); + + // Don't scan the lambda body here - we'll do that later when analyzing the ExplicitlyTypedLambda. + + resolver.PopBlock(); + return lambda; + } + + DomRegion MakeRegion(AstNode node) + { + return new DomRegion(parsedFile != null ? parsedFile.FileName : null, node.StartLocation, node.EndLocation); + } + + sealed class ExplicitlyTypedLambda : LambdaBase + { + readonly IList parameters; + readonly bool isAnonymousMethod; + readonly bool isAsync; + + CSharpResolver storedContext; + ResolveVisitor visitor; + AstNode body; + + IType inferredReturnType; + IList returnExpressions; + IList returnValues; + bool isValidAsVoidMethod; + bool success; + + // The actual return type is set when the lambda is applied by the conversion. + IType actualReturnType; + + internal override bool IsUndecided { + get { return actualReturnType == null; } + } + + internal override AstNode LambdaExpression { + get { return body.Parent; } + } + + internal override AstNode Body { + get { return body; } + } + + public ExplicitlyTypedLambda(IList parameters, bool isAnonymousMethod, bool isAsync, CSharpResolver storedContext, ResolveVisitor visitor, AstNode body) + { + this.parameters = parameters; + this.isAnonymousMethod = isAnonymousMethod; + this.isAsync = isAsync; + this.storedContext = storedContext; + this.visitor = visitor; + this.body = body; + + if (visitor.undecidedLambdas == null) + visitor.undecidedLambdas = new List(); + visitor.undecidedLambdas.Add(this); + Log.WriteLine("Added undecided explicitly-typed lambda: " + this.LambdaExpression); + } + + public override IList Parameters { + get { + return parameters ?? EmptyList.Instance; + } + } + + bool Analyze() + { + // If it's not already analyzed + if (inferredReturnType == null) { + Log.WriteLine("Analyzing " + this.LambdaExpression + "..."); + Log.Indent(); + + visitor.ResetContext( + storedContext, + delegate { + var oldNavigator = visitor.navigator; + visitor.navigator = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Resolve, oldNavigator); + visitor.AnalyzeLambda(body, isAsync, out success, out isValidAsVoidMethod, out inferredReturnType, out returnExpressions, out returnValues); + visitor.navigator = oldNavigator; + }); + Log.Unindent(); + Log.WriteLine("Finished analyzing " + this.LambdaExpression); + + if (inferredReturnType == null) + throw new InvalidOperationException("AnalyzeLambda() didn't set inferredReturnType"); + } + return success; + } + + public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions) + { + Log.WriteLine("Testing validity of {0} for return-type {1}...", this, returnType); + Log.Indent(); + bool valid = Analyze() && IsValidLambda(isValidAsVoidMethod, isAsync, returnValues, returnType, conversions); + Log.Unindent(); + Log.WriteLine("{0} is {1} for return-type {2}", this, valid ? "valid" : "invalid", returnType); + if (valid) { + return Conversion.AnonymousFunctionConversion(new AnonymousFunctionConversionData(returnType, this)); + } else { + return Conversion.None; + } + } + + public override IType GetInferredReturnType(IType[] parameterTypes) + { + Analyze(); + return inferredReturnType; + } + + public override bool IsImplicitlyTyped { + get { return false; } + } + + public override bool IsAsync { + get { return isAsync; } + } + + public override bool IsAnonymousMethod { + get { return isAnonymousMethod; } + } + + public override bool HasParameterList { + get { return parameters != null; } + } + + public override string ToString() + { + return "[ExplicitlyTypedLambda " + this.LambdaExpression + "]"; + } + + public void ApplyReturnType(ResolveVisitor parentVisitor, IType returnType) + { + if (returnType == null) + throw new ArgumentNullException("returnType"); + if (parentVisitor != visitor) { + // Explicitly typed lambdas do not use a nested visitor + throw new InvalidOperationException(); + } + if (actualReturnType != null) { + if (actualReturnType.Equals(returnType)) + return; // return type already set + throw new InvalidOperationException("inconsistent return types for explicitly-typed lambda"); + } + actualReturnType = returnType; + visitor.undecidedLambdas.Remove(this); + Analyze(); + Log.WriteLine("Applying return type {0} to explicitly-typed lambda {1}", returnType, this.LambdaExpression); + if (isAsync) + returnType = parentVisitor.UnpackTask(returnType); + for (int i = 0; i < returnExpressions.Count; i++) { + visitor.ProcessConversion(returnExpressions[i], returnValues[i], returnType); + } + } + + internal override void EnforceMerge(ResolveVisitor parentVisitor) + { + ApplyReturnType(parentVisitor, SharedTypes.UnknownType); + } + } + #endregion + + #region Implicitly typed + sealed class ImplicitlyTypedLambda : LambdaBase + { + readonly LambdaExpression lambda; + readonly QuerySelectClause selectClause; + + readonly CSharpResolver storedContext; + readonly CSharpParsedFile parsedFile; + readonly List hypotheses = new List(); + readonly List parameters = new List(); + + internal LambdaTypeHypothesis winningHypothesis; + internal readonly ResolveVisitor parentVisitor; + + internal override bool IsUndecided { + get { return winningHypothesis == null; } + } + + internal override AstNode LambdaExpression { + get { + if (selectClause != null) + return selectClause.Expression; + else + return lambda; + } + } + + internal override AstNode Body { + get { + if (selectClause != null) + return selectClause.Expression; + else + return lambda.Body; + } + } + + private ImplicitlyTypedLambda(ResolveVisitor parentVisitor) + { + this.parentVisitor = parentVisitor; + this.storedContext = parentVisitor.resolver.Clone(); + this.parsedFile = parentVisitor.parsedFile; + } + + public ImplicitlyTypedLambda(LambdaExpression lambda, ResolveVisitor parentVisitor) + : this(parentVisitor) + { + this.lambda = lambda; + foreach (var pd in lambda.Parameters) { + parameters.Add(new DefaultParameter(SharedTypes.UnknownType, pd.Name) { + Region = parentVisitor.MakeRegion(pd) + }); + } + RegisterUndecidedLambda(); + } + + public ImplicitlyTypedLambda(QuerySelectClause selectClause, IEnumerable parameters, ResolveVisitor parentVisitor) + : this(parentVisitor) + { + this.selectClause = selectClause; + this.parameters.AddRange(parameters); + + RegisterUndecidedLambda(); + } + + void RegisterUndecidedLambda() + { + if (parentVisitor.undecidedLambdas == null) + parentVisitor.undecidedLambdas = new List(); + parentVisitor.undecidedLambdas.Add(this); + Log.WriteLine("Added undecided implicitly-typed lambda: " + this.LambdaExpression); + } + + public override IList Parameters { + get { return parameters; } + } + + public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions) + { + Log.WriteLine("Testing validity of {0} for parameters ({1}) and return-type {2}...", + this, string.Join(", ", parameterTypes), returnType); + Log.Indent(); + var hypothesis = GetHypothesis(parameterTypes); + Conversion c = hypothesis.IsValid(returnType, conversions); + Log.Unindent(); + Log.WriteLine("{0} is {1} for return-type {2}", hypothesis, c ? "valid" : "invalid", returnType); + return c; + } + + public override IType GetInferredReturnType(IType[] parameterTypes) + { + return GetHypothesis(parameterTypes).inferredReturnType; + } + + LambdaTypeHypothesis GetHypothesis(IType[] parameterTypes) + { + if (parameterTypes.Length != parameters.Count) + throw new ArgumentException("Incorrect parameter type count"); + foreach (var h in hypotheses) { + bool ok = true; + for (int i = 0; i < parameterTypes.Length; i++) { + if (!parameterTypes[i].Equals(h.parameterTypes[i])) { + ok = false; + break; + } + } + if (ok) + return h; + } + var resolveAll = new ConstantModeResolveVisitorNavigator(ResolveVisitorNavigationMode.Resolve, null); + ResolveVisitor visitor = new ResolveVisitor(storedContext.Clone(), parsedFile, resolveAll); + var newHypothesis = new LambdaTypeHypothesis(this, parameterTypes, visitor, lambda != null ? lambda.Parameters : null); + hypotheses.Add(newHypothesis); + return newHypothesis; + } + + /// + /// Get any hypothesis for this lambda. + /// This method is used as fallback if the lambda isn't merged the normal way (AnonymousFunctionConversion) + /// + internal LambdaTypeHypothesis GetAnyHypothesis() + { + if (winningHypothesis != null) + return winningHypothesis; + if (hypotheses.Count == 0) { + // make a new hypothesis with unknown parameter types + IType[] parameterTypes = new IType[parameters.Count]; + for (int i = 0; i < parameterTypes.Length; i++) { + parameterTypes[i] = SharedTypes.UnknownType; + } + return GetHypothesis(parameterTypes); + } else { + // We have the choice, so pick the hypothesis with the least missing parameter types + LambdaTypeHypothesis bestHypothesis = hypotheses[0]; + int bestHypothesisUnknownParameters = bestHypothesis.CountUnknownParameters(); + for (int i = 1; i < hypotheses.Count; i++) { + int c = hypotheses[i].CountUnknownParameters(); + if (c < bestHypothesisUnknownParameters || + (c == bestHypothesisUnknownParameters && hypotheses[i].success && !bestHypothesis.success)) + { + bestHypothesis = hypotheses[i]; + bestHypothesisUnknownParameters = c; + } + } + return bestHypothesis; + } + } + + internal override void EnforceMerge(ResolveVisitor parentVisitor) + { + GetAnyHypothesis().MergeInto(parentVisitor, SharedTypes.UnknownType); + } + + public override bool IsImplicitlyTyped { + get { return true; } + } + + public override bool IsAnonymousMethod { + get { return false; } + } + + public override bool HasParameterList { + get { return true; } + } + + public override bool IsAsync { + get { return lambda.IsAsync; } + } + + public override string ToString() + { + return "[ImplicitlyTypedLambda " + this.LambdaExpression + "]"; + } + } + + /// + /// Every possible set of parameter types gets its own 'hypothetical world'. + /// It uses a nested ResolveVisitor that has its own resolve cache, so that resolve results cannot leave the hypothetical world. + /// + /// Only after overload resolution is applied and the actual parameter types are known, the winning hypothesis will be merged + /// with the parent ResolveVisitor. + /// This is done when the AnonymousFunctionConversion is applied on the parent visitor. + /// + sealed class LambdaTypeHypothesis + { + readonly ImplicitlyTypedLambda lambda; + internal readonly IParameter[] lambdaParameters; + internal readonly IType[] parameterTypes; + readonly ResolveVisitor visitor; + + internal readonly IType inferredReturnType; + IList returnExpressions; + IList returnValues; + bool isValidAsVoidMethod; + internal bool success; + + public LambdaTypeHypothesis(ImplicitlyTypedLambda lambda, IType[] parameterTypes, ResolveVisitor visitor, + ICollection parameterDeclarations) + { + Debug.Assert(parameterTypes.Length == lambda.Parameters.Count); + + this.lambda = lambda; + this.parameterTypes = parameterTypes; + this.visitor = visitor; + + Log.WriteLine("Analyzing " + ToString() + "..."); + Log.Indent(); + visitor.resolver.PushLambdaBlock(); + lambdaParameters = new IParameter[parameterTypes.Length]; + if (parameterDeclarations != null) { + int i = 0; + foreach (var pd in parameterDeclarations) { + lambdaParameters[i] = visitor.resolver.AddLambdaParameter(parameterTypes[i], visitor.MakeRegion(pd), pd.Name); + i++; + visitor.Scan(pd); + } + } else { + for (int i = 0; i < parameterTypes.Length; i++) { + var p = lambda.Parameters[i]; + lambdaParameters[i] = visitor.resolver.AddLambdaParameter(parameterTypes[i], p.Region, p.Name); + } + } + + visitor.AnalyzeLambda(lambda.Body, lambda.IsAsync, out success, out isValidAsVoidMethod, out inferredReturnType, out returnExpressions, out returnValues); + visitor.resolver.PopBlock(); + Log.Unindent(); + Log.WriteLine("Finished analyzing " + ToString()); + } + + internal int CountUnknownParameters() + { + int c = 0; + foreach (IType t in parameterTypes) { + if (t.Kind == TypeKind.Unknown) + c++; + } + return c; + } + + public Conversion IsValid(IType returnType, Conversions conversions) + { + if (success && IsValidLambda(isValidAsVoidMethod, lambda.IsAsync, returnValues, returnType, conversions)) { + return Conversion.AnonymousFunctionConversion(new AnonymousFunctionConversionData(returnType, this)); + } else { + return Conversion.None; + } + } + + public void MergeInto(ResolveVisitor parentVisitor, IType returnType) + { + if (returnType == null) + throw new ArgumentNullException("returnType"); + if (parentVisitor != lambda.parentVisitor) + throw new InvalidOperationException("parent visitor mismatch"); + + if (lambda.winningHypothesis == this) + return; + else if (lambda.winningHypothesis != null) + throw new InvalidOperationException("Trying to merge conflicting hypotheses"); + + lambda.winningHypothesis = this; + + Log.WriteLine("Applying return type {0} to implicitly-typed lambda {1}", returnType, lambda.LambdaExpression); + if (lambda.IsAsync) + returnType = parentVisitor.UnpackTask(returnType); + for (int i = 0; i < returnExpressions.Count; i++) { + visitor.ProcessConversion(returnExpressions[i], returnValues[i], returnType); + } + + visitor.MergeUndecidedLambdas(); + Log.WriteLine("Merging " + ToString()); + foreach (var pair in visitor.resolveResultCache) { + parentVisitor.StoreResult(pair.Key, pair.Value); + } + foreach (var pair in visitor.resolverBeforeDict) { + parentVisitor.StoreState(pair.Key, pair.Value); + } + parentVisitor.undecidedLambdas.Remove(lambda); + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append("[LambdaTypeHypothesis ("); + for (int i = 0; i < parameterTypes.Length; i++) { + if (i > 0) b.Append(", "); + b.Append(parameterTypes[i]); + b.Append(' '); + b.Append(lambda.Parameters[i].Name); + } + b.Append(") => "); + b.Append(lambda.Body.ToString()); + b.Append(']'); + return b.ToString(); + } + } + #endregion + + #region MergeUndecidedLambdas + abstract class LambdaBase : LambdaResolveResult + { + internal abstract bool IsUndecided { get; } + internal abstract AstNode LambdaExpression { get; } + internal abstract AstNode Body { get; } + + internal abstract void EnforceMerge(ResolveVisitor parentVisitor); + } + + void MergeUndecidedLambdas() + { + if (undecidedLambdas == null || undecidedLambdas.Count == 0) + return; + Log.WriteLine("MergeUndecidedLambdas()..."); + Log.Indent(); + while (undecidedLambdas.Count > 0) { + LambdaBase lambda = undecidedLambdas[0]; + AstNode parent = lambda.LambdaExpression.Parent; + // Continue going upwards until we find a node that can be resolved and provides + // an expected type. + while (ActsAsParenthesizedExpression(parent) || parent is NamedArgumentExpression || parent is ArrayInitializerExpression) { + parent = parent.Parent; + } + CSharpResolver storedResolver; + if (parent != null && resolverBeforeDict.TryGetValue(parent, out storedResolver)) { + Log.WriteLine("Trying to resolve '" + parent + "' in order to merge the lambda..."); + Log.Indent(); + ResetContext(storedResolver.Clone(), delegate { Resolve(parent); }); + Log.Unindent(); + } else { + Log.WriteLine("Could not find a suitable parent for '" + lambda); + } + if (lambda.IsUndecided) { + // Lambda wasn't merged by resolving its parent -> enforce merging + Log.WriteLine("Lambda wasn't merged by conversion - enforce merging"); + lambda.EnforceMerge(this); + } + } + Log.Unindent(); + Log.WriteLine("MergeUndecidedLambdas() finished."); + } + + internal static bool ActsAsParenthesizedExpression(AstNode expression) + { + return expression is ParenthesizedExpression || expression is CheckedExpression || expression is UncheckedExpression; + } + + internal static Expression UnpackParenthesizedExpression(Expression expr) + { + while (ActsAsParenthesizedExpression(expr)) + expr = expr.GetChildByRole(ParenthesizedExpression.Roles.Expression); + return expr; + } + #endregion + + #region AnalyzeLambda + IType GetTaskType(IType resultType) + { + if (resultType.Kind == TypeKind.Unknown) + return SharedTypes.UnknownType; + if (resultType.Kind == TypeKind.Void) + return resolver.Context.GetTypeDefinition("System.Threading.Tasks", "Task", 0, StringComparer.Ordinal) ?? SharedTypes.UnknownType; + + ITypeDefinition def = resolver.Context.GetTypeDefinition("System.Threading.Tasks", "Task", 1, StringComparer.Ordinal); + if (def != null) + return new ParameterizedType(def, new[] { resultType }); + else + return SharedTypes.UnknownType; + } + + void AnalyzeLambda(AstNode body, bool isAsync, out bool success, out bool isValidAsVoidMethod, out IType inferredReturnType, out IList returnExpressions, out IList returnValues) + { + Expression expr = body as Expression; + if (expr != null) { + isValidAsVoidMethod = ExpressionPermittedAsStatement(expr); + returnExpressions = new [] { expr }; + returnValues = new[] { Resolve(expr) }; + inferredReturnType = returnValues[0].Type; + } else { + Scan(body); + + AnalyzeLambdaVisitor alv = new AnalyzeLambdaVisitor(); + body.AcceptVisitor(alv, null); + isValidAsVoidMethod = (alv.ReturnExpressions.Count == 0); + if (alv.HasVoidReturnStatements) { + returnExpressions = EmptyList.Instance; + returnValues = EmptyList.Instance; + inferredReturnType = KnownTypeReference.Void.Resolve(resolver.Context); + } else { + returnExpressions = alv.ReturnExpressions; + returnValues = new ResolveResult[returnExpressions.Count]; + for (int i = 0; i < returnValues.Count; i++) { + returnValues[i] = resolveResultCache[returnExpressions[i]]; + } + TypeInference ti = new TypeInference(resolver.Context, resolver.conversions); + bool tiSuccess; + inferredReturnType = ti.GetBestCommonType(returnValues, out tiSuccess); + // Failure to infer a return type does not make the lambda invalid, + // so we can ignore the 'tiSuccess' value + } + } + if (isAsync) + inferredReturnType = GetTaskType(inferredReturnType); + Log.WriteLine("Lambda return type was inferred to: " + inferredReturnType); + // TODO: check for compiler errors within the lambda body + + success = true; + } + + static bool ExpressionPermittedAsStatement(Expression expr) + { + UnaryOperatorExpression uoe = expr as UnaryOperatorExpression; + if (uoe != null) { + switch (uoe.Operator) { + case UnaryOperatorType.Increment: + case UnaryOperatorType.Decrement: + case UnaryOperatorType.PostIncrement: + case UnaryOperatorType.PostDecrement: + case UnaryOperatorType.Await: + return true; + default: + return false; + } + } + return expr is InvocationExpression + || expr is ObjectCreateExpression + || expr is AssignmentExpression; + } + + static bool IsValidLambda(bool isValidAsVoidMethod, bool isAsync, IList returnValues, IType returnType, Conversions conversions) + { + if (returnType.Kind == TypeKind.Void) { + // Lambdas that are valid statement lambdas or expression lambdas with a statement-expression + // can be converted to delegates with void return type. + // This holds for both async and regular lambdas. + return isValidAsVoidMethod; + } else if (isAsync && IsTask(returnType) && returnType.TypeParameterCount == 0) { + // Additionally, async lambdas with the above property can be converted to non-generic Task. + return isValidAsVoidMethod; + } else { + if (returnValues.Count == 0) + return false; + if (isAsync) { + // async lambdas must return Task + if (!(IsTask(returnType) && returnType.TypeParameterCount == 1)) + return false; + // unpack Task for testing the implicit conversions + returnType = ((ParameterizedType)returnType).GetTypeArgument(0); + } + foreach (ResolveResult returnRR in returnValues) { + if (!conversions.ImplicitConversion(returnRR, returnType)) + return false; + } + return true; + } + } + + /// + /// Gets the T in Task<T>. + /// Returns void for non-generic Task. + /// + IType UnpackTask(IType type) + { + if (!IsTask(type)) + return type; + if (type.TypeParameterCount == 0) + return KnownTypeReference.Void.Resolve(resolver.Context); + else + return ((ParameterizedType)type).GetTypeArgument(0); + } + + /// + /// Gets whether the specified type is Task or Task<T>. + /// + static bool IsTask(IType type) + { + if (type.Kind == TypeKind.Class && type.Name == "Task" && type.Namespace == "System.Threading.Tasks") { + if (type.TypeParameterCount == 0) + return true; + if (type.TypeParameterCount == 1) + return type is ParameterizedType; + } + return false; + } + + sealed class AnalyzeLambdaVisitor : DepthFirstAstVisitor + { + public bool HasVoidReturnStatements; + public List ReturnExpressions = new List(); + + public override object VisitReturnStatement(ReturnStatement returnStatement, object data) + { + Expression expr = returnStatement.Expression; + if (expr.IsNull) { + HasVoidReturnStatements = true; + } else { + ReturnExpressions.Add(expr); + } + return null; + } + + public override object VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) + { + // don't go into nested lambdas + return null; + } + + public override object VisitLambdaExpression(LambdaExpression lambdaExpression, object data) + { + return null; + } + } + #endregion + #endregion + + #region Local Variable Scopes (Block Statements) + ResolveResult IAstVisitor.VisitBlockStatement(BlockStatement blockStatement, object data) + { + resolver.PushBlock(); + ScanChildren(blockStatement); + resolver.PopBlock(); + return voidResult; + } + + ResolveResult IAstVisitor.VisitUsingStatement(UsingStatement usingStatement, object data) + { + resolver.PushBlock(); + if (resolverEnabled) { + for (AstNode child = usingStatement.FirstChild; child != null; child = child.NextSibling) { + if (child.Role == UsingStatement.ResourceAcquisitionRole && child is Expression) { + ITypeDefinition disposable = resolver.Context.GetTypeDefinition( + "System", "IDisposable", 0, StringComparer.Ordinal); + ResolveAndProcessConversion((Expression)child, disposable ?? SharedTypes.UnknownType); + } else { + Scan(child); + } + } + } else { + ScanChildren(usingStatement); + } + resolver.PopBlock(); + return voidResult; + } + + ResolveResult IAstVisitor.VisitFixedStatement(FixedStatement fixedStatement, object data) + { + resolver.PushBlock(); + ITypeReference type = MakeTypeReference(fixedStatement.Type); + for (AstNode node = fixedStatement.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == FixedStatement.Roles.Variable) { + VariableInitializer vi = (VariableInitializer)node; + resolver.AddVariable(type, MakeRegion(vi) , vi.Name); + } + Scan(node); + } + resolver.PopBlock(); + return voidResult; + } + + ResolveResult IAstVisitor.VisitForeachStatement(ForeachStatement foreachStatement, object data) + { + resolver.PushBlock(); + ITypeReference type; + if (IsVar(foreachStatement.VariableType)) { + if (navigator.Scan(foreachStatement.VariableType) == ResolveVisitorNavigationMode.Resolve) { + IType collectionType = Resolve(foreachStatement.InExpression).Type; + IType elementType = GetElementType(collectionType, resolver.Context, false); + StoreResult(foreachStatement.VariableType, new TypeResolveResult(elementType)); + type = elementType; + } else { + Scan(foreachStatement.InExpression); + type = MakeVarTypeReference(foreachStatement.InExpression, true); + } + } else { + type = ResolveType(foreachStatement.VariableType); + } + IVariable v = resolver.AddVariable(type, MakeRegion(foreachStatement.VariableNameToken), foreachStatement.VariableName); + StoreResult(foreachStatement.VariableNameToken, new LocalResolveResult(v, v.Type.Resolve(resolver.Context))); + Scan(foreachStatement.EmbeddedStatement); + resolver.PopBlock(); + return voidResult; + } + + ResolveResult IAstVisitor.VisitSwitchStatement(SwitchStatement switchStatement, object data) + { + resolver.PushBlock(); + ScanChildren(switchStatement); + resolver.PopBlock(); + return voidResult; + } + + ResolveResult IAstVisitor.VisitCatchClause(CatchClause catchClause, object data) + { + resolver.PushBlock(); + if (!string.IsNullOrEmpty(catchClause.VariableName)) { + ITypeReference variableType = MakeTypeReference(catchClause.Type); + DomRegion region = MakeRegion(catchClause.VariableNameToken); + IVariable v = resolver.AddVariable(variableType, region, catchClause.VariableName); + StoreResult(catchClause.VariableNameToken, new LocalResolveResult(v, v.Type.Resolve(resolver.Context))); + } + ScanChildren(catchClause); + resolver.PopBlock(); + return voidResult; + } + #endregion + + #region VariableDeclarationStatement + ResolveResult IAstVisitor.VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data) + { + bool isConst = (variableDeclarationStatement.Modifiers & Modifiers.Const) != 0; + if (!isConst && IsVar(variableDeclarationStatement.Type) && variableDeclarationStatement.Variables.Count == 1) { + VariableInitializer vi = variableDeclarationStatement.Variables.Single(); + bool needResolve = resolverEnabled + || navigator.Scan(variableDeclarationStatement.Type) == ResolveVisitorNavigationMode.Resolve + || navigator.Scan(vi) == ResolveVisitorNavigationMode.Resolve; + ITypeReference type; + if (needResolve) { + type = Resolve(vi.Initializer).Type; + if (!resolveResultCache.ContainsKey(variableDeclarationStatement.Type)) { + StoreResult(variableDeclarationStatement.Type, new TypeResolveResult(type.Resolve(resolver.Context))); + } + } else { + Scan(vi.Initializer); + type = MakeVarTypeReference(vi.Initializer, false); + } + IVariable v = resolver.AddVariable(type, MakeRegion(vi), vi.Name); + StoreState(vi, resolver.Clone()); + if (needResolve) { + ResolveResult result; + if (!resolveResultCache.TryGetValue(vi, out result)) { + result = new LocalResolveResult(v, type.Resolve(resolver.Context)); + StoreResult(vi, result); + } + return result; + } else { + return null; + } + } else { + ITypeReference type = MakeTypeReference(variableDeclarationStatement.Type); + + int initializerCount = variableDeclarationStatement.Variables.Count; + ResolveResult result = null; + for (AstNode node = variableDeclarationStatement.FirstChild; node != null; node = node.NextSibling) { + if (node.Role == VariableDeclarationStatement.Roles.Variable) { + VariableInitializer vi = (VariableInitializer)node; + + IConstantValue cv = null; + if (isConst) { + cv = TypeSystemConvertVisitor.ConvertConstantValue(type, vi.Initializer, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope); + } + resolver.AddVariable(type, MakeRegion(vi), vi.Name, cv); + + if (resolverEnabled && initializerCount == 1) { + result = Resolve(node); + } else { + Scan(node); + } + } else { + Scan(node); + } + } + return result; + } + } + #endregion + + #region Condition Statements + ResolveResult IAstVisitor.VisitForStatement(ForStatement forStatement, object data) + { + resolver.PushBlock(); + HandleConditionStatement(forStatement); + resolver.PopBlock(); + return voidResult; + } + + ResolveResult IAstVisitor.VisitIfElseStatement(IfElseStatement ifElseStatement, object data) + { + HandleConditionStatement(ifElseStatement); + return voidResult; + } + + ResolveResult IAstVisitor.VisitWhileStatement(WhileStatement whileStatement, object data) + { + HandleConditionStatement(whileStatement); + return voidResult; + } + + ResolveResult IAstVisitor.VisitDoWhileStatement(DoWhileStatement doWhileStatement, object data) + { + HandleConditionStatement(doWhileStatement); + return voidResult; + } + + void HandleConditionStatement(Statement conditionStatement) + { + if (resolverEnabled) { + for (AstNode child = conditionStatement.FirstChild; child != null; child = child.NextSibling) { + if (child.Role == AstNode.Roles.Condition) { + ResolveAndProcessConversion((Expression)child, KnownTypeReference.Boolean.Resolve(resolver.Context)); + } else { + Scan(child); + } + } + } else { + ScanChildren(conditionStatement); + } + } + #endregion + + #region Return Statements + ResolveResult IAstVisitor.VisitReturnStatement(ReturnStatement returnStatement, object data) + { + if (resolverEnabled && !resolver.IsWithinLambdaExpression && resolver.CurrentMember != null) { + IType type = resolver.CurrentMember.ReturnType.Resolve(resolver.Context); + if (IsTask(type)) { + var methodDecl = returnStatement.Ancestors.OfType().FirstOrDefault(); + if (methodDecl != null && (methodDecl.Modifiers & Modifiers.Async) == Modifiers.Async) + type = UnpackTask(type); + } + ResolveAndProcessConversion(returnStatement.Expression, type); + } else { + Scan(returnStatement.Expression); + } + return voidResult; + } + + ResolveResult IAstVisitor.VisitYieldReturnStatement(YieldReturnStatement yieldStatement, object data) + { + if (resolverEnabled && resolver.CurrentMember != null) { + IType returnType = resolver.CurrentMember.ReturnType.Resolve(resolver.Context); + IType elementType = GetElementType(returnType, resolver.Context, true); + ResolveAndProcessConversion(yieldStatement.Expression, elementType); + } else { + Scan(yieldStatement.Expression); + } + return voidResult; + } + + ResolveResult IAstVisitor.VisitYieldBreakStatement(YieldBreakStatement yieldBreakStatement, object data) + { + return voidResult; + } + #endregion + + #region Other statements + ResolveResult IAstVisitor.VisitExpressionStatement(ExpressionStatement expressionStatement, object data) + { + ScanChildren(expressionStatement); + return voidResult; + } + + ResolveResult IAstVisitor.VisitLockStatement(LockStatement lockStatement, object data) + { + ScanChildren(lockStatement); + return voidResult; + } + + ResolveResult IAstVisitor.VisitEmptyStatement(EmptyStatement emptyStatement, object data) + { + return voidResult; + } + + ResolveResult IAstVisitor.VisitBreakStatement(BreakStatement breakStatement, object data) + { + return voidResult; + } + + ResolveResult IAstVisitor.VisitContinueStatement(ContinueStatement continueStatement, object data) + { + return voidResult; + } + + ResolveResult IAstVisitor.VisitThrowStatement(ThrowStatement throwStatement, object data) + { + Scan(throwStatement.Expression); + return voidResult; + } + + ResolveResult IAstVisitor.VisitTryCatchStatement(TryCatchStatement tryCatchStatement, object data) + { + ScanChildren(tryCatchStatement); + return voidResult; + } + + ResolveResult IAstVisitor.VisitGotoCaseStatement(GotoCaseStatement gotoCaseStatement, object data) + { + ScanChildren(gotoCaseStatement); + return voidResult; + } + + ResolveResult IAstVisitor.VisitGotoDefaultStatement(GotoDefaultStatement gotoDefaultStatement, object data) + { + return voidResult; + } + + ResolveResult IAstVisitor.VisitGotoStatement(GotoStatement gotoStatement, object data) + { + return voidResult; + } + + ResolveResult IAstVisitor.VisitLabelStatement(LabelStatement labelStatement, object data) + { + return voidResult; + } + + ResolveResult IAstVisitor.VisitUnsafeStatement(UnsafeStatement unsafeStatement, object data) + { + return voidResult; + } + #endregion + + #region Local Variable Type Inference + static bool IsVar(AstNode returnType) + { + SimpleType st = returnType as SimpleType; + return st != null && st.Identifier == "var" && st.TypeArguments.Count == 0; + } + + ITypeReference MakeTypeReference(AstType type) + { + return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope, currentTypeLookupMode); + } + + ITypeReference MakeVarTypeReference(Expression initializer, bool isForEach) + { + return new VarTypeReference(this, resolver.Clone(), initializer, isForEach); + } + + sealed class VarTypeReference : ITypeReference + { + ResolveVisitor visitor; + CSharpResolver storedContext; + AstNode initializerExpression; + bool isForEach; + + IType result; + + public VarTypeReference(ResolveVisitor visitor, CSharpResolver storedContext, AstNode initializerExpression, bool isForEach) + { + this.visitor = visitor; + this.storedContext = storedContext; + this.initializerExpression = initializerExpression; + this.isForEach = isForEach; + } + + public IType Resolve(ITypeResolveContext context) + { + if (visitor == null) + return result ?? SharedTypes.UnknownType; + + visitor.ResetContext( + storedContext, + delegate { + result = visitor.Resolve(initializerExpression).Type; + + if (isForEach) { + result = GetElementType(result, storedContext.Context, false); + } + }); + visitor = null; + storedContext = null; + initializerExpression = null; + return result; + } + + public override string ToString() + { + if (visitor == null) + return "var=" + result; + else + return "var (not yet resolved)"; + } + } + + static IType GetElementType(IType result, ITypeResolveContext context, bool allowIEnumerator) + { + bool foundSimpleIEnumerable = false; + foreach (IType baseType in result.GetAllBaseTypes(context)) { + ITypeDefinition baseTypeDef = baseType.GetDefinition(); + if (baseTypeDef != null && ( + baseTypeDef.Name == "IEnumerable" || (allowIEnumerator && baseType.Name == "IEnumerator"))) + { + if (baseTypeDef.Namespace == "System.Collections.Generic" && baseTypeDef.TypeParameterCount == 1) { + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + return pt.GetTypeArgument(0); + } + } else if (baseTypeDef.Namespace == "System.Collections" && baseTypeDef.TypeParameterCount == 0) { + foundSimpleIEnumerable = true; + } + } + } + // System.Collections.IEnumerable found in type hierarchy -> Object is element type. + if (foundSimpleIEnumerable) + return KnownTypeReference.Object.Resolve(context); + return SharedTypes.UnknownType; + } + #endregion + + #region Attributes + ResolveResult IAstVisitor.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) { + // Resolve the ctor arguments and find the matching ctor overload + string[] argumentNames; + ResolveResult[] arguments = GetArguments(constructorArguments, out argumentNames); + ResolveResult rr = resolver.ResolveObjectCreation(type, arguments, argumentNames); + ProcessConversionsInInvocation(null, constructorArguments, rr as CSharpInvocationResolveResult); + return rr; + } else { + foreach (var node in constructorArguments) + Scan(node); + return null; + } + } + + ResolveResult IAstVisitor.VisitAttributeSection(AttributeSection attributeSection, object data) + { + ScanChildren(attributeSection); + return voidResult; + } + #endregion + + #region Using Declaration + ResolveResult IAstVisitor.VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) + { + currentTypeLookupMode = SimpleNameLookupMode.TypeInUsingDeclaration; + ScanChildren(usingDeclaration); + currentTypeLookupMode = SimpleNameLookupMode.Type; + return voidResult; + } + + ResolveResult IAstVisitor.VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) + { + currentTypeLookupMode = SimpleNameLookupMode.TypeInUsingDeclaration; + ScanChildren(usingDeclaration); + currentTypeLookupMode = SimpleNameLookupMode.Type; + return voidResult; + } + + ResolveResult IAstVisitor.VisitExternAliasDeclaration(ExternAliasDeclaration externAliasDeclaration, object data) + { + return voidResult; + } + #endregion + + #region Type References + ResolveResult IAstVisitor.VisitPrimitiveType(PrimitiveType primitiveType, object data) + { + if (!resolverEnabled) + return null; + IType type = MakeTypeReference(primitiveType).Resolve(resolver.Context); + if (type.Kind != TypeKind.Unknown) + return new TypeResolveResult(type); + else + return errorResult; + } + + ResolveResult HandleAttributeType(AstType astType) + { + ScanChildren(astType); + IType type = TypeSystemConvertVisitor.ConvertAttributeType(astType, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.CurrentUsingScope).Resolve(resolver.Context); + if (type.Kind != TypeKind.Unknown) + return new TypeResolveResult(type); + else + return errorResult; + } + + ResolveResult IAstVisitor.VisitSimpleType(SimpleType simpleType, object data) + { + if (!resolverEnabled) { + ScanChildren(simpleType); + return null; + } + if (simpleType.Parent is Attribute) { + return HandleAttributeType(simpleType); + } + + var typeArguments = GetTypeArguments(simpleType.TypeArguments); + return resolver.LookupSimpleNameOrTypeName(simpleType.Identifier, typeArguments, currentTypeLookupMode); + } + + ResolveResult IAstVisitor.VisitMemberType(MemberType memberType, object data) + { + if (!resolverEnabled) { + ScanChildren(memberType); + return null; + } + if (memberType.Parent is Attribute) { + return HandleAttributeType(memberType); + } + ResolveResult target; + if (memberType.IsDoubleColon && memberType.Target is SimpleType) { + SimpleType t = (SimpleType)memberType.Target; + target = resolver.ResolveAlias(t.Identifier); + StoreResult(t, target); + } else { + target = Resolve(memberType.Target); + } + + var typeArguments = GetTypeArguments(memberType.TypeArguments); + return resolver.ResolveMemberType(target, memberType.MemberName, typeArguments); + } + + ResolveResult IAstVisitor.VisitComposedType(ComposedType composedType, object data) + { + if (!resolverEnabled) { + ScanChildren(composedType); + return null; + } + IType t = ResolveType(composedType.BaseType); + if (composedType.HasNullableSpecifier) { + t = NullableType.Create(t, resolver.Context); + } + for (int i = 0; i < composedType.PointerRank; i++) { + t = new PointerType(t); + } + foreach (var a in composedType.ArraySpecifiers.Reverse()) { + t = new ArrayType(t, a.Dimensions); + } + return new TypeResolveResult(t); + } + #endregion + + #region Query Expressions + ResolveResult IAstVisitor.VisitQueryExpression(QueryExpression queryExpression, object data) + { + resolver.PushBlock(); + ResolveResult oldQueryResult = currentQueryResult; + try { + currentQueryResult = null; + foreach (var clause in queryExpression.Clauses) { + currentQueryResult = Resolve(clause); + } + return currentQueryResult; + } finally { + currentQueryResult = oldQueryResult; + resolver.PopBlock(); + } + } + + IType GetTypeForQueryVariable(IType type) + { + // This assumes queries are only used on IEnumerable. + // We might want to look at the signature of a LINQ method (e.g. Select) instead. + return GetElementType(type, resolver.Context, false); + } + + sealed class QueryExpressionLambda : LambdaResolveResult + { + readonly IParameter[] parameters; + readonly ResolveResult bodyExpression; + + internal IType[] inferredParameterTypes; + + public QueryExpressionLambda(int parameterCount, ResolveResult bodyExpression) + { + this.parameters = new IParameter[parameterCount]; + for (int i = 0; i < parameterCount; i++) { + parameters[i] = new DefaultParameter(SharedTypes.UnknownType, "x" + i); + } + this.bodyExpression = bodyExpression; + } + + public override IList Parameters { + get { return parameters; } + } + + public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions) + { + if (parameterTypes.Length == parameters.Length) { + this.inferredParameterTypes = parameterTypes; + return Conversion.AnonymousFunctionConversion(parameterTypes); + } else { + return Conversion.None; + } + } + + public override bool IsAsync { + get { return false; } + } + + public override bool IsImplicitlyTyped { + get { return true; } + } + + public override bool IsAnonymousMethod { + get { return false; } + } + + public override bool HasParameterList { + get { return true; } + } + + public override IType GetInferredReturnType(IType[] parameterTypes) + { + return bodyExpression.Type; + } + + public override string ToString() + { + return string.Format("[QueryExpressionLambda ({0}) => {1}]", string.Join(",", parameters.Select(p => p.Name)), bodyExpression); + } + } + + QueryClause GetPreviousQueryClause(QueryClause clause) + { + for (AstNode node = clause.PrevSibling; node != null; node = node.PrevSibling) { + if (node.Role == QueryExpression.ClauseRole) + return (QueryClause)node; + } + return null; + } + + QueryClause GetNextQueryClause(QueryClause clause) + { + for (AstNode node = clause.NextSibling; node != null; node = node.NextSibling) { + if (node.Role == QueryExpression.ClauseRole) + return (QueryClause)node; + } + return null; + } + + ResolveResult IAstVisitor.VisitQueryFromClause(QueryFromClause queryFromClause, object data) + { + ResolveResult result = null; + ResolveResult expr = Resolve(queryFromClause.Expression); + IType variableType; + if (queryFromClause.Type.IsNull) { + variableType = GetTypeForQueryVariable(expr.Type); + result = expr; + } else { + variableType = ResolveType(queryFromClause.Type); + if (resolverEnabled) { + // resolve the .Cast<>() call + ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { variableType }, true); + result = resolver.ResolveInvocation(methodGroup, new ResolveResult[0]); + } + } + + DomRegion region = MakeRegion(queryFromClause.IdentifierToken); + IVariable v = resolver.AddVariable(variableType, region, queryFromClause.Identifier); + StoreResult(queryFromClause.IdentifierToken, new LocalResolveResult(v, variableType)); + + if (resolverEnabled && currentQueryResult != null) { + // this is a second 'from': resolve the .SelectMany() call + QuerySelectClause selectClause = GetNextQueryClause(queryFromClause) as QuerySelectClause; + ResolveResult selectResult; + if (selectClause != null) { + // from ... from ... select - the SelectMany call also performs the Select operation + selectResult = Resolve(selectClause.Expression); + } else { + // from .. from ... ... - introduce a transparent identifier + selectResult = transparentIdentifierResolveResult; + } + ResolveResult methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "SelectMany", EmptyList.Instance, true); + ResolveResult[] arguments = { + new QueryExpressionLambda(1, result), + new QueryExpressionLambda(2, selectResult) + }; + result = resolver.ResolveInvocation(methodGroup, arguments); + } + return result; + } + + ResolveResult IAstVisitor.VisitQueryContinuationClause(QueryContinuationClause queryContinuationClause, object data) + { + ResolveResult rr = Resolve(queryContinuationClause.PrecedingQuery); + IType variableType = GetTypeForQueryVariable(rr.Type); + DomRegion region = MakeRegion(queryContinuationClause.IdentifierToken); + IVariable v = resolver.AddVariable(variableType, region, queryContinuationClause.Identifier); + StoreResult(queryContinuationClause.IdentifierToken, new LocalResolveResult(v, variableType)); + return rr; + } + + ResolveResult IAstVisitor.VisitQueryLetClause(QueryLetClause queryLetClause, object data) + { + ResolveResult expr = Resolve(queryLetClause.Expression); + DomRegion region = MakeRegion(queryLetClause.IdentifierToken); + IVariable v = resolver.AddVariable(expr.Type, region, queryLetClause.Identifier); + StoreResult(queryLetClause.IdentifierToken, new LocalResolveResult(v, expr.Type)); + if (resolverEnabled && currentQueryResult != null) { + // resolve the .Select() call + ResolveResult methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Select", EmptyList.Instance, true); + ResolveResult[] arguments = { new QueryExpressionLambda(1, transparentIdentifierResolveResult) }; + return resolver.ResolveInvocation(methodGroup, arguments); + } else { + return null; + } + } + + ResolveResult IAstVisitor.VisitQueryJoinClause(QueryJoinClause queryJoinClause, object data) + { + // join v in expr on onExpr equals equalsExpr [into g] + ResolveResult inResult = null; + ResolveResult expr = Resolve(queryJoinClause.InExpression); + IType variableType; + if (queryJoinClause.Type.IsNull) { + variableType = GetTypeForQueryVariable(expr.Type); + inResult = expr; + } else { + variableType = ResolveType(queryJoinClause.Type); + if (resolverEnabled) { + // resolve the .Cast<>() call + ResolveResult methodGroup = resolver.ResolveMemberAccess(expr, "Cast", new[] { variableType }, true); + inResult = resolver.ResolveInvocation(methodGroup, new ResolveResult[0]); + } + } + + // resolve the 'On' expression in a context that contains only the previously existing range variables: + // (before adding any variable) + ResolveResult onResult = Resolve(queryJoinClause.OnExpression); + + // scan the 'Equals' expression in a context that contains only the variable 'v' + CSharpResolver resolverOutsideQuery = resolver.Clone(); + resolverOutsideQuery.PopBlock(); // pop all variables from the current query expression + DomRegion joinIdentifierRegion = MakeRegion(queryJoinClause.JoinIdentifierToken); + IVariable v = resolverOutsideQuery.AddVariable(variableType, joinIdentifierRegion, queryJoinClause.JoinIdentifier); + ResolveResult equalsResult = errorResult; + ResetContext(resolverOutsideQuery, delegate { + equalsResult = Resolve(queryJoinClause.EqualsExpression); + }); + StoreResult(queryJoinClause.JoinIdentifierToken, new LocalResolveResult(v, variableType)); + + if (queryJoinClause.IsGroupJoin) { + return ResolveGroupJoin(queryJoinClause, inResult, onResult, equalsResult); + } else { + resolver.AddVariable(variableType, joinIdentifierRegion, queryJoinClause.JoinIdentifier); + if (resolverEnabled && currentQueryResult != null) { + QuerySelectClause selectClause = GetNextQueryClause(queryJoinClause) as QuerySelectClause; + ResolveResult selectResult; + if (selectClause != null) { + // from ... join ... select - the Join call also performs the Select operation + selectResult = Resolve(selectClause.Expression); + } else { + // from .. join ... ... - introduce a transparent identifier + selectResult = transparentIdentifierResolveResult; + } + + var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Join", EmptyList.Instance); + ResolveResult[] arguments = { + inResult, + new QueryExpressionLambda(1, onResult), + new QueryExpressionLambda(1, equalsResult), + new QueryExpressionLambda(2, selectResult) + }; + return resolver.ResolveInvocation(methodGroup, arguments); + } else { + return null; + } + } + } + + ResolveResult ResolveGroupJoin(QueryJoinClause queryJoinClause, + ResolveResult inResult, ResolveResult onResult, ResolveResult equalsResult) + { + Debug.Assert(queryJoinClause.IsGroupJoin); + + DomRegion intoIdentifierRegion = MakeRegion(queryJoinClause.IntoIdentifierToken); + + // We need to declare the group variable, but it's a bit tricky to determine its type: + // We'll have to resolve the GroupJoin invocation and take a look at the inferred types + // for the lambda given as last parameter. + var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "GroupJoin", EmptyList.Instance); + QuerySelectClause selectClause = GetNextQueryClause(queryJoinClause) as QuerySelectClause; + LambdaResolveResult groupJoinLambda; + if (selectClause != null) { + // from ... join ... into g select - the GroupJoin call also performs the Select operation + IParameter[] selectLambdaParameters = { + new DefaultParameter(SharedTypes.UnknownType, "<>transparentIdentifier"), + new DefaultParameter(SharedTypes.UnknownType, queryJoinClause.IntoIdentifier) { + Region = intoIdentifierRegion + } + }; + groupJoinLambda = new ImplicitlyTypedLambda(selectClause, selectLambdaParameters, this); + } else { + // from .. join ... ... - introduce a transparent identifier + groupJoinLambda = new QueryExpressionLambda(2, transparentIdentifierResolveResult); + } + + ResolveResult[] arguments = { + inResult, + new QueryExpressionLambda(1, onResult), + new QueryExpressionLambda(1, equalsResult), + groupJoinLambda + }; + ResolveResult rr = resolver.ResolveInvocation(methodGroup, arguments); + InvocationResolveResult invocationRR = rr as InvocationResolveResult; + + IVariable groupVariable; + if (groupJoinLambda is ImplicitlyTypedLambda) { + var implicitlyTypedLambda = (ImplicitlyTypedLambda)groupJoinLambda; + + if (invocationRR != null && invocationRR.Arguments.Count > 0) { + ConversionResolveResult crr = invocationRR.Arguments[invocationRR.Arguments.Count - 1] as ConversionResolveResult; + if (crr != null) + ProcessConversion(null, crr.Input, crr.Conversion, crr.Type); + } + + implicitlyTypedLambda.EnforceMerge(this); + if (implicitlyTypedLambda.winningHypothesis.parameterTypes.Length == 2) + groupVariable = implicitlyTypedLambda.winningHypothesis.lambdaParameters[1]; + else + groupVariable = null; + } else { + Debug.Assert(groupJoinLambda is QueryExpressionLambda); + + // Add the variable if the query expression continues after the group join + // (there's no need to do this if there's only a select clause remaining, as + // we already handled that in the ImplicitlyTypedLambda). + + // Get the inferred type of the group variable: + IType[] inferredParameterTypes = null; + if (invocationRR != null && invocationRR.Arguments.Count > 0) { + ConversionResolveResult crr = invocationRR.Arguments[invocationRR.Arguments.Count - 1] as ConversionResolveResult; + if (crr != null && crr.Conversion.IsAnonymousFunctionConversion) { + inferredParameterTypes = crr.Conversion.data as IType[]; + } + } + if (inferredParameterTypes == null) + inferredParameterTypes = ((QueryExpressionLambda)groupJoinLambda).inferredParameterTypes; + + IType groupParameterType; + if (inferredParameterTypes != null && inferredParameterTypes.Length == 2) + groupParameterType = inferredParameterTypes[1]; + else + groupParameterType = SharedTypes.UnknownType; + + groupVariable = resolver.AddVariable(groupParameterType, intoIdentifierRegion, queryJoinClause.IntoIdentifier); + } + + if (groupVariable != null) { + LocalResolveResult lrr = new LocalResolveResult(groupVariable, groupVariable.Type.Resolve(resolver.Context)); + StoreResult(queryJoinClause.IntoIdentifierToken, lrr); + } + + return rr; + } + + ResolveResult IAstVisitor.VisitQueryWhereClause(QueryWhereClause queryWhereClause, object data) + { + ResolveResult condition = Resolve(queryWhereClause.Condition); + IType boolType = KnownTypeReference.Boolean.Resolve(resolver.Context); + Conversion conversionToBool = resolver.conversions.ImplicitConversion(condition, boolType); + ProcessConversion(queryWhereClause.Condition, condition, conversionToBool, boolType); + if (resolverEnabled && currentQueryResult != null) { + if (conversionToBool != Conversion.IdentityConversion && conversionToBool != Conversion.None) { + condition = new ConversionResolveResult(boolType, condition, conversionToBool); + } + + var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Where", EmptyList.Instance); + ResolveResult[] arguments = { new QueryExpressionLambda(1, condition) }; + return resolver.ResolveInvocation(methodGroup, arguments); + } else { + return null; + } + } + + ResolveResult IAstVisitor.VisitQuerySelectClause(QuerySelectClause querySelectClause, object data) + { + if (resolverEnabled && currentQueryResult != null) { + QueryClause previousQueryClause = GetPreviousQueryClause(querySelectClause); + // If the 'select' follows on a 'SelectMany', 'Join' or 'GroupJoin' clause, then the 'select' portion + // was already done as part of the previous clause. + if (((previousQueryClause is QueryFromClause && GetPreviousQueryClause(previousQueryClause) != null)) + || previousQueryClause is QueryJoinClause) + { + Scan(querySelectClause.Expression); + return currentQueryResult; + } + + QueryExpression query = querySelectClause.Parent as QueryExpression; + string rangeVariable = GetSingleRangeVariable(query); + if (rangeVariable != null) { + IdentifierExpression ident = UnpackParenthesizedExpression(querySelectClause.Expression) as IdentifierExpression; + if (ident != null && ident.Identifier == rangeVariable && !ident.TypeArguments.Any()) { + // selecting the single identifier that is the range variable + if (query.Clauses.Count > 2) { + // only if the query is not degenerate: + // the Select call will be optimized away, so directly return the previous result + Scan(querySelectClause.Expression); + return currentQueryResult; + } + } + } + + ResolveResult expr = Resolve(querySelectClause.Expression); + var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "Select", EmptyList.Instance); + ResolveResult[] arguments = { new QueryExpressionLambda(1, expr) }; + return resolver.ResolveInvocation(methodGroup, arguments); + } else { + Scan(querySelectClause.Expression); + return null; + } + } + + /// + /// Gets the name of the range variable in the specified query. + /// If the query has multiple range variables, this method returns null. + /// + string GetSingleRangeVariable(QueryExpression query) + { + if (query == null) + return null; + foreach (QueryClause clause in query.Clauses.Skip(1)) { + if (clause is QueryFromClause || clause is QueryJoinClause || clause is QueryLetClause) { + // query has more than 1 range variable + return null; + } + } + QueryFromClause fromClause = query.Clauses.FirstOrDefault() as QueryFromClause; + if (fromClause != null) + return fromClause.Identifier; + QueryContinuationClause continuationClause = query.Clauses.FirstOrDefault() as QueryContinuationClause; + if (continuationClause != null) + return continuationClause.Identifier; + return null; + } + + ResolveResult IAstVisitor.VisitQueryGroupClause(QueryGroupClause queryGroupClause, object data) + { + if (resolverEnabled && currentQueryResult != null) { + // ... group projection by key + ResolveResult projection = Resolve(queryGroupClause.Projection); + ResolveResult key = Resolve(queryGroupClause.Key); + + var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, "GroupBy", EmptyList.Instance); + ResolveResult[] arguments = { + new QueryExpressionLambda(1, key), + new QueryExpressionLambda(1, projection) + }; + return resolver.ResolveInvocation(methodGroup, arguments); + } else { + ScanChildren(queryGroupClause); + return null; + } + } + + ResolveResult IAstVisitor.VisitQueryOrderClause(QueryOrderClause queryOrderClause, object data) + { + if (resolverEnabled) { + foreach (QueryOrdering ordering in queryOrderClause.Orderings) { + currentQueryResult = Resolve(ordering); + } + return currentQueryResult; + } else { + ScanChildren(queryOrderClause); + return null; + } + } + + ResolveResult IAstVisitor.VisitQueryOrdering(QueryOrdering queryOrdering, object data) + { + if (resolverEnabled && currentQueryResult != null) { + // ... orderby sortKey [descending] + ResolveResult sortKey = Resolve(queryOrdering.Expression); + + QueryOrderClause parentClause = queryOrdering.Parent as QueryOrderClause; + bool isFirst = (parentClause == null || parentClause.Orderings.FirstOrDefault() == queryOrdering); + string methodName = isFirst ? "OrderBy" : "ThenBy"; + if (queryOrdering.Direction == QueryOrderingDirection.Descending) + methodName += "Descending"; + + var methodGroup = resolver.ResolveMemberAccess(currentQueryResult, methodName, EmptyList.Instance); + ResolveResult[] arguments = { + new QueryExpressionLambda(1, sortKey), + }; + return resolver.ResolveInvocation(methodGroup, arguments); + } else { + Scan(queryOrdering.Expression); + return null; + } + } + #endregion + + #region Constructor Initializer + ResolveResult IAstVisitor.VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) + { + if (!resolverEnabled) { + ScanChildren(constructorInitializer); + return null; + } + ResolveResult target; + if (constructorInitializer.ConstructorInitializerType == ConstructorInitializerType.Base) { + target = resolver.ResolveBaseReference(); + } else { + target = resolver.ResolveThisReference(); + } + string[] argumentNames; + ResolveResult[] arguments = GetArguments(constructorInitializer.Arguments, out argumentNames); + ResolveResult rr = resolver.ResolveObjectCreation(target.Type, arguments, argumentNames); + ProcessConversionsInInvocation(null, constructorInitializer.Arguments, rr as CSharpInvocationResolveResult); + return rr; + } + #endregion + + #region Other Nodes + // Token nodes + ResolveResult IAstVisitor.VisitIdentifier(Identifier identifier, object data) + { + return null; + } + + ResolveResult IAstVisitor.VisitComment(Comment comment, object data) + { + return null; + } + + ResolveResult IAstVisitor.VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, object data) + { + return null; + } + + ResolveResult IAstVisitor.VisitArraySpecifier(ArraySpecifier arraySpecifier, object data) + { + return null; + } + + ResolveResult IAstVisitor.VisitPatternPlaceholder(AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern, object data) + { + return null; + } + + // Nodes where we just need to visit the children: + ResolveResult IAstVisitor.VisitAccessor(Accessor accessor, object data) + { + ScanChildren(accessor); + return voidResult; + } + + ResolveResult IAstVisitor.VisitSwitchSection(SwitchSection switchSection, object data) + { + ScanChildren(switchSection); + return voidResult; + } + + ResolveResult IAstVisitor.VisitCaseLabel(CaseLabel caseLabel, object data) + { + ScanChildren(caseLabel); + return voidResult; + } + + ResolveResult IAstVisitor.VisitConstraint(Constraint constraint, object data) + { + ScanChildren(constraint); + return voidResult; + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/SimpleNameLookupMode.cs b/ICSharpCode.NRefactory.CSharp/Resolver/SimpleNameLookupMode.cs new file mode 100644 index 000000000..a58a90bf5 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/SimpleNameLookupMode.cs @@ -0,0 +1,47 @@ +// 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; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + public enum SimpleNameLookupMode + { + /// + /// Normal name lookup in expressions + /// + Expression, + /// + /// Name lookup in expression, where the expression is the target of an invocation. + /// Such a lookup will only return methods and delegate-typed fields. + /// + InvocationTarget, + /// + /// Normal name lookup in type references. + /// + Type, + /// + /// Name lookup in the type reference inside a using declaration. + /// + TypeInUsingDeclaration, + /// + /// Name lookup for base type references. + /// + BaseTypeReference + } +} diff --git a/ICSharpCode.NRefactory.CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory.CSharp/Resolver/SimpleTypeOrNamespaceReference.cs new file mode 100644 index 000000000..4a0bddf10 --- /dev/null +++ b/ICSharpCode.NRefactory.CSharp/Resolver/SimpleTypeOrNamespaceReference.cs @@ -0,0 +1,142 @@ +// 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.Collections.Generic; +using System.Collections.ObjectModel; + +using ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +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, ISupportsInterning + { + readonly ITypeDefinition parentTypeDefinition; + readonly UsingScope parentUsingScope; + string identifier; + IList typeArguments; + readonly SimpleNameLookupMode lookupMode; + + public SimpleTypeOrNamespaceReference(string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope, SimpleNameLookupMode lookupMode = SimpleNameLookupMode.Type) + { + if (identifier == null) + throw new ArgumentNullException("identifier"); + this.identifier = identifier; + this.typeArguments = typeArguments ?? EmptyList.Instance; + this.parentTypeDefinition = parentTypeDefinition; + this.parentUsingScope = parentUsingScope; + this.lookupMode = lookupMode; + } + + public string Identifier { + get { return identifier; } + } + + public IList TypeArguments { + get { return new ReadOnlyCollection(typeArguments); } + } + + /// + /// Adds a suffix to the identifier. + /// Does not modify the existing type reference, but returns a new one. + /// + public SimpleTypeOrNamespaceReference AddSuffix(string suffix) + { + return new SimpleTypeOrNamespaceReference(identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope, lookupMode); + } + + public ResolveResult DoResolve(ITypeResolveContext context) + { + CacheManager cacheManager = context.CacheManager; + if (cacheManager != null) { + ResolveResult cachedResult = cacheManager.GetShared(this) as ResolveResult; + if (cachedResult != null) + return cachedResult; + } + + CSharpResolver r = new CSharpResolver(context); + r.CurrentTypeDefinition = parentTypeDefinition; + r.CurrentUsingScope = parentUsingScope; + IType[] typeArgs = new IType[typeArguments.Count]; + for (int i = 0; i < typeArgs.Length; i++) { + typeArgs[i] = typeArguments[i].Resolve(context); + } + ResolveResult rr = r.LookupSimpleNameOrTypeName(identifier, typeArgs, lookupMode); + if (cacheManager != null) + cacheManager.SetShared(this, rr); + return rr; + } + + public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible + return DoResolve(context) as NamespaceResolveResult; + } + + public IType Resolve(ITypeResolveContext context) + { + // TODO: use resolve context for original project, if possible; then map the result type into the new context + TypeResolveResult rr = DoResolve(context) as TypeResolveResult; + return rr != null ? rr.Type : SharedTypes.UnknownType; + } + + public override string ToString() + { + if (typeArguments.Count == 0) + return identifier; + else + return identifier + "<" + string.Join(",", typeArguments) + ">"; + } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + identifier = provider.Intern(identifier); + typeArguments = provider.InternList(typeArguments); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + int hashCode = 0; + unchecked { + if (parentTypeDefinition != null) + hashCode += 1000000007 * parentTypeDefinition.GetHashCode(); + if (parentUsingScope != null) + hashCode += 1000000009 * parentUsingScope.GetHashCode(); + + hashCode += 1000000021 * identifier.GetHashCode(); + hashCode += 1000000033 * typeArguments.GetHashCode(); + hashCode += 1000000087 * (int)lookupMode; + } + return hashCode; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + SimpleTypeOrNamespaceReference o = other as SimpleTypeOrNamespaceReference; + return o != null && this.parentTypeDefinition == o.parentTypeDefinition + && this.parentUsingScope == o.parentUsingScope && this.identifier == o.identifier + && this.typeArguments == o.typeArguments && this.lookupMode == o.lookupMode; + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs b/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs similarity index 72% rename from ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs index e3c75632e..66558056a 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/TypeInference.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/TypeInference.cs @@ -1,10 +1,27 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Diagnostics; using System.Linq; + +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -46,7 +63,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (context == null) throw new ArgumentNullException("context"); this.context = context; - this.conversions = conversions ?? new Conversions(context); + this.conversions = conversions ?? Conversions.Get(context); } #endregion @@ -72,9 +89,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType[] parameterTypes; ResolveResult[] arguments; bool[,] dependencyMatrix; + IList classTypeArguments; #region InferTypeArguments (main function) - public IType[] InferTypeArguments(IList typeParameters, IList arguments, IList parameterTypes, out bool success) + /// + /// Performs type inference. + /// + /// The method type parameters that should be inferred. + /// The arguments passed to the method. + /// The parameter types of the method. + /// Out: whether type inference was successful + /// + /// Class type arguments. These are substituted for class type parameters in the formal parameter types + /// when inferring a method group or lambda. + /// + /// The inferred type arguments. + public IType[] InferTypeArguments(IList typeParameters, IList arguments, IList parameterTypes, out bool success, IList classTypeArguments = null) { if (typeParameters == null) throw new ArgumentNullException("typeParameters"); @@ -87,6 +117,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver for (int i = 0; i < this.typeParameters.Length; i++) { if (i != typeParameters[i].Index) throw new ArgumentException("Type parameter has wrong index"); + if (typeParameters[i].OwnerType != EntityType.Method) + throw new ArgumentException("Type parameter must be owned by a method"); this.typeParameters[i] = new TP(typeParameters[i]); } this.parameterTypes = new IType[Math.Min(arguments.Count, parameterTypes.Count)]; @@ -97,8 +129,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.arguments[i] = arguments[i]; this.parameterTypes[i] = parameterTypes[i]; } + this.classTypeArguments = classTypeArguments; + Log.WriteLine("Type Inference"); + Log.WriteLine(" Signature: M<" + string.Join(", ", this.typeParameters) + ">" + + "(" + string.Join(", ", this.parameterTypes) + ")"); + Log.WriteCollection(" Arguments: ", arguments); + Log.Indent(); + PhaseOne(); success = PhaseTwo(); + + Log.Unindent(); + Log.WriteLine(" Type inference finished " + (success ? "successfully" : "with errors") + ": " + + "M<" + string.Join(", ", this.typeParameters.Select(tp => tp.FixedTo ?? SharedTypes.UnknownType)) + ">"); return this.typeParameters.Select(tp => tp.FixedTo ?? SharedTypes.UnknownType).ToArray(); } finally { Reset(); @@ -112,6 +155,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver this.parameterTypes = null; this.arguments = null; this.dependencyMatrix = null; + this.classTypeArguments = null; } /// @@ -203,11 +247,22 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver void PhaseOne() { // C# 4.0 spec: §7.5.2.1 The first phase - Log("Phase One"); + Log.WriteLine("Phase One"); for (int i = 0; i < arguments.Length; i++) { ResolveResult Ei = arguments[i]; IType Ti = parameterTypes[i]; - // TODO: what if Ei is an anonymous function? + + LambdaResolveResult lrr = Ei as LambdaResolveResult; + if (lrr != null) { + MakeExplicitParameterTypeInference(lrr, Ti); + } + if (lrr != null || Ei is MethodGroupResolveResult) { + // this is not in the spec??? + if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) { + MakeOutputTypeInference(Ei, Ti); + } + } + IType U = Ei.Type; if (U != SharedTypes.UnknownType) { if (Ti is ByReferenceType) { @@ -222,18 +277,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool PhaseTwo() { // C# 4.0 spec: §7.5.2.2 The second phase - Log("Phase Two"); + Log.WriteLine("Phase Two"); // All unfixed type variables Xi which do not depend on any Xj are fixed. List typeParametersToFix = new List(); foreach (TP Xi in typeParameters) { if (Xi.IsFixed == false) { - if (!typeParameters.Any((TP Xj) => DependsOn(Xi, Xj))) { + if (!typeParameters.Any((TP Xj) => !Xj.IsFixed && DependsOn(Xi, Xj))) { typeParametersToFix.Add(Xi); } } } // If no such type variables exist, all unfixed type variables Xi are fixed for which all of the following hold: if (typeParametersToFix.Count == 0) { + Log.WriteLine("Type parameters cannot be fixed due to dependency cycles"); + Log.WriteLine("Trying to break the cycle by fixing any TPs that have non-empty bounds..."); foreach (TP Xi in typeParameters) { // Xi has a non­empty set of bounds if (!Xi.IsFixed && Xi.HasBounds) { @@ -255,6 +312,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver bool unfixedTypeVariablesExist = typeParameters.Any((TP X) => X.IsFixed == false); if (typeParametersToFix.Count == 0 && unfixedTypeVariablesExist) { // If no such type variables exist and there are still unfixed type variables, type inference fails. + Log.WriteLine("Type inference fails: there are still unfixed TPs remaining"); return false; } else if (!unfixedTypeVariablesExist) { // Otherwise, if no further unfixed type variables exist, type inference succeeds. @@ -268,7 +326,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // but the input types (§7.4.2.3) do not if (OutputTypeContainsUnfixed(Ei, Ti) && !InputTypesContainsUnfixed(Ei, Ti)) { // an output type inference (§7.4.2.6) is made for ei with type Ti. - Log("MakeOutputTypeInference for #" + i); + Log.WriteLine("MakeOutputTypeInference for argument #" + i); MakeOutputTypeInference(Ei, Ti); } } @@ -284,33 +342,44 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver IType[] InputTypes(ResolveResult e, IType t) { // C# 4.0 spec: §7.5.2.3 Input types - /* TODO - AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; - if (amrt != null && amrt.HasImplicitlyTypedParameters || e is MethodGroupReturnType) { - IMethod m = GetDelegateOrExpressionTreeSignature(t, amrt != null && amrt.CanBeConvertedToExpressionTree); + LambdaResolveResult lrr = e as LambdaResolveResult; + if (lrr != null && lrr.IsImplicitlyTyped || e is MethodGroupResolveResult) { + IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { - return m.Parameters.Select(p => p.ReturnType); + IType[] inputTypes = new IType[m.Parameters.Count]; + for (int i = 0; i < inputTypes.Length; i++) { + inputTypes[i] = m.Parameters[i].Type.Resolve(context); + } + return inputTypes; } - }*/ + } return emptyTypeArray; } - IType[] OutputTypes(ResolveResult e, IType t) { - // C# 4.0 spec: §7.5.2.4 Input types - /* - AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; - if (amrt != null || e is MethodGroupReturnType) { - IMethod m = GetDelegateOrExpressionTreeSignature(T, amrt != null && amrt.CanBeConvertedToExpressionTree); + // C# 4.0 spec: §7.5.2.4 Output types + LambdaResolveResult lrr = e as LambdaResolveResult; + if (lrr != null && lrr.IsImplicitlyTyped || e is MethodGroupResolveResult) { + IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { - return new[] { m.ReturnType }; + return new[] { m.ReturnType.Resolve(context) }; } } - */ return emptyTypeArray; } + static IMethod GetDelegateOrExpressionTreeSignature(IType t) + { + ParameterizedType pt = t as ParameterizedType; + if (pt != null && pt.TypeParameterCount == 1 && pt.Name == "Expression" + && pt.Namespace == "System.Linq.Expressions") + { + t = pt.GetTypeArgument(0); + } + return t.GetDelegateInvokeMethod(); + } + bool InputTypesContainsUnfixed(ResolveResult argument, IType parameterType) { return AnyTypeContainsUnfixedParameter(InputTypes(argument, parameterType)); @@ -382,53 +451,91 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #region MakeOutputTypeInference (§7.5.2.6) void MakeOutputTypeInference(ResolveResult e, IType t) { + Log.WriteLine(" MakeOutputTypeInference from " + e + " to " + t); // If E is an anonymous function with inferred return type U (§7.5.2.12) and T is a delegate type or expression // tree type with return type Tb, then a lower-bound inference (§7.5.2.9) is made from U to Tb. - /* TODO AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; - if (amrt != null) { - IMethod m = GetDelegateOrExpressionTreeSignature(T, amrt.CanBeConvertedToExpressionTree); + LambdaResolveResult lrr = e as LambdaResolveResult; + if (lrr != null) { + IMethod m = GetDelegateOrExpressionTreeSignature(t); if (m != null) { - IReturnType inferredReturnType; - if (amrt.HasParameterList && amrt.MethodParameters.Count == m.Parameters.Count) { - var inferredParameterTypes = m.Parameters.Select(p => SubstituteFixedTypes(p.ReturnType)).ToArray(); - inferredReturnType = amrt.ResolveReturnType(inferredParameterTypes); + IType inferredReturnType; + if (lrr.IsImplicitlyTyped) { + if (m.Parameters.Count != lrr.Parameters.Count) + return; // cannot infer due to mismatched parameter lists + TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); + IType[] inferredParameterTypes = new IType[m.Parameters.Count]; + for (int i = 0; i < inferredParameterTypes.Length; i++) { + IType parameterType = m.Parameters[i].Type.Resolve(context); + inferredParameterTypes[i] = parameterType.AcceptVisitor(substitution); + } + inferredReturnType = lrr.GetInferredReturnType(inferredParameterTypes); } else { - inferredReturnType = amrt.ResolveReturnType(); + inferredReturnType = lrr.GetInferredReturnType(null); } - - MakeLowerBoundInference(inferredReturnType, m.ReturnType); + MakeLowerBoundInference(inferredReturnType, m.ReturnType.Resolve(context)); return; } - }*/ + } // Otherwise, if E is a method group and T is a delegate type or expression tree type // with parameter types T1…Tk and return type Tb, and overload resolution // of E with the types T1…Tk yields a single method with return type U, then a lower­-bound // inference is made from U to Tb. MethodGroupResolveResult mgrr = e as MethodGroupResolveResult; if (mgrr != null) { - throw new NotImplementedException(); + IMethod m = GetDelegateOrExpressionTreeSignature(t); + if (m != null) { + ResolveResult[] args = new ResolveResult[m.Parameters.Count]; + TypeParameterSubstitution substitution = GetSubstitutionForFixedTPs(); + for (int i = 0; i < args.Length; i++) { + IParameter param = m.Parameters[i]; + IType parameterType = param.Type.Resolve(context); + parameterType = parameterType.AcceptVisitor(substitution); + if ((param.IsRef || param.IsOut) && parameterType.Kind == TypeKind.ByReference) { + parameterType = ((ByReferenceType)parameterType).ElementType; + args[i] = new ByReferenceResolveResult(parameterType, param.IsOut); + } else { + args[i] = new ResolveResult(parameterType); + } + } + var or = mgrr.PerformOverloadResolution(context, args, + allowExtensionMethods: false, + allowExpandingParams: false); + if (or.FoundApplicableCandidate && or.BestCandidateAmbiguousWith == null) { + IType returnType = or.BestCandidate.ReturnType.Resolve(context); + MakeLowerBoundInference(returnType, m.ReturnType.Resolve(context)); + } + } + return; } // Otherwise, if E is an expression with type U, then a lower-bound inference is made from U to T. if (e.Type != SharedTypes.UnknownType) { MakeLowerBoundInference(e.Type, t); } } + + TypeParameterSubstitution GetSubstitutionForFixedTPs() + { + IType[] fixedTypes = new IType[typeParameters.Length]; + for (int i = 0; i < fixedTypes.Length; i++) { + fixedTypes[i] = typeParameters[i].FixedTo ?? SharedTypes.UnknownType; + } + return new TypeParameterSubstitution(classTypeArguments, fixedTypes); + } #endregion #region MakeExplicitParameterTypeInference (§7.5.2.7) - void MakeExplicitParameterTypeInference(ResolveResult e, IType t) + void MakeExplicitParameterTypeInference(LambdaResolveResult e, IType t) { // C# 4.0 spec: §7.5.2.7 Explicit parameter type inferences - throw new NotImplementedException(); - /*AnonymousMethodReturnType amrt = e as AnonymousMethodReturnType; - if (amrt != null && amrt.HasParameterList) { - IMethod m = GetDelegateOrExpressionTreeSignature(T, amrt.CanBeConvertedToExpressionTree); - if (m != null && amrt.MethodParameters.Count == m.Parameters.Count) { - for (int i = 0; i < amrt.MethodParameters.Count; i++) { - MakeExactInference(amrt.MethodParameters[i].ReturnType, m.Parameters[i].ReturnType); - } - } - }*/ + if (e.IsImplicitlyTyped || !e.HasParameterList) + return; + Log.WriteLine(" MakeExplicitParameterTypeInference from " + e + " to " + t); + IMethod m = GetDelegateOrExpressionTreeSignature(t); + if (m == null) + return; + for (int i = 0; i < e.Parameters.Count && i < m.Parameters.Count; i++) { + MakeExactInference(e.Parameters[i].Type.Resolve(context), m.Parameters[i].Type.Resolve(context)); + } } #endregion @@ -439,12 +546,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// void MakeExactInference(IType U, IType V) { - Log("MakeExactInference from " + U + " to " + V); + Log.WriteLine("MakeExactInference from " + U + " to " + V); // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. TP tp = GetTPForType(V); if (tp != null && tp.IsFixed == false) { - Log(" Add exact bound '" + U + "' to " + tp); + Log.WriteLine(" Add exact bound '" + U + "' to " + tp); tp.LowerBounds.Add(U); tp.UpperBounds.Add(U); return; @@ -470,11 +577,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver && object.Equals(pU.GetDefinition(), pV.GetDefinition()) && pU.TypeParameterCount == pV.TypeParameterCount) { - Debug.Indent(); + Log.Indent(); for (int i = 0; i < pU.TypeParameterCount; i++) { - MakeExactInference(pU.TypeArguments[i], pV.TypeArguments[i]); + MakeExactInference(pU.GetTypeArgument(i), pV.GetTypeArgument(i)); } - Debug.Unindent(); + Log.Unindent(); } } @@ -497,12 +604,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// void MakeLowerBoundInference(IType U, IType V) { - Log(" MakeLowerBoundInference from " + U + " to " + V); + Log.WriteLine(" MakeLowerBoundInference from " + U + " to " + V); // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. TP tp = GetTPForType(V); if (tp != null && tp.IsFixed == false) { - Log(" Add lower bound '" + U + "' to " + tp); + Log.WriteLine(" Add lower bound '" + U + "' to " + tp); tp.LowerBounds.Add(U); return; } @@ -515,7 +622,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver MakeLowerBoundInference(arrU.ElementType, arrV.ElementType); return; } else if (arrU != null && IsIEnumerableCollectionOrList(pV) && arrU.Dimensions == 1) { - MakeLowerBoundInference(arrU.ElementType, pV.TypeArguments[0]); + MakeLowerBoundInference(arrU.ElementType, pV.GetTypeArgument(0)); return; } // Handle parameterized types: @@ -530,11 +637,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return; // cannot make an inference because it's not unique } } - Debug.Indent(); + Log.Indent(); if (uniqueBaseType != null) { for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { - IType Ui = uniqueBaseType.TypeArguments[i]; - IType Vi = pV.TypeArguments[i]; + IType Ui = uniqueBaseType.GetTypeArgument(i); + IType Vi = pV.GetTypeArgument(i); if (Ui.IsReferenceType(context) == true) { // look for variance ITypeParameter Xi = pV.GetDefinition().TypeParameters[i]; @@ -555,7 +662,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } } - Debug.Unindent(); + Log.Unindent(); } } @@ -581,12 +688,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// void MakeUpperBoundInference(IType U, IType V) { - Log(" MakeUpperBoundInference from " + U + " to " + V); + Log.WriteLine(" MakeUpperBoundInference from " + U + " to " + V); // If V is one of the unfixed Xi then U is added to the set of bounds for Xi. TP tp = GetTPForType(V); if (tp != null && tp.IsFixed == false) { - Log(" Add upper bound '" + U + "' to " + tp); + Log.WriteLine(" Add upper bound '" + U + "' to " + tp); tp.UpperBounds.Add(U); return; } @@ -599,7 +706,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver MakeUpperBoundInference(arrU.ElementType, arrV.ElementType); return; } else if (arrV != null && IsIEnumerableCollectionOrList(pU) && arrV.Dimensions == 1) { - MakeUpperBoundInference(pU.TypeArguments[0], arrV.ElementType); + MakeUpperBoundInference(pU.GetTypeArgument(0), arrV.ElementType); return; } // Handle parameterized types: @@ -614,11 +721,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return; // cannot make an inference because it's not unique } } - Debug.Indent(); + Log.Indent(); if (uniqueBaseType != null) { for (int i = 0; i < uniqueBaseType.TypeParameterCount; i++) { - IType Ui = pU.TypeArguments[i]; - IType Vi = uniqueBaseType.TypeArguments[i]; + IType Ui = pU.GetTypeArgument(i); + IType Vi = uniqueBaseType.GetTypeArgument(i); if (Ui.IsReferenceType(context) == true) { // look for variance ITypeParameter Xi = pU.GetDefinition().TypeParameters[i]; @@ -639,7 +746,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } } - Debug.Unindent(); + Log.Unindent(); } } #endregion @@ -647,18 +754,18 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver #region Fixing (§7.5.2.11) bool Fix(TP tp) { - Log(" Trying to fix " + tp); + Log.WriteLine(" Trying to fix " + tp); Debug.Assert(!tp.IsFixed); - Debug.Indent(); + Log.Indent(); var types = CreateNestedInstance().FindTypesInBounds(tp.LowerBounds.ToArray(), tp.UpperBounds.ToArray()); - Debug.Unindent(); + Log.Unindent(); if (algorithm == TypeInferenceAlgorithm.ImprovedReturnAllResults) { tp.FixedTo = IntersectionType.Create(types); - Log(" T was fixed " + (types.Count >= 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); + Log.WriteLine(" T was fixed " + (types.Count >= 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); return types.Count >= 1; } else { tp.FixedTo = GetFirstTypePreferNonInterfaces(types); - Log(" T was fixed " + (types.Count == 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); + Log.WriteLine(" T was fixed " + (types.Count == 1 ? "successfully" : "(with errors)") + " to " + tp.FixedTo); return types.Count == 1; } } @@ -668,10 +775,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// /// Gets the best common type (C# 4.0 spec: §7.5.2.14) of a set of expressions. /// - public IType GetBestCommonType(IEnumerable expressions, out bool success) + public IType GetBestCommonType(IList expressions, out bool success) { if (expressions == null) throw new ArgumentNullException("expressions"); + if (expressions.Count == 1) { + success = (expressions[0].Type.Kind != TypeKind.Unknown); + return expressions[0].Type; + } + Log.WriteCollection("GetBestCommonType() for ", expressions); try { this.typeParameters = new TP[1] { new TP(DummyTypeParameter.Instance) }; foreach (ResolveResult r in expressions) { @@ -739,14 +851,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver get { return VarianceModifier.Invariant; } } - IType ITypeParameter.BoundTo { - get { return null; } - } - - ITypeParameter ITypeParameter.UnboundTypeParameter { - get { return null; } - } - bool IFreezable.IsFrozen { get { return true; } } @@ -758,6 +862,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver DomRegion ITypeParameter.Region { get { return DomRegion.Empty; } } + + public override TypeKind Kind { + get { return TypeKind.TypeParameter; } + } } #endregion @@ -784,7 +892,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver static IType GetFirstTypePreferNonInterfaces(IList result) { - return result.FirstOrDefault(c => c.GetDefinition().ClassType != ClassType.Interface) + return result.FirstOrDefault(c => c.Kind != TypeKind.Interface) ?? result.FirstOrDefault() ?? SharedTypes.UnknownType; } @@ -800,9 +908,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver return EmptyList.Instance; // Finds a type X so that "LB <: X <: UB" - Log("FindTypesInBound, LowerBounds=", lowerBounds); - Log("FindTypesInBound, UpperBounds=", upperBounds); - Debug.Indent(); + Log.WriteCollection("FindTypesInBound, LowerBounds=", lowerBounds); + Log.WriteCollection("FindTypesInBound, UpperBounds=", upperBounds); // First try the Fixing algorithm from the C# spec (§7.5.2.11) List candidateTypes = lowerBounds.Union(upperBounds) @@ -824,6 +931,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver candidateTypes.Clear(); // Now try the improved algorithm + Log.Indent(); List candidateTypeDefinitions; if (lowerBounds.Count > 0) { // Find candidates by using the lower bounds: @@ -851,21 +959,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (candidateDef.TypeParameterCount == 0) { candidate = candidateDef; } else { - Log("Inferring arguments for candidate type definition: " + candidateDef); + Log.WriteLine("Inferring arguments for candidate type definition: " + candidateDef); bool success; IType[] result = InferTypeArgumentsFromBounds( candidateDef.TypeParameters, - new ParameterizedType(candidateDef, candidateDef.TypeParameters.SafeCast()), + new ParameterizedType(candidateDef, candidateDef.TypeParameters), lowerBounds, upperBounds, out success); if (success) { candidate = new ParameterizedType(candidateDef, result); } else { - Log("Inference failed; ignoring candidate"); + Log.WriteLine("Inference failed; ignoring candidate"); continue; } } - Log("Candidate type: " + candidate); + Log.WriteLine("Candidate type: " + candidate); if (lowerBounds.Count > 0) { // if there were lower bounds, we aim for the most specific candidate: @@ -889,31 +997,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } } - Debug.Unindent(); + Log.Unindent(); return candidateTypes; } #endregion - - [Conditional("DEBUG")] - static void Log(string text) - { - Debug.WriteLine(text); - } - - [Conditional("DEBUG")] - static void Log(string text, IEnumerable lines) - { - #if DEBUG - T[] arr = lines.ToArray(); - if (arr.Length == 0) { - Log(text + ""); - } else { - Log(text + (arr[0] != null ? arr[0].ToString() : "")); - for (int i = 1; i < arr.Length; i++) { - Log(new string(' ', text.Length) + (arr[i] != null ? arr[i].ToString() : "")); - } - } - #endif - } } } diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs b/ICSharpCode.NRefactory.CSharp/Resolver/UsingScope.cs similarity index 77% rename from ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs rename to ICSharpCode.NRefactory.CSharp/Resolver/UsingScope.cs index 6b55f3474..7a933459d 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/UsingScope.cs +++ b/ICSharpCode.NRefactory.CSharp/Resolver/UsingScope.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -13,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.Demo/CSDemo.Designer.cs b/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs index 998cee6fe..079e531e1 100644 --- a/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs +++ b/ICSharpCode.NRefactory.Demo/CSDemo.Designer.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// 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. namespace ICSharpCode.NRefactory.Demo { @@ -33,6 +48,7 @@ namespace ICSharpCode.NRefactory.Demo { this.splitContainer1 = new System.Windows.Forms.SplitContainer(); this.csharpCodeTextBox = new System.Windows.Forms.TextBox(); + this.findReferencesButton = new System.Windows.Forms.Button(); this.resolveButton = new System.Windows.Forms.Button(); this.csharpTreeView = new System.Windows.Forms.TreeView(); this.csharpGenerateCodeButton = new System.Windows.Forms.Button(); @@ -56,6 +72,7 @@ namespace ICSharpCode.NRefactory.Demo // // splitContainer1.Panel2 // + this.splitContainer1.Panel2.Controls.Add(this.findReferencesButton); this.splitContainer1.Panel2.Controls.Add(this.resolveButton); this.splitContainer1.Panel2.Controls.Add(this.csharpTreeView); this.splitContainer1.Panel2.Controls.Add(this.csharpGenerateCodeButton); @@ -77,15 +94,27 @@ namespace ICSharpCode.NRefactory.Demo this.csharpCodeTextBox.ScrollBars = System.Windows.Forms.ScrollBars.Both; this.csharpCodeTextBox.Size = new System.Drawing.Size(475, 178); this.csharpCodeTextBox.TabIndex = 0; - this.csharpCodeTextBox.Text = "using System;\r\nclass Test\r\n{\r\n public void Main(string[] args)\r\n {\r\n " + - " Console.WriteLine(\"Hello, World\");\r\n }\r\n}"; + this.csharpCodeTextBox.Text = "using System;\r\nusing System.Linq;\r\nclass Test\r\n{\r\n public void Main(string[] a" + + "rgs)\r\n {\r\n Console.WriteLine(\"Hello, World\");\r\n }\r\n}"; this.csharpCodeTextBox.WordWrap = false; this.csharpCodeTextBox.TextChanged += new System.EventHandler(this.CsharpCodeTextBoxTextChanged); // + // findReferencesButton + // + this.findReferencesButton.Anchor = System.Windows.Forms.AnchorStyles.Top; + this.findReferencesButton.Enabled = false; + this.findReferencesButton.Location = new System.Drawing.Point(344, 4); + this.findReferencesButton.Name = "findReferencesButton"; + this.findReferencesButton.Size = new System.Drawing.Size(100, 23); + this.findReferencesButton.TabIndex = 4; + this.findReferencesButton.Text = "Find References"; + this.findReferencesButton.UseVisualStyleBackColor = true; + this.findReferencesButton.Click += new System.EventHandler(this.FindReferencesButtonClick); + // // resolveButton // this.resolveButton.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.resolveButton.Location = new System.Drawing.Point(187, 3); + this.resolveButton.Location = new System.Drawing.Point(132, 4); this.resolveButton.Name = "resolveButton"; this.resolveButton.Size = new System.Drawing.Size(100, 23); this.resolveButton.TabIndex = 3; @@ -108,7 +137,7 @@ namespace ICSharpCode.NRefactory.Demo // csharpGenerateCodeButton // this.csharpGenerateCodeButton.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.csharpGenerateCodeButton.Location = new System.Drawing.Point(293, 2); + this.csharpGenerateCodeButton.Location = new System.Drawing.Point(238, 4); this.csharpGenerateCodeButton.Name = "csharpGenerateCodeButton"; this.csharpGenerateCodeButton.Size = new System.Drawing.Size(100, 23); this.csharpGenerateCodeButton.TabIndex = 1; @@ -119,7 +148,7 @@ namespace ICSharpCode.NRefactory.Demo // csharpParseButton // this.csharpParseButton.Anchor = System.Windows.Forms.AnchorStyles.Top; - this.csharpParseButton.Location = new System.Drawing.Point(81, 3); + this.csharpParseButton.Location = new System.Drawing.Point(26, 4); this.csharpParseButton.Name = "csharpParseButton"; this.csharpParseButton.Size = new System.Drawing.Size(100, 23); this.csharpParseButton.TabIndex = 0; @@ -141,6 +170,7 @@ namespace ICSharpCode.NRefactory.Demo this.splitContainer1.ResumeLayout(false); this.ResumeLayout(false); } + private System.Windows.Forms.Button findReferencesButton; private System.Windows.Forms.Button csharpParseButton; private System.Windows.Forms.Button csharpGenerateCodeButton; private System.Windows.Forms.TreeView csharpTreeView; diff --git a/ICSharpCode.NRefactory.Demo/CSDemo.cs b/ICSharpCode.NRefactory.Demo/CSDemo.cs index f589e3325..82dd46559 100644 --- a/ICSharpCode.NRefactory.Demo/CSDemo.cs +++ b/ICSharpCode.NRefactory.Demo/CSDemo.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -7,6 +22,7 @@ using System.ComponentModel; using System.Diagnostics; using System.Drawing; using System.IO; +using System.Linq; using System.Reflection; using System.Text; using System.Threading; @@ -15,6 +31,7 @@ using System.Windows.Forms; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -56,6 +73,7 @@ namespace ICSharpCode.NRefactory.Demo } SelectCurrentNode(csharpTreeView.Nodes); resolveButton.Enabled = true; + findReferencesButton.Enabled = true; } TreeNode MakeTreeNode(AstNode node) @@ -130,12 +148,12 @@ namespace ICSharpCode.NRefactory.Demo void CSharpGenerateCodeButtonClick(object sender, EventArgs e) { StringWriter w = new StringWriter(); - OutputVisitor output = new OutputVisitor(w, new CSharpFormattingOptions()); + CSharpOutputVisitor output = new CSharpOutputVisitor(w, new CSharpFormattingOptions()); compilationUnit.AcceptVisitor(output, null); csharpCodeTextBox.Text = w.ToString(); } - int GetOffset(TextBox textBox, AstLocation location) + int GetOffset(TextBox textBox, TextLocation location) { return textBox.GetFirstCharIndexFromLine(location.Line - 1) + location.Column - 1; } @@ -144,9 +162,13 @@ namespace ICSharpCode.NRefactory.Demo { AstNode node = e.Node.Tag as AstNode; if (node != null) { - int startOffset = GetOffset(csharpCodeTextBox, node.StartLocation); - int endOffset = GetOffset(csharpCodeTextBox, node.EndLocation); - csharpCodeTextBox.Select(startOffset, endOffset - startOffset); + if (node.StartLocation.IsEmpty || node.EndLocation.IsEmpty) { + csharpCodeTextBox.DeselectAll(); + } else { + int startOffset = GetOffset(csharpCodeTextBox, node.StartLocation); + int endOffset = GetOffset(csharpCodeTextBox, node.EndLocation); + csharpCodeTextBox.Select(startOffset, endOffset - startOffset); + } } } @@ -178,9 +200,8 @@ namespace ICSharpCode.NRefactory.Demo void ResolveButtonClick(object sender, EventArgs e) { SimpleProjectContent project = new SimpleProjectContent(); - TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(project, "dummy.cs"); - compilationUnit.AcceptVisitor(convertVisitor, null); - project.UpdateProjectContent(null, convertVisitor.ParsedFile); + var parsedFile = new TypeSystemConvertVisitor(project, "dummy.cs").Convert(compilationUnit); + project.UpdateProjectContent(null, parsedFile); List projects = new List(); projects.Add(project); @@ -193,7 +214,7 @@ namespace ICSharpCode.NRefactory.Demo if (csharpTreeView.SelectedNode != null) { navigator = new NodeListResolveVisitorNavigator(new[] { (AstNode)csharpTreeView.SelectedNode.Tag }); } - ResolveVisitor visitor = new ResolveVisitor(resolver, convertVisitor.ParsedFile, navigator); + ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); visitor.Scan(compilationUnit); csharpTreeView.BeginUpdate(); ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); @@ -206,7 +227,7 @@ namespace ICSharpCode.NRefactory.Demo foreach (TreeNode t in c) { AstNode node = t.Tag as AstNode; if (node != null) { - ResolveResult rr = v.GetResolveResult(node); + ResolveResult rr = v.GetResolveResultIfResolved(node); if (rr != null) t.Text = GetNodeTitle(node) + " " + rr.ToString(); else @@ -227,6 +248,57 @@ namespace ICSharpCode.NRefactory.Demo void CsharpCodeTextBoxTextChanged(object sender, EventArgs e) { resolveButton.Enabled = false; + findReferencesButton.Enabled = false; + } + + void FindReferencesButtonClick(object sender, EventArgs e) + { + if (csharpTreeView.SelectedNode == null) + return; + + SimpleProjectContent project = new SimpleProjectContent(); + var parsedFile = new TypeSystemConvertVisitor(project, "dummy.cs").Convert(compilationUnit); + project.UpdateProjectContent(null, parsedFile); + + List projects = new List(); + projects.Add(project); + projects.AddRange(builtInLibs.Value); + + using (var context = new CompositeTypeResolveContext(projects).Synchronize()) { + CSharpResolver resolver = new CSharpResolver(context); + + AstNode node = (AstNode)csharpTreeView.SelectedNode.Tag; + IResolveVisitorNavigator navigator = new NodeListResolveVisitorNavigator(new[] { node }); + ResolveVisitor visitor = new ResolveVisitor(resolver, parsedFile, navigator); + visitor.Scan(compilationUnit); + IEntity entity; + MemberResolveResult mrr = visitor.GetResolveResult(node) as MemberResolveResult; + TypeResolveResult trr = visitor.GetResolveResult(node) as TypeResolveResult; + if (mrr != null) { + entity = mrr.Member; + } else if (trr != null) { + entity = trr.Type.GetDefinition(); + } else { + return; + } + + FindReferences fr = new FindReferences(); + int referenceCount = 0; + FoundReferenceCallback callback = delegate(AstNode matchNode, ResolveResult result) { + referenceCount++; + }; + + var searchScopes = fr.GetSearchScopes(entity); + navigator = new CompositeResolveVisitorNavigator(searchScopes.Select(s => s.GetNavigator(callback)).ToArray()); + visitor = new ResolveVisitor(resolver, parsedFile, navigator); + visitor.Scan(compilationUnit); + + csharpTreeView.BeginUpdate(); + ShowResolveResultsInTree(csharpTreeView.Nodes, visitor); + csharpTreeView.EndUpdate(); + + MessageBox.Show("Found " + referenceCount + " references to " + entity.FullName); + } } } } diff --git a/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj b/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj index 841474f59..8b91449b7 100644 --- a/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj +++ b/ICSharpCode.NRefactory.Demo/ICSharpCode.NRefactory.Demo.csproj @@ -8,7 +8,6 @@ ICSharpCode.NRefactory.Demo ICSharpCode.NRefactory.Demo v4.0 - Client Properties @@ -30,6 +29,9 @@ False TRACE + + x86 + @@ -58,6 +60,10 @@ + + {53DCA265-3C3C-42F9-B647-F72BA678122B} + ICSharpCode.NRefactory.CSharp + {7B82B671-419F-45F4-B778-D9286F996EFA} ICSharpCode.NRefactory.VB diff --git a/ICSharpCode.NRefactory.Demo/MainForm.Designer.cs b/ICSharpCode.NRefactory.Demo/MainForm.Designer.cs index 12c38ffb6..61def695c 100644 --- a/ICSharpCode.NRefactory.Demo/MainForm.Designer.cs +++ b/ICSharpCode.NRefactory.Demo/MainForm.Designer.cs @@ -1,5 +1,21 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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. + namespace ICSharpCode.NRefactory.Demo { partial class MainForm diff --git a/ICSharpCode.NRefactory.Demo/MainForm.cs b/ICSharpCode.NRefactory.Demo/MainForm.cs index 9633a00f1..e548fd2c3 100644 --- a/ICSharpCode.NRefactory.Demo/MainForm.cs +++ b/ICSharpCode.NRefactory.Demo/MainForm.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory.Demo/Program.cs b/ICSharpCode.NRefactory.Demo/Program.cs index 7c176b1aa..d7d34708f 100644 --- a/ICSharpCode.NRefactory.Demo/Program.cs +++ b/ICSharpCode.NRefactory.Demo/Program.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Windows.Forms; diff --git a/ICSharpCode.NRefactory.Demo/VBAstView.Designer.cs b/ICSharpCode.NRefactory.Demo/VBAstView.Designer.cs index 9cdb32334..c8e09c198 100644 --- a/ICSharpCode.NRefactory.Demo/VBAstView.Designer.cs +++ b/ICSharpCode.NRefactory.Demo/VBAstView.Designer.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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. namespace ICSharpCode.NRefactory.Demo { diff --git a/ICSharpCode.NRefactory.Demo/VBAstView.cs b/ICSharpCode.NRefactory.Demo/VBAstView.cs index a6e6f58aa..21656d230 100644 --- a/ICSharpCode.NRefactory.Demo/VBAstView.cs +++ b/ICSharpCode.NRefactory.Demo/VBAstView.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; diff --git a/ICSharpCode.NRefactory.Demo/VBDemo.Designer.cs b/ICSharpCode.NRefactory.Demo/VBDemo.Designer.cs index 48641c669..4168c0bea 100644 --- a/ICSharpCode.NRefactory.Demo/VBDemo.Designer.cs +++ b/ICSharpCode.NRefactory.Demo/VBDemo.Designer.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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. namespace ICSharpCode.NRefactory.Demo { diff --git a/ICSharpCode.NRefactory.Demo/VBDemo.cs b/ICSharpCode.NRefactory.Demo/VBDemo.cs index beb3308c1..287aa20aa 100644 --- a/ICSharpCode.NRefactory.Demo/VBDemo.cs +++ b/ICSharpCode.NRefactory.Demo/VBDemo.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -122,7 +137,7 @@ namespace ICSharpCode.NRefactory.Demo codeView.Text = w.ToString(); } - int GetOffset(TextBox textBox, AstLocation location) + int GetOffset(TextBox textBox, TextLocation location) { return textBox.GetFirstCharIndexFromLine(location.Line - 1) + location.Column - 1; } diff --git a/ICSharpCode.NRefactory.Demo/VBEditDialog.Designer.cs b/ICSharpCode.NRefactory.Demo/VBEditDialog.Designer.cs index 6d4254497..451c8aefd 100644 --- a/ICSharpCode.NRefactory.Demo/VBEditDialog.Designer.cs +++ b/ICSharpCode.NRefactory.Demo/VBEditDialog.Designer.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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. namespace ICSharpCode.NRefactory.Demo { diff --git a/ICSharpCode.NRefactory.Demo/VBEditDialog.cs b/ICSharpCode.NRefactory.Demo/VBEditDialog.cs index 031ab9971..6c591d493 100644 --- a/ICSharpCode.NRefactory.Demo/VBEditDialog.cs +++ b/ICSharpCode.NRefactory.Demo/VBEditDialog.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Drawing; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs index 10373b84c..dc4bf55f8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Analysis/DefiniteAssignmentTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs index 183efacdb..777f2e869 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/AstStructureTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Reflection; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.cs new file mode 100644 index 000000000..d836308e5 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/CSharpOutputVisitorTests.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 CSharpOutputVisitorTests + { + 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 CSharpOutputVisitor(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/CSharp/CodeDomConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs new file mode 100644 index 000000000..ab61edf51 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/CodeDomConvertVisitorTests.cs @@ -0,0 +1,177 @@ +// 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.CodeDom; +using System.CodeDom.Compiler; +using System.IO; +using System.Text.RegularExpressions; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using Microsoft.CSharp; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp +{ + [TestFixture] + public class CodeDomConvertVisitorTests : ResolverTestBase + { + CodeDomConvertVisitor convertVisitor; + + public override void SetUp() + { + base.SetUp(); + AddUsing("System"); + AddUsing("System.Collections.Generic"); + AddUsing("System.Linq"); + resolver.CurrentTypeDefinition = new DefaultTypeDefinition(project, string.Empty, "MyClass"); + convertVisitor = new CodeDomConvertVisitor(); + convertVisitor.UseFullyQualifiedTypeNames = true; + } + + string Convert(Expression expr) + { + ResolveVisitor rv = new ResolveVisitor(resolver, null); + rv.Scan(expr); + var codeExpr = (CodeExpression)convertVisitor.Convert(expr, rv); + StringWriter writer = new StringWriter(); + writer.NewLine = " "; + new CSharpCodeProvider().GenerateCodeFromExpression(codeExpr, writer, new CodeGeneratorOptions { IndentString = " " }); + return Regex.Replace(writer.ToString(), @"\s+", " "); + } + + [Test] + public void CreateArray() + { + Assert.AreEqual("new int[10]", Convert( + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(10) } + })); + } + + [Test] + public void CreateJaggedArray() + { + Assert.AreEqual("new int[10][]", Convert( + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(10) }, + AdditionalArraySpecifiers = { new ArraySpecifier() } + })); + } + + [Test] + public void Create2DArray() + { + Assert.AreEqual("new int[10, 20]", Convert( + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(10), new PrimitiveExpression(20) } + })); + } + + [Test] + public void CreateImplicitlyTypedArray() + { + // implicitly-typed array not supported in CodeDom, so the conversion should infer the type + Assert.AreEqual("new int[] { 1, 2, 3}", Convert( + new ArrayCreateExpression { + AdditionalArraySpecifiers = { new ArraySpecifier() }, + Initializer = new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(1), + new PrimitiveExpression(2), + new PrimitiveExpression(3) + } + } + })); + } + + [Test] + public void Create2DImplicitlyTypedArray() + { + Assert.AreEqual("new int[,] { { 1, 2 }, { 3, 4 }}", Convert( + new ArrayCreateExpression { + AdditionalArraySpecifiers = { new ArraySpecifier(2) }, + Initializer = new ArrayInitializerExpression { + Elements = { + new ArrayInitializerExpression(new PrimitiveExpression(1), new PrimitiveExpression(2)), + new ArrayInitializerExpression(new PrimitiveExpression(3), new PrimitiveExpression(4)) + } + } + })); + } + + [Test] + public void AdditionOperator() + { + Assert.AreEqual("(0 + 1)", Convert( + new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Add, new PrimitiveExpression(1)))); + } + + [Test] + public void EqualityOperator() + { + Assert.AreEqual("(0 == 1)", Convert( + new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.Equality, new PrimitiveExpression(1)))); + } + + [Test] + public void InEqualityOperator() + { + Assert.AreEqual("((0 == 1) == false)", Convert( + new BinaryOperatorExpression(new PrimitiveExpression(0), BinaryOperatorType.InEquality, new PrimitiveExpression(1)))); + } + + [Test] + public void ReferenceInEqualityOperator() + { + Assert.AreEqual("(default(object) != null)", Convert( + new BinaryOperatorExpression(new DefaultValueExpression(new PrimitiveType("object")), BinaryOperatorType.InEquality, new NullReferenceExpression()))); + } + + [Test] + public void StaticProperty() + { + Assert.AreEqual("System.Environment.TickCount", Convert( + new IdentifierExpression("Environment").Member("TickCount"))); + } + + [Test] + public void InstanceMethodInvocation() + { + Assert.AreEqual("this.Equals(null)", + Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression()))); + } + + [Test] + public void StaticMethodInvocation() + { + Assert.AreEqual("object.Equals(null, null)", + Convert(new IdentifierExpression("Equals").Invoke(new NullReferenceExpression(), new NullReferenceExpression()))); + } + + [Test] + public void NotOperator() + { + Assert.AreEqual("(a == false)", Convert(new UnaryOperatorExpression(UnaryOperatorType.Not, new IdentifierExpression("a")))); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs index b7f6328f3..05bbcede4 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/InsertParenthesesVisitorTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -24,7 +39,7 @@ namespace ICSharpCode.NRefactory.CSharp expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }, null); StringWriter w = new StringWriter(); w.NewLine = " "; - expr.AcceptVisitor(new OutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null); + expr.AcceptVisitor(new CSharpOutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null); return w.ToString(); } @@ -34,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp expr.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = false }, null); StringWriter w = new StringWriter(); w.NewLine = " "; - expr.AcceptVisitor(new OutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null); + expr.AcceptVisitor(new CSharpOutputVisitor(new TextWriterOutputFormatter(w) { IndentationString = "" }, policy), null); return w.ToString(); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs deleted file mode 100644 index a3ec92054..000000000 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AliasReferenceExpressionTests.cs +++ /dev/null @@ -1,53 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - - -using System; -using System.IO; -using NUnit.Framework; -using ICSharpCode.NRefactory.PatternMatching; - -namespace ICSharpCode.NRefactory.CSharp.Parser.Expression -{ - [TestFixture] - public class AliasReferenceExpressionTests - { - [Test] - public void GlobalReferenceExpressionTest() - { - CSharpParser parser = new CSharpParser(); - AstType type = parser.ParseTypeReference(new StringReader("global::System")); - Assert.IsTrue( - new MemberType { - Target = new SimpleType("global"), - IsDoubleColon = true, - MemberName = "System" - }.IsMatch(type) - ); - } - - [Test] - public void GlobalTypeDeclaration() - { - VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("global::System.String a;"); - Assert.IsTrue( - new VariableDeclarationStatement { - Type = new MemberType { - Target = new MemberType { - Target = new SimpleType("global"), - IsDoubleColon = true, - MemberName = "System" - }, - IsDoubleColon = false, - MemberName = "String", - }, - Variables = { - new VariableInitializer("a") - } - }.IsMatch(lvd) - ); - } - - // TODO: add tests for aliases other than 'global' - } -} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodExpressionTests.cs new file mode 100644 index 000000000..1858b8d4c --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodExpressionTests.cs @@ -0,0 +1,82 @@ +// 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 System.Linq; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class AnonymousMethodExpressionTests + { + AnonymousMethodExpression Parse(string expression) + { + return ParseUtilCSharp.ParseExpression(expression); + } + + [Test] + public void AnonymousMethodWithoutParameterList() + { + AnonymousMethodExpression ame = Parse("delegate {}"); + Assert.AreEqual(0, ame.Parameters.Count()); + Assert.AreEqual(0, ame.Body.Statements.Count()); + Assert.IsFalse(ame.IsAsync); + Assert.IsFalse(ame.HasParameterList); + } + + [Test] + public void AnonymousMethodAfterCast() + { + CastExpression c = ParseUtilCSharp.ParseExpression("(ThreadStart)delegate {}"); + AnonymousMethodExpression ame = (AnonymousMethodExpression)c.Expression; + Assert.AreEqual(0, ame.Parameters.Count()); + Assert.AreEqual(0, ame.Body.Statements.Count()); + } + + [Test] + public void EmptyAnonymousMethod() + { + AnonymousMethodExpression ame = Parse("delegate() {}"); + Assert.AreEqual(0, ame.Parameters.Count()); + Assert.AreEqual(0, ame.Body.Statements.Count()); + Assert.IsTrue(ame.HasParameterList); + } + + [Test] + public void SimpleAnonymousMethod() + { + AnonymousMethodExpression ame = Parse("delegate(int a, int b) { return a + b; }"); + Assert.IsTrue(ame.HasParameterList); + Assert.AreEqual(2, ame.Parameters.Count()); + Assert.AreEqual(1, ame.Body.Statements.Count()); + Assert.IsTrue(ame.Body.Statements.First() is ReturnStatement); + } + + [Test, Ignore("async/await not yet supported")] + public void AsyncAnonymousMethod() + { + AnonymousMethodExpression ame = Parse("async delegate {}"); + Assert.AreEqual(0, ame.Parameters.Count()); + Assert.AreEqual(0, ame.Body.Statements.Count()); + Assert.IsTrue(ame.IsAsync); + Assert.IsFalse(ame.HasParameterList); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs deleted file mode 100644 index 710df07ec..000000000 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousMethodTests.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.IO; -using System.Linq; -using NUnit.Framework; - -namespace ICSharpCode.NRefactory.CSharp.Parser.Expression -{ - [TestFixture] - public class AnonymousMethodTests - { - AnonymousMethodExpression Parse(string expression) - { - return ParseUtilCSharp.ParseExpression(expression); - } - - [Test] - public void AnonymousMethodWithoutParameterList() - { - AnonymousMethodExpression ame = Parse("delegate {}"); - Assert.AreEqual(0, ame.Parameters.Count()); - Assert.AreEqual(0, ame.Body.Statements.Count()); - Assert.IsFalse(ame.HasParameterList); - } - - [Test] - public void AnonymousMethodAfterCast() - { - CastExpression c = ParseUtilCSharp.ParseExpression("(ThreadStart)delegate {}"); - AnonymousMethodExpression ame = (AnonymousMethodExpression)c.Expression; - Assert.AreEqual(0, ame.Parameters.Count()); - Assert.AreEqual(0, ame.Body.Statements.Count()); - } - - [Test] - public void EmptyAnonymousMethod() - { - AnonymousMethodExpression ame = Parse("delegate() {}"); - Assert.AreEqual(0, ame.Parameters.Count()); - Assert.AreEqual(0, ame.Body.Statements.Count()); - Assert.IsTrue(ame.HasParameterList); - } - - [Test] - public void SimpleAnonymousMethod() - { - AnonymousMethodExpression ame = Parse("delegate(int a, int b) { return a + b; }"); - Assert.IsTrue(ame.HasParameterList); - Assert.AreEqual(2, ame.Parameters.Count()); - Assert.AreEqual(1, ame.Body.Statements.Count()); - Assert.IsTrue(ame.Body.Statements.First() is ReturnStatement); - } - } -} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs new file mode 100644 index 000000000..e0190fd26 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AnonymousTypeCreateExpressionTests.cs @@ -0,0 +1,40 @@ +// 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 NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class AnonymousTypeCreateExpressionTests + { + [Test] + public void Simple() + { + ParseUtilCSharp.AssertExpression( + "new { Name = \"Test\", Price, Something.Property }", + new AnonymousTypeCreateExpression { + Initializers = { + new NamedExpression("Name", new PrimitiveExpression("Test")), + new IdentifierExpression("Price"), + new IdentifierExpression("Something").Member("Property") + }}); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs new file mode 100644 index 000000000..bb96d1e5b --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayCreateExpressionTests.cs @@ -0,0 +1,149 @@ +// 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 NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class ArrayCreateExpressionTests + { + [Test] + public void ArrayCreateExpressionTest1() + { + ParseUtilCSharp.AssertExpression( + "new int[5]", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(5) } + }); + } + + [Test] + public void MultidimensionalNestedArray() + { + ParseUtilCSharp.AssertExpression( + "new int[5,2][,,][]", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + Arguments = { new PrimitiveExpression(5), new PrimitiveExpression(2) }, + AdditionalArraySpecifiers = { + new ArraySpecifier(3), + new ArraySpecifier(1) + } + }); + } + + [Test] + public void ArrayWithImplicitSize() + { + ParseUtilCSharp.AssertExpression( + "new int[] { 1 }", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + AdditionalArraySpecifiers = { + new ArraySpecifier(0) + }, + Initializer = new ArrayInitializerExpression { + Elements = { new PrimitiveExpression(1) } + } + }); + } + + [Test] + public void ArrayWithImplicitSize2D() + { + ParseUtilCSharp.AssertExpression( + "new int[,] { { 1 } }", + new ArrayCreateExpression { + Type = new PrimitiveType("int"), + AdditionalArraySpecifiers = { new ArraySpecifier (2) }, + Initializer = new ArrayInitializerExpression { + Elements = { + new ArrayInitializerExpression { + Elements = { new PrimitiveExpression(1) } + } + } + } + }); + } + + [Test] + public void ImplicitlyTypedArrayCreateExpression() + { + ParseUtilCSharp.AssertExpression( + "new[] { 1, 10, 100, 1000 }", + new ArrayCreateExpression { + AdditionalArraySpecifiers = { + new ArraySpecifier(0) + }, + Initializer = new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(1), + new PrimitiveExpression(10), + new PrimitiveExpression(100), + new PrimitiveExpression(1000) + } + }}); + } + + [Test] + public void ImplicitlyTypedArrayCreateExpression2D() + { + ParseUtilCSharp.AssertExpression( + "new [,] { { 1, 10 }, { 100, 1000 } }", + new ArrayCreateExpression { + AdditionalArraySpecifiers = { + new ArraySpecifier(2), + }, + Initializer = new ArrayInitializerExpression { + Elements = { + new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(1), + new PrimitiveExpression(10) + } + }, + new ArrayInitializerExpression { + Elements = { + new PrimitiveExpression(100), + new PrimitiveExpression(1000) + } + } + } + }}); + } + + [Test] + public void AssignmentInArrayInitializer() + { + ParseUtilCSharp.AssertExpression( + "new [] { a = 10 }", + new ArrayCreateExpression { + AdditionalArraySpecifiers = { + new ArraySpecifier(0) + }, + Initializer = new ArrayInitializerExpression { + Elements = { + new AssignmentExpression(new IdentifierExpression("a"), new PrimitiveExpression(10)) + } + }}); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs deleted file mode 100644 index a6d3ec017..000000000 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ArrayObjectCreateExpressionTests.cs +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using NUnit.Framework; - -namespace ICSharpCode.NRefactory.CSharp.Parser.Expression -{ - [TestFixture] - public class ArrayObjectCreateExpressionTests - { - [Test] - public void ArrayCreateExpressionTest1() - { - ParseUtilCSharp.AssertExpression( - "new int[5]", - new ArrayCreateExpression { - Type = new PrimitiveType("int"), - Arguments = { new PrimitiveExpression(5) } - }); - } - - [Test] - public void MultidimensionalNestedArray() - { - ParseUtilCSharp.AssertExpression( - "new int[5,2][,,][]", - new ArrayCreateExpression { - Type = new PrimitiveType("int"), - Arguments = { new PrimitiveExpression(5), new PrimitiveExpression(2) }, - AdditionalArraySpecifiers = { - new ArraySpecifier(3), - new ArraySpecifier(1) - } - }); - } - - [Test] - public void ImplicitlyTypedArrayCreateExpression() - { - ParseUtilCSharp.AssertExpression( - "new[] { 1, 10, 100, 1000 }", - new ArrayCreateExpression { - Initializer = new ArrayInitializerExpression { - Elements = { - new PrimitiveExpression(1), - new PrimitiveExpression(10), - new PrimitiveExpression(100), - new PrimitiveExpression(1000) - } - } - }); - - } - } -} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs index 065b88bba..29156a15b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/AssignmentExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; @@ -84,5 +99,15 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression { TestAssignmentExpression("a ^= b", AssignmentOperatorType.ExclusiveOr); } + + [Test] + public void NestedAssignment() + { + ParseUtilCSharp.AssertExpression( + "a = b = c", + new AssignmentExpression( + new IdentifierExpression("a"), + new AssignmentExpression(new IdentifierExpression("b"), new IdentifierExpression("c")))); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BaseReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BaseReferenceExpressionTests.cs index 4bde43b92..d6f0739ad 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BaseReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BaseReferenceExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BinaryOperatorExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BinaryOperatorExpressionTests.cs index 9e133b763..5c83b84e5 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BinaryOperatorExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/BinaryOperatorExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs index 2909f7184..c111d1b7f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CastExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CheckedExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CheckedExpressionTests.cs index 696a28b7a..403e5a10c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CheckedExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/CheckedExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ConditionalExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ConditionalExpressionTests.cs index 819b16582..88de721c6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ConditionalExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ConditionalExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs index 03f561753..9b9d5b048 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/DefaultValueExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs index 5a054efe6..5c4e97214 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IdentifierExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IndexerExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IndexerExpressionTests.cs index 1a46dc63f..79cfb6107 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IndexerExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IndexerExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs index 53c89bbf8..91983603e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/InvocationExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; @@ -104,14 +119,14 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression public void NestedInvocationPositions() { InvocationExpression expr = ParseUtilCSharp.ParseExpression("a.B().C(args)"); - Assert.AreEqual(new AstLocation(1, 8), expr.StartLocation); - Assert.AreEqual(new AstLocation(1, 14), expr.EndLocation); + Assert.AreEqual(new TextLocation(1, 8), expr.StartLocation); + Assert.AreEqual(new TextLocation(1, 14), expr.EndLocation); MemberReferenceExpression mre = (MemberReferenceExpression)expr.Target; - Assert.AreEqual(new AstLocation(1, 6), mre.StartLocation); - Assert.AreEqual(new AstLocation(1, 8), mre.EndLocation); + Assert.AreEqual(new TextLocation(1, 6), mre.StartLocation); + Assert.AreEqual(new TextLocation(1, 8), mre.EndLocation); - Assert.AreEqual(new AstLocation(1, 4), mre.Target.StartLocation); - Assert.AreEqual(new AstLocation(1, 6), mre.Target.EndLocation); + Assert.AreEqual(new TextLocation(1, 4), mre.Target.StartLocation); + Assert.AreEqual(new TextLocation(1, 6), mre.Target.EndLocation); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs index bbab99a6f..baf6f8ad0 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/IsExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs index d389bac7c..7a67ccaad 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/LambdaExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; @@ -104,5 +119,29 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression FalseExpression = new NullReferenceExpression() }}); } + + [Test, Ignore("async/await not yet supported")] + public void AsyncLambdaExpression() + { + ParseUtilCSharp.AssertExpression( + "async x => x + 1", + new LambdaExpression { + IsAsync = true, + Parameters = { new ParameterDeclaration { Name = "x" } }, + Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }); + } + + [Test, Ignore("async/await not yet supported")] + public void AsyncLambdaExpressionWithMultipleParameters() + { + ParseUtilCSharp.AssertExpression( + "async (x,y) => x + 1", + new LambdaExpression { + IsAsync = true, + Parameters = { new ParameterDeclaration { Name = "x" }, new ParameterDeclaration { Name = "y" } }, + Body = new BinaryOperatorExpression(new IdentifierExpression("x"), BinaryOperatorType.Add, new PrimitiveExpression(1)) + }); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs index 038b33644..dedbd8353 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/MemberReferenceExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; @@ -89,5 +104,22 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression }.Member("myField") ); } + + [Test] + public void AliasedNamespace() + { + ParseUtilCSharp.AssertExpression( + "a::b.c", + new MemberReferenceExpression { + Target = new TypeReferenceExpression { + Type = new MemberType { + Target = new SimpleType("a"), + IsDoubleColon = true, + MemberName = "b" + } + }, + MemberName = "c" + }); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs new file mode 100644 index 000000000..768ae9f39 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ObjectCreateExpressionTests.cs @@ -0,0 +1,252 @@ +// 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 NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Parser.Expression +{ + [TestFixture] + public class ObjectCreateExpressionTests + { + [Test] + public void Simple() + { + ParseUtilCSharp.AssertExpression( + "new MyObject(1, 2, 3)", + new ObjectCreateExpression { + Type = new SimpleType("MyObject"), + Arguments = { + new PrimitiveExpression(1), + new PrimitiveExpression(2), + new PrimitiveExpression(3) + }}); + } + + [Test] + public void Nullable() + { + ParseUtilCSharp.AssertExpression( + "new IntPtr?(1)", + new ObjectCreateExpression { + Type = new SimpleType("IntPtr").MakeNullableType(), + Arguments = { new PrimitiveExpression(1) } + }); + } + + [Test] + public void ObjectInitializer() + { + ParseUtilCSharp.AssertExpression( + "new Point() { X = 0, Y = 1 }", + new ObjectCreateExpression { + Type = new SimpleType("Point"), + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) + } + }}); + } + + [Test] + public void ObjectInitializerWithoutParenthesis() + { + ParseUtilCSharp.AssertExpression( + "new Point { X = 0, Y = 1 }", + new ObjectCreateExpression { + Type = new SimpleType("Point"), + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) + } + }}); + } + + [Test] + public void ObjectInitializerWithTrailingComma() + { + ParseUtilCSharp.AssertExpression( + "new Point() { X = 0, Y = 1, }", + new ObjectCreateExpression { + Type = new SimpleType("Point"), + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) + } + }}); + } + + [Test] + public void NestedObjectInitializer() + { + ParseUtilCSharp.AssertExpression( + "new Rectangle { P1 = new Point { X = 0, Y = 1 }, P2 = new Point { X = 2, Y = 3 } }", + new ObjectCreateExpression { + Type = new SimpleType("Rectangle"), + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression( + "P1", + new ObjectCreateExpression { + Type = new SimpleType("Point"), + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) + } + }}), + new NamedExpression( + "P2", + new ObjectCreateExpression { + Type = new SimpleType("Point"), + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression("X", new PrimitiveExpression(2)), + new NamedExpression("Y", new PrimitiveExpression(3)) + } + }}) + }}}); + } + + [Test] + public void NestedObjectInitializerForPreinitializedProperty() + { + ParseUtilCSharp.AssertExpression( + "new Rectangle { P1 = { X = 0, Y = 1 }, P2 = { X = 2, Y = 3 } }", + new ObjectCreateExpression { + Type = new SimpleType("Rectangle"), + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression( + "P1", + new ArrayInitializerExpression { + Elements = { + new NamedExpression("X", new PrimitiveExpression(0)), + new NamedExpression("Y", new PrimitiveExpression(1)) + } + }), + new NamedExpression( + "P2", + new ArrayInitializerExpression { + Elements = { + new NamedExpression("X", new PrimitiveExpression(2)), + new NamedExpression("Y", new PrimitiveExpression(3)) + } + }) + }}}); + } + + [Test] + public void CollectionInitializer() + { + ParseUtilCSharp.AssertExpression( + "new List { 0, 1, 2 }", + new ObjectCreateExpression { + Type = new SimpleType("List", new PrimitiveType("int")), + Initializer = new ArrayInitializerExpression { + Elements = { + new ArrayInitializerExpression(new PrimitiveExpression(0)), + new ArrayInitializerExpression(new PrimitiveExpression(1)), + new ArrayInitializerExpression(new PrimitiveExpression(2)) + }}}); + } + + + [Test] + public void DictionaryInitializer() + { + ParseUtilCSharp.AssertExpression( + "new Dictionary { { \"a\", 0 }, { \"b\", 1 } }", + new ObjectCreateExpression { + Type = new SimpleType("Dictionary", new PrimitiveType("string"), new PrimitiveType("int")), + Initializer = new ArrayInitializerExpression { + Elements = { + new ArrayInitializerExpression { + Elements = { new PrimitiveExpression("a"), new PrimitiveExpression(0) } + }, + new ArrayInitializerExpression { + Elements = { new PrimitiveExpression("b"), new PrimitiveExpression(1) } + } + }}}); + } + + [Test] + public void ComplexCollectionInitializer() + { + ParseUtilCSharp.AssertExpression( + @"new List { + new Contact { + Name = ""Chris"", + PhoneNumbers = { ""206-555-0101"" } + }, + new Contact(additionalParameter) { + Name = ""Bob"", + PhoneNumbers = { ""650-555-0199"", ""425-882-8080"" } + } + }", + new ObjectCreateExpression { + Type = new SimpleType("List", new SimpleType("Contact")), + 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 ArrayInitializerExpression(new PrimitiveExpression("206-555-0101")) } + }) + }}}), + new ArrayInitializerExpression( + new ObjectCreateExpression { + Type = new SimpleType("Contact"), + Arguments = { new IdentifierExpression("additionalParameter") }, + Initializer = new ArrayInitializerExpression { + Elements = { + new NamedExpression("Name", new PrimitiveExpression("Bob")), + new NamedExpression("PhoneNumbers", new ArrayInitializerExpression () { + Elements = { + 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/ParenthesizedExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ParenthesizedExpressionTests.cs index c60bcbf1f..a9adfac5a 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ParenthesizedExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ParenthesizedExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs index 8104524b9..8527e6f3f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PointerReferenceExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs index 9b4b1efcc..61cfa77fe 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/PrimitiveExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; @@ -199,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 TextLocation(1, 1), pe.StartLocation); + Assert.AreEqual(new TextLocation(1, 2), pe.EndLocation); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs index 35e3f5489..b22860100 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/QueryExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; @@ -132,7 +147,7 @@ select new { c.Name, o.OrderID, o.Total }", }, new QuerySelectClause { Expression = new AnonymousTypeCreateExpression { - Initializer = { + Initializers = { new IdentifierExpression("c").Member("Name"), new IdentifierExpression("o").Member("OrderID"), new IdentifierExpression("o").Member("Total") @@ -280,5 +295,70 @@ select new { c.Name, o.OrderID, o.Total }", new QuerySelectClause { Expression = new IdentifierExpression("g") } }}); } + + [Test] + public void QueryWithGroupBy() + { + ParseUtilCSharp.AssertExpression( + "from a in b group c by d", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QueryGroupClause { + Projection = new IdentifierExpression("c"), + Key = new IdentifierExpression("d") + } + }}); + } + + [Test] + public void QueryWithJoin() + { + ParseUtilCSharp.AssertExpression( + "from a in b join c in d on e equals f select g", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QueryJoinClause { + JoinIdentifier = "c", + InExpression = new IdentifierExpression("d"), + OnExpression = new IdentifierExpression("e"), + EqualsExpression = new IdentifierExpression("f") + }, + new QuerySelectClause { + Expression = new IdentifierExpression("g") + } + }}); + } + + [Test] + public void QueryWithGroupJoin() + { + ParseUtilCSharp.AssertExpression( + "from a in b join c in d on e equals f into g select h", + new QueryExpression { + Clauses = { + new QueryFromClause { + Identifier = "a", + Expression = new IdentifierExpression("b") + }, + new QueryJoinClause { + JoinIdentifier = "c", + InExpression = new IdentifierExpression("d"), + OnExpression = new IdentifierExpression("e"), + EqualsExpression = new IdentifierExpression("f"), + IntoIdentifier = "g" + }, + new QuerySelectClause { + Expression = new IdentifierExpression("h") + } + }}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs index f6a85fcb3..8d168960e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/SizeOfExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs index c28d559fc..7e04028e6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/StackAllocExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ThisReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ThisReferenceExpressionTests.cs index 7c547adea..d35313554 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ThisReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/ThisReferenceExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs index 847b70567..2dbfd988c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeOfExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeReferenceExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeReferenceExpressionTests.cs index 31f01ce39..f3e93037f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeReferenceExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/TypeReferenceExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs index a968af1eb..a5c69f53b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Expression/UnaryOperatorExpressionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; @@ -66,17 +81,43 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Expression } [Test] - public void StarTest() + public void Dereference() { TestUnaryOperatorExpressionTest("*a", UnaryOperatorType.Dereference); } [Test] - public void BitWiseAndTest() + public void AddressOf() { TestUnaryOperatorExpressionTest("&a", UnaryOperatorType.AddressOf); } + [Test, Ignore("async/await not yet supported")] + public void Await() + { + ParseUtilCSharp.AssertExpression( + "async a => await a", + new LambdaExpression { + IsAsync = true, + Parameters = { new ParameterDeclaration { Name = "a" } }, + Body = new UnaryOperatorExpression(UnaryOperatorType.Await, new IdentifierExpression("a")) + }); + } + + [Test, Ignore("async/await not yet supported")] + public void AwaitAwait() + { + ParseUtilCSharp.AssertExpression( + "async a => await await a", + new LambdaExpression { + IsAsync = true, + Parameters = { new ParameterDeclaration { Name = "a" } }, + Body = new UnaryOperatorExpression( + UnaryOperatorType.Await, + new UnaryOperatorExpression(UnaryOperatorType.Await, new IdentifierExpression("a"))) + }); + } + [Test] public void DereferenceAfterCast() { diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs index 15707c51b..17def861a 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/AttributeSectionTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; @@ -15,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()] @@ -30,56 +45,50 @@ public class Form1 { } [Test] - public void AssemblyAttributeCSharp() + public void AssemblyAttribute() { string program = @"[assembly: System.Attribute()]"; AttributeSection decl = ParseUtilCSharp.ParseGlobal(program); - Assert.AreEqual(new AstLocation(1, 1), decl.StartLocation); + Assert.AreEqual(new TextLocation(1, 1), decl.StartLocation); 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); - Assert.AreEqual(new AstLocation(1, 1), decl.StartLocation); + Assert.AreEqual(new TextLocation(1, 1), decl.StartLocation); Assert.AreEqual("module", decl.AttributeTarget); } [Test] - public void TypeAttributeCSharp() + public void TypeAttribute() { string program = @"[type: System.Attribute()] class Test {}"; TypeDeclaration type = ParseUtilCSharp.ParseGlobal(program); AttributeSection decl = type.Attributes.Single(); - Assert.AreEqual(new AstLocation(1, 1), decl.StartLocation); + Assert.AreEqual(new TextLocation(1, 1), decl.StartLocation); Assert.AreEqual("type", decl.AttributeTarget); } - [Test, Ignore("Parser doesn't support attributes on type parameters")] + [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] public void AttributesOnTypeParameter() { ParseUtilCSharp.AssertGlobal( @@ -138,5 +147,28 @@ public class Form1 { } // TODO: Tests for other contexts where attributes can appear + + [Test] + public void AttributeWithNamedArguments() + { + ParseUtilCSharp.AssertTypeMember( + @"[A(0, a:1, b=2)] class Test {}", + new TypeDeclaration { + Name = "Test", + Attributes = { + new AttributeSection { + Attributes = { + new Attribute { + Type = new SimpleType("A"), + Arguments = { + new PrimitiveExpression(0), + new NamedArgumentExpression("a", new PrimitiveExpression(1)), + new NamedExpression("b", new PrimitiveExpression(2)) + } + } + } + } + }}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs index b41c5e569..df0e5135a 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/DelegateDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/NamespaceDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/NamespaceDeclarationTests.cs index bec573270..780087e4b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/NamespaceDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/NamespaceDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs index 2c123a5dd..9893f9ef8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/TypeDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; @@ -29,7 +44,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.GeneralScope TypeDeclaration td = ParseUtilCSharp.ParseGlobal(program); Assert.AreEqual(1, td.StartLocation.Line, "StartLocation.Y"); Assert.AreEqual(1, td.StartLocation.Column, "StartLocation.X"); - AstLocation bodyStartLocation = td.GetChildByRole(AstNode.Roles.LBrace).PrevSibling.EndLocation; + TextLocation bodyStartLocation = td.GetChildByRole(AstNode.Roles.LBrace).PrevSibling.EndLocation; Assert.AreEqual(1, bodyStartLocation.Line, "BodyStartLocation.Y"); Assert.AreEqual(14, bodyStartLocation.Column, "BodyStartLocation.X"); Assert.AreEqual(3, td.EndLocation.Line, "EndLocation.Y"); diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs index e5a82c3ea..81ea199ad 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/GeneralScope/UsingDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs new file mode 100644 index 000000000..924a3ebba --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseSelfTests.cs @@ -0,0 +1,149 @@ +// 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.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 (Path.Combine ("..", "..", "..")); + 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()); + if (parser.HasErrors) + continue; + this.currentFileName = fileName; + CheckPositionConsistency(cu); + CheckMissingTokens(cu); + } + } + + void PrintNode (AstNode node) + { + Console.WriteLine ("Parent:" + node.GetType ()); + Console.WriteLine ("Children:"); + foreach (var c in node.Children) + Console.WriteLine (c.GetType () +" at:"+ c.StartLocation +"-"+ c.EndLocation + " Role: "+ c.Role); + Console.WriteLine ("----"); + } + + void CheckPositionConsistency (AstNode node) + { + string comment = "(" + node.GetType ().Name + " at " + node.StartLocation + " in " + currentFileName + ")"; + var pred = node.StartLocation <= node.EndLocation; + if (!pred) + PrintNode (node); + Assert.IsTrue(pred, "StartLocation must be before EndLocation " + comment); + var prevNodeEnd = node.StartLocation; + var prevNode = node; + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + bool assertion = child.StartLocation >= prevNodeEnd; + if (!assertion) { + PrintNode (prevNode); + PrintNode (node); + + } + Assert.IsTrue(assertion, currentFileName + ": Child " + child.GetType () +" (" + child.StartLocation + ")" +" must start after previous sibling " + prevNode.GetType () + "(" + prevNode.StartLocation + ")"); + CheckPositionConsistency(child); + prevNodeEnd = child.EndLocation; + prevNode = child; + } + 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; + var prevNode = node; + for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { + CheckWhitespace(prevNode, prevNodeEnd, child, child.StartLocation); + CheckMissingTokens(child); + prevNode = child; + prevNodeEnd = child.EndLocation; + } + CheckWhitespace(prevNode, prevNodeEnd, node, node.EndLocation); + } + } + + void CheckWhitespace(AstNode startNode, TextLocation whitespaceStart, AstNode endNode, TextLocation whitespaceEnd) + { + if (whitespaceStart == whitespaceEnd || startNode == endNode) + return; + int start = currentDocument.GetOffset(whitespaceStart.Line, whitespaceStart.Column); + int end = currentDocument.GetOffset(whitespaceEnd.Line, whitespaceEnd.Column); + string text = currentDocument.GetText(start, end - start); + bool assertion = string.IsNullOrWhiteSpace(text); + if (!assertion) { + if (startNode.Parent != endNode.Parent) + PrintNode (startNode.Parent); + PrintNode (endNode.Parent); + } + Assert.IsTrue(assertion, "Expected whitespace between " + startNode.GetType () +":" + whitespaceStart + " and " + endNode.GetType () + ":" + whitespaceEnd + + ", but got '" + text + "' (in " + currentFileName + " parent:" + startNode.Parent.GetType () +")"); + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs index cef1f5652..c5068c989 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/ParseUtil.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -102,7 +117,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser static string ToCSharp(AstNode node) { StringWriter w = new StringWriter(); - node.AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); + node.AcceptVisitor(new CSharpOutputVisitor(w, new CSharpFormattingOptions()), null); return w.ToString(); } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/BlockStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/BlockStatementTests.cs index 2aaa2c57b..7ea91f90e 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/BlockStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/BlockStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/CheckedStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/CheckedStatementTests.cs index 15628db47..463a09bc6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/CheckedStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/CheckedStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/EmptyStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/EmptyStatementTests.cs index b492b21ed..bcc94f6c6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/EmptyStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/EmptyStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ExpressionStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ExpressionStatementTests.cs index 9489deffc..079ba93a3 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ExpressionStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ExpressionStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs index 374bf760b..2ae7d105b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/FixedStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs index 44232de5a..985b334b8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ForStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/GotoStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/GotoStatementTests.cs index f5a882b0b..f7790d738 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/GotoStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/GotoStatementTests.cs @@ -1,6 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/IfElseStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/IfElseStatementTests.cs index e0daaba5f..fd72af4b1 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/IfElseStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/IfElseStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LabelStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LabelStatementTests.cs index 3ce3339fd..ca8cee19a 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LabelStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LabelStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LockStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LockStatementTests.cs index a85dc06c9..eec195517 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LockStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/LockStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ReturnStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ReturnStatementTests.cs index 3747198ee..88c6b3247 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ReturnStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ReturnStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/SwitchStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/SwitchStatementTests.cs index 0800ffb61..04fd2aeca 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/SwitchStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/SwitchStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ThrowStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ThrowStatementTests.cs index 4ec682f00..4adc65804 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ThrowStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/ThrowStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs index 5854bf904..61e9b2660 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/TryCatchStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UnsafeStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UnsafeStatementTests.cs index bdeed271f..c0db318dc 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UnsafeStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UnsafeStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UsingStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UsingStatementTests.cs index db377d078..5bb5956fe 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UsingStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/UsingStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/VariableDeclarationStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/VariableDeclarationStatementTests.cs index 74564a6bf..e11c186c0 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/VariableDeclarationStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/VariableDeclarationStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; @@ -203,5 +218,43 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Statements VariableDeclarationStatement lvd = ParseUtilCSharp.ParseStatement("DateTime?[] a;"); Assert.IsTrue(new VariableDeclarationStatement(new SimpleType("DateTime").MakeNullableType().MakeArrayType(), "a").IsMatch(lvd)); } + + [Test] + public void Global() + { + ParseUtilCSharp.AssertStatement( + "global::System.String a;", + new VariableDeclarationStatement { + Type = new MemberType { + Target = new MemberType { + Target = new SimpleType("global"), + IsDoubleColon = true, + MemberName = "System" + }, + IsDoubleColon = false, + MemberName = "String", + }, + Variables = { + new VariableInitializer("a") + } + }); + } + + [Test] + public void ArrayDeclarationWithInitializer() + { + ParseUtilCSharp.AssertStatement( + "int[] a = { 0 };", + new VariableDeclarationStatement { + Type = new PrimitiveType("int").MakeArrayType(), + Variables = { + new VariableInitializer { + Name = "a", + Initializer = new ArrayInitializerExpression { + Elements = { new PrimitiveExpression(0) } + } + } + }}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/WhileStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/WhileStatementTests.cs index 689eb0584..d04af5552 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/WhileStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/WhileStatementTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs index ae4d75d93..dc46ae5df 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/Statements/YieldStatementTests.cs @@ -1,6 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - +// 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 NUnit.Framework; @@ -13,7 +27,7 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.Statements [Test] public void YieldReturnStatementTest() { - YieldStatement yieldStmt = ParseUtilCSharp.ParseStatement("yield return \"Foo\";"); + YieldReturnStatement yieldStmt = ParseUtilCSharp.ParseStatement("yield return \"Foo\";"); PrimitiveExpression expr = (PrimitiveExpression)yieldStmt.Expression; Assert.AreEqual("Foo", expr.Value); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/ConstructorDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/ConstructorDeclarationTests.cs index 3d3124a39..deee960db 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/ConstructorDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/ConstructorDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/DestructorDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/DestructorDeclarationTests.cs index 25ba714f7..34ecaaf47 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/DestructorDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/DestructorDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs index 35c98a4a1..6ef545b31 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/EventDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs index 1ed04478b..ab851606a 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/FieldDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs index a324c51b1..55f75091f 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/IndexerDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs index c0a8ab3c3..5742b2425 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/MethodDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; @@ -313,8 +328,8 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers "}", true // expect errors ); Assert.AreEqual("A", md.Name); - Assert.AreEqual(new AstLocation(2, 1), md.Body.StartLocation); - Assert.AreEqual(new AstLocation(5, 2), md.Body.EndLocation); + Assert.AreEqual(new TextLocation(2, 1), md.Body.StartLocation); + Assert.AreEqual(new TextLocation(5, 2), md.Body.EndLocation); } [Test] @@ -340,5 +355,33 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers } }}); } + + [Test, Ignore("async/await not yet supported")] + public void AsyncMethod() + { + ParseUtilCSharp.AssertTypeMember( + "async void MyMethod() {}", + new MethodDeclaration { + Modifiers = Modifiers.Async, + ReturnType = new PrimitiveType("void"), + Name = "MyMethod", + Body = new BlockStatement() + }); + } + + [Test, Ignore("async/await not yet supported")] + public void AsyncAsyncAsync() + { + ParseUtilCSharp.AssertTypeMember( + "async async async(async async) {}", + new MethodDeclaration { + Modifiers = Modifiers.Async, + ReturnType = new SimpleType("async"), + Name = "async", + Body = new BlockStatement(), + Parameters = { + new ParameterDeclaration(new SimpleType("async"), "async") + }}); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs index 4956d374a..034b52549 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/OperatorDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs index a9d0711d4..bb9ce196b 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeMembers/PropertyDeclarationTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -59,12 +74,12 @@ namespace ICSharpCode.NRefactory.CSharp.Parser.TypeMembers CSharpParser parser = new CSharpParser(); CompilationUnit cu = parser.Parse(new StringReader(code)); PropertyDeclaration pd = (PropertyDeclaration)cu.Children.Single().GetChildByRole(TypeDeclaration.MemberRole); - Assert.AreEqual(new AstLocation(2, code.IndexOf("{\n\t\tget") - line2Pos + 1), pd.GetChildByRole(AstNode.Roles.LBrace).StartLocation); - Assert.AreEqual(new AstLocation(5, 3), pd.EndLocation); - Assert.AreEqual(new AstLocation(3, code.IndexOf("{ return") - line3Pos + 1), pd.Getter.Body.StartLocation); - Assert.AreEqual(new AstLocation(3, code.IndexOf("}\n\t\tset") + 1 - line3Pos + 1), pd.Getter.Body.EndLocation); - Assert.AreEqual(new AstLocation(4, code.IndexOf("{ f =") - line4Pos + 1), pd.Setter.Body.StartLocation); - Assert.AreEqual(new AstLocation(4, code.IndexOf("}\n\t}") + 1 - line4Pos + 1), pd.Setter.Body.EndLocation); + Assert.AreEqual(new TextLocation(2, code.IndexOf("{\n\t\tget") - line2Pos + 1), pd.GetChildByRole(AstNode.Roles.LBrace).StartLocation); + Assert.AreEqual(new TextLocation(5, 3), pd.EndLocation); + Assert.AreEqual(new TextLocation(3, code.IndexOf("{ return") - line3Pos + 1), pd.Getter.Body.StartLocation); + Assert.AreEqual(new TextLocation(3, code.IndexOf("}\n\t\tset") + 1 - line3Pos + 1), pd.Getter.Body.EndLocation); + Assert.AreEqual(new TextLocation(4, code.IndexOf("{ f =") - line4Pos + 1), pd.Setter.Body.StartLocation); + Assert.AreEqual(new TextLocation(4, code.IndexOf("}\n\t}") + 1 - line4Pos + 1), pd.Setter.Body.EndLocation); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs index 9606e3247..fa4c82ad6 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Parser/TypeSystemConvertVisitorTests.cs @@ -1,11 +1,26 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - +// 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.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; +using ICSharpCode.NRefactory.Utils; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Parser @@ -13,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"; @@ -26,11 +44,26 @@ namespace ICSharpCode.NRefactory.CSharp.Parser cu = parser.Parse(s); } - testCasePC = new SimpleProjectContent(); - TypeSystemConvertVisitor visitor = new TypeSystemConvertVisitor(testCasePC, fileName); - cu.AcceptVisitor(visitor, null); - ParsedFile parsedFile = visitor.ParsedFile; - ((SimpleProjectContent)testCasePC).UpdateProjectContent(null, parsedFile); + var testCasePC = new SimpleProjectContent(); + CSharpParsedFile parsedFile = new TypeSystemConvertVisitor(testCasePC, fileName).Convert(cu); + parsedFile.Freeze(); + testCasePC.UpdateProjectContent(null, parsedFile); + 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.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs new file mode 100644 index 000000000..b85b674dc --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Refactoring/TypeSystemAstBuilderTests.cs @@ -0,0 +1,212 @@ +// 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.Collections; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Refactoring +{ + [TestFixture] + public class TypeSystemAstBuilderTests + { + const string program = @" +using System; +using System.Collections.Generic; +using OtherNS; + +class Base { + public class Nested { } +} +class Derived : Base { } + +namespace NS { + using R = global::System.Reflection; + using L = List; + + class System { } +} +namespace OtherNS { + class Array { } +} +"; + + SimpleProjectContent pc; + ITypeResolveContext ctx; + ITypeDefinition baseClass, derivedClass, nestedClass, systemClass; + CSharpParsedFile parsedFile; + + [SetUp] + public void SetUp() + { + pc = new SimpleProjectContent(); + var cu = new CSharpParser().Parse(new StringReader(program)); + parsedFile = new TypeSystemConvertVisitor(pc, "program.cs").Convert(cu); + pc.UpdateProjectContent(null, parsedFile); + + ctx = new CompositeTypeResolveContext(new[] { pc, CecilLoaderTests.Mscorlib }); + + baseClass = pc.GetTypeDefinition(string.Empty, "Base", 1, StringComparer.Ordinal); + nestedClass = baseClass.NestedTypes.Single(); + derivedClass = pc.GetTypeDefinition(string.Empty, "Derived", 2, StringComparer.Ordinal); + systemClass = pc.GetTypeDefinition("NS", "System", 0, StringComparer.Ordinal); + } + + TypeSystemAstBuilder CreateBuilder(ITypeDefinition currentTypeDef = null) + { + return new TypeSystemAstBuilder( + new CSharpResolver(ctx) { + CurrentUsingScope = currentTypeDef != null ? parsedFile.GetUsingScope(currentTypeDef.Region.Begin) : parsedFile.RootUsingScope, + CurrentTypeDefinition = currentTypeDef + }); + } + + string TypeToString(ITypeReference type, ITypeDefinition currentTypeDef = null) + { + var builder = CreateBuilder(currentTypeDef); + IType resolvedType = type.Resolve(ctx); + AstType node = builder.ConvertType(resolvedType); + return node.ToString(); + } + + [Test] + public void PrimitiveVoid() + { + Assert.AreEqual("void", TypeToString(KnownTypeReference.Void)); + } + + [Test] + public void PrimitiveInt() + { + Assert.AreEqual("int", TypeToString(KnownTypeReference.Int32)); + } + + [Test] + public void PrimitiveDecimal() + { + Assert.AreEqual("decimal", TypeToString(KnownTypeReference.Decimal)); + } + + [Test] + public void SystemType() + { + Assert.AreEqual("Type", TypeToString(KnownTypeReference.Type)); + } + + [Test] + public void ListOfNSSystem() + { + var type = new ParameterizedType(ctx.GetTypeDefinition(typeof(List<>)), new[] { systemClass }); + Assert.AreEqual("List", TypeToString(type)); + Assert.AreEqual("List", TypeToString(type, systemClass)); + } + + [Test] + public void NonGenericIEnumerable() + { + Assert.AreEqual("System.Collections.IEnumerable", TypeToString(typeof(IEnumerable).ToTypeReference())); + } + + [Test] + public void NonGenericIEnumerableWithSystemNamespaceCollision() + { + Assert.AreEqual("global::System.Collections.IEnumerable", TypeToString(typeof(IEnumerable).ToTypeReference(), systemClass)); + } + + [Test] + public void AliasedNamespace() + { + var type = typeof(System.Reflection.Assembly).ToTypeReference(); + Assert.AreEqual("R.Assembly", TypeToString(type, systemClass)); + } + + [Test] + public void AliasedType() + { + var type = new ParameterizedTypeReference(ctx.GetTypeDefinition(typeof(List<>)), new[] { KnownTypeReference.Char }); + Assert.AreEqual("List", TypeToString(type)); + Assert.AreEqual("L", TypeToString(type, systemClass)); + } + + [Test] + public void UnboundType() + { + Assert.AreEqual("Base<>", TypeToString(baseClass)); + Assert.AreEqual("Base<>.Nested<>", TypeToString(nestedClass)); + } + + [Test] + public void NestedType() + { + var type = new ParameterizedTypeReference(nestedClass, new[] { KnownTypeReference.Char, KnownTypeReference.String }); + Assert.AreEqual("Base.Nested", TypeToString(type)); + Assert.AreEqual("Base.Nested", TypeToString(type, baseClass)); + Assert.AreEqual("Base.Nested", TypeToString(type, nestedClass)); + Assert.AreEqual("Base.Nested", TypeToString(type, derivedClass)); + } + + [Test] + public void NestedTypeInCurrentClass() + { + var type = new ParameterizedTypeReference(nestedClass, new[] { baseClass.TypeParameters[0], KnownTypeReference.String }); + Assert.AreEqual("Nested", TypeToString(type, baseClass)); + Assert.AreEqual("Nested", TypeToString(type, nestedClass)); + } + + [Test] + public void NestedTypeInDerivedClass() + { + var type1 = new ParameterizedTypeReference(nestedClass, new[] { derivedClass.TypeParameters[0], KnownTypeReference.String }); + Assert.AreEqual("Base.Nested", TypeToString(type1, derivedClass)); + + var type2 = new ParameterizedTypeReference(nestedClass, new[] { derivedClass.TypeParameters[1], KnownTypeReference.String }); + Assert.AreEqual("Nested", TypeToString(type2, derivedClass)); + } + + [Test] + public void MultidimensionalArray() + { + Assert.AreEqual("byte[][,]", TypeToString(typeof(byte[][,]).ToTypeReference())); + } + + [Test] + public void Pointer() + { + Assert.AreEqual("long*", TypeToString(typeof(long*).ToTypeReference())); + } + + [Test] + public void NullableType() + { + Assert.AreEqual("ulong?", TypeToString(typeof(ulong?).ToTypeReference())); + } + + [Test] + public void AmbiguousType() + { + Assert.AreEqual("System.Array", TypeToString(typeof(Array).ToTypeReference())); + Assert.AreEqual("OtherNS.Array", TypeToString(ctx.GetTypeDefinition("OtherNS", "Array", 0, StringComparer.Ordinal))); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs new file mode 100644 index 000000000..a3d45f6c0 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ArrayCreateTests.cs @@ -0,0 +1,116 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + [Ignore("Parser produces incorrect positions")] + public class ArrayCreateTests : ResolverTestBase + { + [Test] + public void SimpleArrayCreation() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new int[] { 42 }$; + } +} +"; + var result = Resolve(program); + Assert.AreEqual("System.Int32[]", result.Type.ReflectionName); + } + + [Test] + public void NestedArrayCreation() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new int[2][,][,,]$; + } +} +"; + var result = Resolve(program); + // a one-dimensional array of two-dimensional arrays of three-dimensional arrays + ArrayType a1 = (ArrayType)result.Type; + Assert.AreEqual(1, a1.Dimensions); + ArrayType a2 = (ArrayType)a1.ElementType; + Assert.AreEqual(2, a2.Dimensions); + ArrayType a3 = (ArrayType)a2.ElementType; + Assert.AreEqual(3, a3.Dimensions); + Assert.AreEqual("System.Int32", a3.ElementType.ReflectionName); + } + + [Test] + public void InferredType() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new [] { 1, 1L }$; + } +} +"; + var result = Resolve(program); + Assert.AreEqual("System.Int64[]", result.Type.ReflectionName); + } + + [Test] + public void InferredType2D() + { + string program = @"using System.Collections.Generic; +class A { + static void Main() { + var a = $new [,] { { 1 }, { 1L } }$; + } +} +"; + var result = Resolve(program); + Assert.AreEqual("System.Int64[,]", result.Type.ReflectionName); + } + + [Test] + public void ArrayInitializerExpression() + { + string program = @"using System.Collections.Generic; +class A { + int[] a = ${ 1 }$; +} +"; + var result = Resolve(program); + Assert.AreEqual("System.Int32[]", result.Type.ReflectionName); + } + + [Test] + public void ArrayInitializerExpression2D() + { + string program = @"using System.Collections.Generic; +class A { + int[,] a = ${ { 1 }, { 2 } }$; +} +"; + var result = Resolve(program); + Assert.AreEqual("System.Int32[,]", result.Type.ReflectionName); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs index bca436254..4ca571767 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/AttributeTests.cs @@ -1,7 +1,23 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; @@ -18,19 +34,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreEqual("System.Runtime", result.NamespaceName); } - [Test] + [Test, Ignore("Parser produces incorrect position (attribute position doesn't include empty arg list)")] public void AttributeWithShortName() { - string program = "using System; [$Obsolete$] class Test {}"; + string program = "using System; [$Obsolete$()] class Test {}"; TypeResolveResult result = Resolve(program); Assert.AreEqual("System.ObsoleteAttribute", result.Type.FullName); } - [Test] + [Test, Ignore("Parser produces incorrect position (attribute position doesn't include empty arg list)")] public void QualifiedAttributeWithShortName() { - string program = "using System; [$System.Obsolete$] class Test {}"; + string program = "using System; [$System.Obsolete$()] class Test {}"; TypeResolveResult result = Resolve(program); Assert.AreEqual("System.ObsoleteAttribute", result.Type.FullName); @@ -40,18 +56,27 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public void AttributeConstructor1() { string program = "using System; [$LoaderOptimization(3)$] class Test { }"; - var mrr = Resolve(program); + var mrr = Resolve(program); Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); - Assert.AreEqual("System.Byte", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName); + Assert.AreEqual("System.Byte", mrr.Member.Parameters[0].Type.Resolve(context).FullName); } [Test] public void AttributeConstructor2() { string program = "using System; [$LoaderOptimization(LoaderOptimization.NotSpecified)$] class Test { }"; - var mrr = Resolve(program); + var mrr = Resolve(program); Assert.AreEqual("System.LoaderOptimizationAttribute..ctor", mrr.Member.FullName); - Assert.AreEqual("System.LoaderOptimization", (mrr.Member as IMethod).Parameters[0].Type.Resolve(context).FullName); + Assert.AreEqual("System.LoaderOptimization", mrr.Member.Parameters[0].Type.Resolve(context).FullName); + } + + [Test] + public void AttributeWithoutArgumentListRefersToConstructor() + { + string program = "using System; [$Obsolete$] class Test {}"; + + var result = Resolve(program); + Assert.AreEqual("System.ObsoleteAttribute..ctor", result.Member.FullName); } [Test] @@ -62,7 +87,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public const AttributeTargets XXX = AttributeTargets.All; } "; - MemberResolveResult result = Resolve(program); + var result = Resolve(program); Assert.AreEqual("MyAttribute.XXX", result.Member.FullName); } @@ -74,7 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver enum E { A, B } } "; - MemberResolveResult result = Resolve(program); + var result = Resolve(program); Assert.AreEqual("MyNamespace.E.A", result.Member.FullName); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs index 250c2619e..3d0192e7d 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/BinaryOperatorTests.cs @@ -1,7 +1,23 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; @@ -16,11 +32,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void Multiplication() { - AssertType(typeof(int), resolver.ResolveBinaryOperator( - BinaryOperatorType.Multiply, MakeResult(typeof(int)), MakeResult(typeof(int)))); + TestOperator(MakeResult(typeof(int)), BinaryOperatorType.Multiply, MakeResult(typeof(int)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(int)); - AssertType(typeof(float), resolver.ResolveBinaryOperator( - BinaryOperatorType.Multiply, MakeResult(typeof(int)), MakeConstant(0.0f))); + TestOperator(MakeResult(typeof(int)), BinaryOperatorType.Multiply, MakeConstant(0.0f), + Conversion.ImplicitNumericConversion, Conversion.IdentityConversion, typeof(float)); AssertConstant(3.0f, resolver.ResolveBinaryOperator( BinaryOperatorType.Multiply, MakeConstant(1.5f), MakeConstant(2))); @@ -28,8 +44,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertConstant(6, resolver.ResolveBinaryOperator( BinaryOperatorType.Multiply, MakeConstant((byte)2), MakeConstant((byte)3))); - AssertType(typeof(long?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Multiply, MakeResult(typeof(uint?)), MakeResult(typeof(int?)))); + TestOperator(MakeResult(typeof(uint?)), BinaryOperatorType.Multiply, MakeResult(typeof(int?)), + Conversion.ImplicitNullableConversion, Conversion.ImplicitNullableConversion, typeof(long?)); AssertError(typeof(decimal), resolver.ResolveBinaryOperator( BinaryOperatorType.Multiply, MakeResult(typeof(float)), MakeResult(typeof(decimal)))); @@ -38,18 +54,12 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void Addition() { - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(short)), MakeResult(typeof(byte?)))); + TestOperator(MakeResult(typeof(short)), BinaryOperatorType.Add, MakeResult(typeof(byte?)), + Conversion.ImplicitNullableConversion, Conversion.ImplicitNullableConversion, typeof(int?)); AssertConstant(3.0, resolver.ResolveBinaryOperator( BinaryOperatorType.Add, MakeConstant(1.0f), MakeConstant(2.0))); - AssertConstant(StringComparison.Ordinal, resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeConstant(StringComparison.InvariantCulture), MakeConstant(2))); - - AssertConstant(StringComparison.OrdinalIgnoreCase, resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeConstant((short)3), MakeConstant(StringComparison.InvariantCulture))); - AssertConstant("Text", resolver.ResolveBinaryOperator( BinaryOperatorType.Add, MakeConstant("Te"), MakeConstant("xt"))); @@ -59,38 +69,76 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertError(typeof(ReflectionHelper.Null), resolver.ResolveBinaryOperator( BinaryOperatorType.Add, MakeConstant(null), MakeConstant(null))); - AssertType(typeof(Action), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + TestOperator(MakeResult(typeof(int?)), BinaryOperatorType.Add, MakeResult(typeof(uint?)), + Conversion.ImplicitNullableConversion, Conversion.ImplicitNullableConversion, typeof(long?)); - AssertType(typeof(Action), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + TestOperator(MakeResult(typeof(ushort?)), BinaryOperatorType.Add, MakeResult(typeof(ushort?)), + Conversion.ImplicitNullableConversion, Conversion.ImplicitNullableConversion, typeof(int?)); - Assert.IsTrue(resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(Action)), MakeResult(typeof(Action))).IsError); + TestOperator(MakeConstant(1), BinaryOperatorType.Add, MakeConstant(null), + Conversion.ImplicitNullableConversion, Conversion.NullLiteralConversion, typeof(int?)); + } + + [Test] + public void StringPlusNull() + { + ResolveResult left = MakeResult(typeof(string)); + var rr = (BinaryOperatorResolveResult)resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, left, MakeConstant(null)); + AssertType(typeof(string), rr); + Assert.AreSame(left, rr.Left); + Assert.AreEqual("System.String", rr.Right.Type.FullName); + Assert.IsTrue(rr.Right.IsCompileTimeConstant); + Assert.IsNull(rr.Right.ConstantValue); + } + + [Test] + public void DelegateAddition() + { + TestOperator(MakeResult(typeof(Action)), BinaryOperatorType.Add, MakeResult(typeof(Action)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(Action)); - AssertType(typeof(StringComparison?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(StringComparison?)), MakeResult(typeof(int)))); + TestOperator(MakeResult(typeof(Action)), BinaryOperatorType.Add, MakeResult(typeof(Action)), + Conversion.ImplicitReferenceConversion, Conversion.IdentityConversion, typeof(Action)); - AssertType(typeof(StringComparison?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(int?)), MakeResult(typeof(StringComparison)))); + TestOperator(MakeResult(typeof(Action)), BinaryOperatorType.Add, MakeResult(typeof(Action)), + Conversion.IdentityConversion, Conversion.ImplicitReferenceConversion, typeof(Action)); - AssertType(typeof(long?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(int?)), MakeResult(typeof(uint?)))); + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeResult(typeof(Action)), MakeResult(typeof(Action))).IsError); + } + + + [Test] + public void EnumAddition() + { + AssertConstant(StringComparison.Ordinal, resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant(StringComparison.InvariantCulture), MakeConstant(2))); - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(ushort?)), MakeResult(typeof(ushort?)))); + AssertConstant(StringComparison.OrdinalIgnoreCase, resolver.ResolveBinaryOperator( + BinaryOperatorType.Add, MakeConstant((short)3), MakeConstant(StringComparison.InvariantCulture))); - Assert.IsTrue(resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeConstant(null), MakeConstant(null)).IsError); + TestOperator(MakeResult(typeof(StringComparison?)), BinaryOperatorType.Add, MakeResult(typeof(int)), + Conversion.IdentityConversion, Conversion.ImplicitNullableConversion, typeof(StringComparison?)); - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeConstant(1), MakeConstant(null))); + TestOperator(MakeResult(typeof(StringComparison?)), BinaryOperatorType.Add, MakeResult(typeof(int?)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(StringComparison?)); - AssertType(typeof(int*), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(int*)), MakeConstant(1))); + TestOperator(MakeResult(typeof(int)), BinaryOperatorType.Add, MakeResult(typeof(StringComparison?)), + Conversion.ImplicitNullableConversion, Conversion.IdentityConversion, typeof(StringComparison?)); + + TestOperator(MakeResult(typeof(int?)), BinaryOperatorType.Add, MakeResult(typeof(StringComparison?)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(StringComparison?)); + } + + [Test] + public void PointerAddition() + { + TestOperator(MakeResult(typeof(int*)), BinaryOperatorType.Add, MakeConstant(1), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(int*)); - AssertType(typeof(byte*), resolver.ResolveBinaryOperator( - BinaryOperatorType.Add, MakeResult(typeof(long)), MakeResult(typeof(byte*)))); + TestOperator(MakeResult(typeof(long)), BinaryOperatorType.Add, MakeResult(typeof(byte*)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(byte*)); } [Test] @@ -109,44 +157,70 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void Subtraction() { - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(short)), MakeResult(typeof(byte?)))); + TestOperator(MakeResult(typeof(short)), BinaryOperatorType.Subtract, MakeResult(typeof(byte?)), + Conversion.ImplicitNullableConversion, Conversion.ImplicitNullableConversion, typeof(int?)); + + TestOperator(MakeResult(typeof(float)), BinaryOperatorType.Subtract, MakeResult(typeof(long)), + Conversion.IdentityConversion, Conversion.ImplicitNumericConversion, typeof(float)); AssertConstant(-1.0, resolver.ResolveBinaryOperator( BinaryOperatorType.Subtract, MakeConstant(1.0f), MakeConstant(2.0))); + Assert.IsTrue(resolver.ResolveBinaryOperator( + BinaryOperatorType.Subtract, MakeConstant("Te"), MakeConstant("xt")).IsError); + } + + [Test] + public void EnumSubtraction() + { AssertConstant(StringComparison.InvariantCulture, resolver.ResolveBinaryOperator( BinaryOperatorType.Subtract, MakeConstant(StringComparison.Ordinal), MakeConstant(2))); AssertConstant(3, resolver.ResolveBinaryOperator( BinaryOperatorType.Subtract, MakeConstant(StringComparison.OrdinalIgnoreCase), MakeConstant(StringComparison.InvariantCulture))); + TestOperator(MakeResult(typeof(StringComparison?)), BinaryOperatorType.Subtract, MakeResult(typeof(int)), + Conversion.IdentityConversion, Conversion.ImplicitNullableConversion, typeof(StringComparison?)); + + TestOperator(MakeResult(typeof(StringComparison?)), BinaryOperatorType.Subtract, MakeResult(typeof(StringComparison)), + Conversion.IdentityConversion, Conversion.ImplicitNullableConversion, typeof(int?)); + Assert.IsTrue(resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeConstant("Te"), MakeConstant("xt")).IsError); + BinaryOperatorType.Subtract, MakeResult(typeof(int?)), MakeResult(typeof(StringComparison))).IsError); + } + + [Test] + public void DelegateSubtraction() + { + TestOperator(MakeResult(typeof(Action)), BinaryOperatorType.Subtract, MakeResult(typeof(Action)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(Action)); - AssertType(typeof(Action), resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + TestOperator(MakeResult(typeof(Action)), BinaryOperatorType.Subtract, MakeResult(typeof(Action)), + Conversion.ImplicitReferenceConversion, Conversion.IdentityConversion, typeof(Action)); - AssertType(typeof(Action), resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(Action)), MakeResult(typeof(Action)))); + TestOperator(MakeResult(typeof(Action)), BinaryOperatorType.Subtract, MakeResult(typeof(Action)), + Conversion.IdentityConversion, Conversion.ImplicitReferenceConversion, typeof(Action)); Assert.IsTrue(resolver.ResolveBinaryOperator( BinaryOperatorType.Subtract, MakeResult(typeof(Action)), MakeResult(typeof(Action))).IsError); + } + + [Test] + public void PointerSubtraction() + { + TestOperator(MakeResult(typeof(int*)), BinaryOperatorType.Subtract, MakeConstant(1), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(int*)); - AssertType(typeof(StringComparison?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(StringComparison?)), MakeResult(typeof(int)))); - - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(StringComparison?)), MakeResult(typeof(StringComparison)))); + TestOperator(MakeResult(typeof(byte*)), BinaryOperatorType.Subtract, MakeResult(typeof(uint)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(byte*)); - Assert.IsTrue(resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(int?)), MakeResult(typeof(StringComparison))).IsError); + TestOperator(MakeResult(typeof(byte*)), BinaryOperatorType.Subtract, MakeResult(typeof(short)), + Conversion.IdentityConversion, Conversion.ImplicitNumericConversion, typeof(byte*)); - AssertType(typeof(byte*), resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(byte*)), MakeResult(typeof(uint)))); + TestOperator(MakeResult(typeof(byte*)), BinaryOperatorType.Subtract, MakeResult(typeof(byte*)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(long)); - AssertType(typeof(long), resolver.ResolveBinaryOperator( - BinaryOperatorType.Subtract, MakeResult(typeof(byte*)), MakeResult(typeof(byte*)))); + AssertError(typeof(long), resolver.ResolveBinaryOperator(BinaryOperatorType.Subtract, MakeResult(typeof(byte*)), MakeResult(typeof(int*)))); } [Test] @@ -158,18 +232,21 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertConstant(ulong.MaxValue >> 2, resolver.ResolveBinaryOperator( BinaryOperatorType.ShiftRight, MakeConstant(ulong.MaxValue), MakeConstant(2))); - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.ShiftLeft, MakeResult(typeof(ushort?)), MakeConstant(1))); + TestOperator(MakeResult(typeof(ushort?)), BinaryOperatorType.ShiftLeft, MakeConstant(1), + Conversion.ImplicitNullableConversion, Conversion.ImplicitNullableConversion, typeof(int?)); - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.ShiftLeft, MakeConstant(null), MakeConstant(1))); + TestOperator(MakeConstant(null), BinaryOperatorType.ShiftLeft, MakeConstant(1), + Conversion.NullLiteralConversion, Conversion.ImplicitNullableConversion, typeof(int?)); - AssertType(typeof(int?), resolver.ResolveBinaryOperator( - BinaryOperatorType.ShiftLeft, MakeConstant(null), MakeConstant(null))); + TestOperator(MakeResult(typeof(long)), BinaryOperatorType.ShiftLeft, MakeConstant(null), + Conversion.ImplicitNullableConversion, Conversion.NullLiteralConversion, typeof(long?)); + + TestOperator(MakeConstant(null), BinaryOperatorType.ShiftLeft, MakeConstant(null), + Conversion.NullLiteralConversion, Conversion.NullLiteralConversion, typeof(int?)); } [Test] - public void Equality() + public void ConstantEquality() { AssertConstant(true, resolver.ResolveBinaryOperator( BinaryOperatorType.Equality, MakeConstant(3), MakeConstant(3))); @@ -203,9 +280,19 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertConstant(false, resolver.ResolveBinaryOperator( BinaryOperatorType.Equality, MakeConstant(null), MakeConstant('a'))); + } + + [Test] + public void Equality() + { + TestOperator(MakeResult(typeof(int*)), BinaryOperatorType.Equality, MakeResult(typeof(uint*)), + Conversion.IdentityConversion, Conversion.IdentityConversion, typeof(bool)); - AssertType(typeof(bool), resolver.ResolveBinaryOperator( - BinaryOperatorType.Equality, MakeResult(typeof(int*)), MakeResult(typeof(uint*)))); + TestOperator(MakeResult(typeof(int)), BinaryOperatorType.Equality, MakeResult(typeof(int?)), + Conversion.ImplicitNullableConversion, Conversion.IdentityConversion, typeof(bool)); + + TestOperator(MakeResult(typeof(int)), BinaryOperatorType.Equality, MakeResult(typeof(float)), + Conversion.ImplicitNumericConversion, Conversion.IdentityConversion, typeof(bool)); } [Test] @@ -257,8 +344,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertConstant(false, resolver.ResolveBinaryOperator( BinaryOperatorType.Equality, MakeConstant(0), MakeConstant(StringComparison.Ordinal))); - AssertConstant(false, resolver.ResolveBinaryOperator( - BinaryOperatorType.Equality, MakeConstant(0), MakeConstant(StringComparison.Ordinal))); + AssertConstant(true, resolver.ResolveBinaryOperator( + BinaryOperatorType.Equality, MakeConstant(0), MakeConstant(StringComparison.CurrentCulture))); Assert.IsFalse(resolver.ResolveBinaryOperator( BinaryOperatorType.Equality, MakeConstant(StringComparison.Ordinal), MakeConstant(1)).IsCompileTimeConstant); @@ -389,7 +476,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver BinaryOperatorType.NullCoalescing, MakeResult(typeof(string)), MakeResult(typeof(dynamic)))); } - [Test, Ignore("user-defined operators not yet implemented")] + [Test] public void LiftedUserDefined() { AssertType(typeof(TimeSpan), resolver.ResolveBinaryOperator( @@ -402,7 +489,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver BinaryOperatorType.Subtract, MakeResult(typeof(DateTime?)), MakeResult(typeof(DateTime?)))); } - [Test, Ignore("user-defined operators not yet implemented")] + [Test] public void UserDefinedNeedsLiftingDueToImplicitConversion() { string program = @"struct S {} @@ -417,16 +504,23 @@ class Test { } } "; - MemberResolveResult trr = Resolve(program); - Assert.IsFalse(trr.IsError); - Assert.AreEqual("A.op_Addition", trr.Member.FullName); + var irr = Resolve(program); + Assert.IsFalse(irr.IsError); + Assert.IsTrue(irr.IsLiftedOperatorInvocation); + Assert.AreEqual("A.op_Addition", irr.Member.FullName); // even though we're calling the lifted operator, trr.Member should be the original operator method - Assert.AreEqual("S", trr.Member.ReturnType.Resolve(context).ReflectionName); - Assert.AreEqual("System.Nullable`1[[S]]", trr.Type.ReflectionName); + Assert.AreEqual("S", irr.Member.ReturnType.Resolve(context).ReflectionName); + Assert.AreEqual("System.Nullable`1[[S]]", irr.Type.ReflectionName); + + Conversion lhsConv = ((ConversionResolveResult)irr.Arguments[0]).Conversion; + Conversion rhsConv = ((ConversionResolveResult)irr.Arguments[1]).Conversion; + Assert.AreEqual(Conversion.ImplicitNullableConversion, lhsConv); + Assert.IsTrue(rhsConv.IsUserDefined); + Assert.AreEqual("A.op_Implicit", rhsConv.Method.FullName); } - [Test, Ignore("user-defined operators not yet implemented")] - public void ThereIsNoLiftedOperatorsForClasses() + [Test] + public void ThereAreNoLiftedOperatorsForClasses() { string program = @"struct S {} class A { @@ -440,10 +534,10 @@ class Test { } } "; - MemberResolveResult trr = Resolve(program); - Assert.IsTrue(trr.IsError); // cannot convert from A to S - Assert.AreEqual("A.op_Addition", trr.Member.FullName); - Assert.AreEqual("S", trr.Type.ReflectionName); + var irr = Resolve(program); + Assert.IsTrue(irr.IsError); // cannot convert from A to S + Assert.AreEqual("A.op_Addition", irr.Member.FullName); + Assert.AreEqual("S", irr.Type.ReflectionName); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs index a961a9b8c..2c4ea461c 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/CastTests.cs @@ -1,7 +1,24 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -12,13 +29,34 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class CastTests : ResolverTestBase { + void TestCast(Type targetType, ResolveResult input, Conversion expectedConversion) + { + IType type = targetType.ToTypeReference().Resolve(context); + ResolveResult rr = resolver.ResolveCast(type, input); + AssertType(targetType, rr); + Assert.AreEqual(typeof(ConversionResolveResult), rr.GetType()); + var crr = (ConversionResolveResult)rr; + Assert.AreEqual(expectedConversion, crr.Conversion, "ConversionResolveResult.Conversion"); + Assert.AreSame(input, crr.Input, "ConversionResolveResult.Input"); + } + [Test] public void SimpleCast() { - AssertType(typeof(int), resolver.ResolveCast(ResolveType(typeof(int)), MakeResult(typeof(float)))); - AssertType(typeof(string), resolver.ResolveCast(ResolveType(typeof(string)), MakeResult(typeof(object)))); - AssertType(typeof(byte), resolver.ResolveCast(ResolveType(typeof(byte)), MakeResult(typeof(dynamic)))); - AssertType(typeof(dynamic), resolver.ResolveCast(ResolveType(typeof(dynamic)), MakeResult(typeof(double)))); + TestCast(typeof(int), MakeResult(typeof(float)), Conversion.ExplicitNumericConversion); + TestCast(typeof(string), MakeResult(typeof(object)), Conversion.ExplicitReferenceConversion); + TestCast(typeof(byte), MakeResult(typeof(dynamic)), Conversion.ExplicitDynamicConversion); + TestCast(typeof(dynamic), MakeResult(typeof(double)), Conversion.BoxingConversion); + } + + [Test] + public void NullableCasts() + { + TestCast(typeof(int), MakeResult(typeof(int?)), Conversion.ExplicitNullableConversion); + TestCast(typeof(int?), MakeResult(typeof(int)), Conversion.ImplicitNullableConversion); + + TestCast(typeof(int?), MakeResult(typeof(long?)), Conversion.ExplicitNullableConversion); + TestCast(typeof(long?), MakeResult(typeof(int?)), Conversion.ImplicitNullableConversion); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs index d1178757e..8a4644aab 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConditionalOperatorTests.cs @@ -1,8 +1,24 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; +using ICSharpCode.NRefactory.Semantics; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -13,55 +29,94 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class ConditionalOperatorTests : ResolverTestBase { + void TestOperator(ResolveResult condition, ResolveResult trueExpr, ResolveResult falseExpr, + Conversion conditionConv, Conversion trueConv, Conversion falseConv, + Type expectedResultType) + { + var corr = (ConditionalOperatorResolveResult)resolver.ResolveConditional(condition, trueExpr, falseExpr); + AssertType(expectedResultType, corr); + AssertConversion(corr.Condition, condition, conditionConv, "Condition Conversion"); + AssertConversion(corr.True, trueExpr, trueConv, "True Conversion"); + AssertConversion(corr.False, falseExpr, falseConv, "False Conversion"); + } + [Test] public void PickMoreGeneralOfTheTypes() { - AssertType(typeof(object), resolver.ResolveConditional( - MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeResult(typeof(object)))); - AssertType(typeof(long), resolver.ResolveConditional( - MakeResult(typeof(bool)), MakeResult(typeof(int)), MakeResult(typeof(long)))); + TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeResult(typeof(object)), + Conversion.IdentityConversion, Conversion.ImplicitReferenceConversion, Conversion.IdentityConversion, + typeof(object)); + + TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(int)), MakeResult(typeof(long)), + Conversion.IdentityConversion, Conversion.ImplicitNumericConversion, Conversion.IdentityConversion, + typeof(long)); } [Test] - public void Null() + public void StringAndNull() { - AssertType(typeof(string), resolver.ResolveConditional( - MakeResult(typeof(bool)), MakeResult(typeof(string)), MakeConstant(null))); - AssertType(typeof(string), resolver.ResolveConditional( - MakeResult(typeof(bool)), MakeConstant(null), MakeResult(typeof(string)))); + ResolveResult condition = MakeResult(typeof(bool)); + ResolveResult trueExpr = MakeResult(typeof(string)); + var result = (ConditionalOperatorResolveResult)resolver.ResolveConditional( + condition, trueExpr, MakeConstant(null)); + AssertType(typeof(string), result); + AssertConversion(result.Condition, condition, Conversion.IdentityConversion, "Condition Conversion"); + AssertConversion(result.True, trueExpr, Conversion.IdentityConversion, "True Conversion"); + Assert.IsTrue(result.False.IsCompileTimeConstant); + Assert.IsNull(result.False.ConstantValue); + Assert.AreEqual("System.String", result.False.Type.FullName); + } + + [Test] + public void NullAndString() + { + ResolveResult condition = MakeResult(typeof(bool)); + ResolveResult falseExpr = MakeResult(typeof(string)); + var result = (ConditionalOperatorResolveResult)resolver.ResolveConditional( + condition, MakeConstant(null), falseExpr); + AssertType(typeof(string), result); + AssertConversion(result.Condition, condition, Conversion.IdentityConversion, "Condition Conversion"); + Assert.IsTrue(result.True.IsCompileTimeConstant); + Assert.IsNull(result.True.ConstantValue); + Assert.AreEqual("System.String", result.True.Type.FullName); + AssertConversion(result.False, falseExpr, Conversion.IdentityConversion, "False Conversion"); } [Test] public void DynamicInArguments() { - AssertType(typeof(dynamic), resolver.ResolveConditional( - MakeResult(typeof(bool)), MakeResult(typeof(dynamic)), MakeResult(typeof(double)))); + TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(dynamic)), MakeResult(typeof(double)), + Conversion.IdentityConversion, Conversion.IdentityConversion, Conversion.BoxingConversion, + typeof(dynamic)); - AssertType(typeof(dynamic), resolver.ResolveConditional( - MakeResult(typeof(bool)), MakeResult(typeof(double)), MakeResult(typeof(dynamic)))); + TestOperator(MakeResult(typeof(bool)), MakeResult(typeof(double)), MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, Conversion.BoxingConversion, Conversion.IdentityConversion, + typeof(dynamic)); } [Test] public void DynamicInCondition() { - AssertType(typeof(double), resolver.ResolveConditional( - MakeResult(typeof(dynamic)), MakeResult(typeof(float)), MakeResult(typeof(double)))); + TestOperator(MakeResult(typeof(dynamic)), MakeResult(typeof(float)), MakeResult(typeof(double)), + Conversion.ImplicitDynamicConversion, Conversion.ImplicitNumericConversion, Conversion.IdentityConversion, + typeof(double)); } [Test] public void AllDynamic() { - AssertType(typeof(dynamic), resolver.ResolveConditional( - MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)))); + TestOperator(MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)), MakeResult(typeof(dynamic)), + Conversion.ImplicitDynamicConversion, Conversion.IdentityConversion, Conversion.IdentityConversion, + typeof(dynamic)); } [Test] public void ListOfDynamicAndListOfObject() { - AssertError(typeof(List), resolver.ResolveConditional( + AssertError(typeof(List), resolver.ResolveConditional( MakeResult(typeof(bool)), MakeResult(typeof(List)), MakeResult(typeof(List)))); - AssertError(typeof(List), resolver.ResolveConditional( + AssertError(typeof(List), resolver.ResolveConditional( MakeResult(typeof(bool)), MakeResult(typeof(List)), MakeResult(typeof(List)))); } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs index f1d270398..e1986cdb3 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ConversionsTest.cs @@ -1,9 +1,26 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; using System.Collections.Generic; + +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; @@ -13,6 +30,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver // assign short names to the fake reflection types using Null = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Null; using dynamic = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.Dynamic; + using C = Conversion; [TestFixture] public unsafe class ConversionsTest @@ -20,179 +38,209 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver ITypeResolveContext ctx = CecilLoaderTests.Mscorlib; Conversions conversions = new Conversions(CecilLoaderTests.Mscorlib); - bool ImplicitConversion(Type from, Type to) + Conversion ImplicitConversion(Type from, Type to) { IType from2 = from.ToTypeReference().Resolve(ctx); IType to2 = to.ToTypeReference().Resolve(ctx); return conversions.ImplicitConversion(from2, to2); } + Conversion ExplicitConversion(Type from, Type to) + { + IType from2 = from.ToTypeReference().Resolve(ctx); + IType to2 = to.ToTypeReference().Resolve(ctx); + return conversions.ExplicitConversion(from2, to2); + } + [Test] public void IdentityConversions() { - Assert.IsTrue(ImplicitConversion(typeof(char), typeof(char))); - Assert.IsTrue(ImplicitConversion(typeof(string), typeof(string))); - Assert.IsTrue(ImplicitConversion(typeof(object), typeof(object))); - Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(char))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(char), typeof(char))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(string), typeof(string))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(object))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(bool), typeof(char))); - Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Dynamic, SharedTypes.Dynamic)); - Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.UnknownType, SharedTypes.UnknownType)); - Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, SharedTypes.Null)); + Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SharedTypes.Dynamic, SharedTypes.Dynamic)); + Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SharedTypes.UnknownType, SharedTypes.UnknownType)); + Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(SharedTypes.Null, SharedTypes.Null)); } [Test] public void DynamicIdentityConversions() { - Assert.IsTrue(ImplicitConversion(typeof(object), typeof(ReflectionHelper.Dynamic))); - Assert.IsTrue(ImplicitConversion(typeof(ReflectionHelper.Dynamic), typeof(object))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(object), typeof(ReflectionHelper.Dynamic))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(ReflectionHelper.Dynamic), typeof(object))); } [Test] public void ComplexDynamicIdentityConversions() { - Assert.IsTrue(ImplicitConversion(typeof(List), typeof(List))); - Assert.IsTrue(ImplicitConversion(typeof(List), typeof(List))); - Assert.IsFalse(ImplicitConversion(typeof(List), typeof(List))); - Assert.IsFalse(ImplicitConversion(typeof(List), typeof(List))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List), typeof(List))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List), typeof(List))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(List), typeof(List))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(List), typeof(List))); - Assert.IsTrue(ImplicitConversion(typeof(List[]>), typeof(List[]>))); - Assert.IsTrue(ImplicitConversion(typeof(List[]>), typeof(List[]>))); - Assert.IsFalse(ImplicitConversion(typeof(List[,]>), typeof(List[]>))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List[]>), typeof(List[]>))); + Assert.AreEqual(C.IdentityConversion, ImplicitConversion(typeof(List[]>), typeof(List[]>))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(List[,]>), typeof(List[]>))); } [Test] public void PrimitiveConversions() { - Assert.IsTrue(ImplicitConversion(typeof(char), typeof(ushort))); - Assert.IsFalse(ImplicitConversion(typeof(byte), typeof(char))); - Assert.IsTrue(ImplicitConversion(typeof(int), typeof(long))); - Assert.IsFalse(ImplicitConversion(typeof(long), typeof(int))); - Assert.IsTrue(ImplicitConversion(typeof(int), typeof(float))); - Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(float))); - Assert.IsTrue(ImplicitConversion(typeof(float), typeof(double))); - Assert.IsFalse(ImplicitConversion(typeof(float), typeof(decimal))); - Assert.IsTrue(ImplicitConversion(typeof(char), typeof(long))); - Assert.IsTrue(ImplicitConversion(typeof(uint), typeof(long))); + Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(char), typeof(ushort))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(byte), typeof(char))); + Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(int), typeof(long))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(long), typeof(int))); + Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(int), typeof(float))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(bool), typeof(float))); + Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(float), typeof(double))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(float), typeof(decimal))); + Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(char), typeof(long))); + Assert.AreEqual(C.ImplicitNumericConversion, ImplicitConversion(typeof(uint), typeof(long))); } [Test] public void NullableConversions() { - Assert.IsTrue(ImplicitConversion(typeof(char), typeof(ushort?))); - Assert.IsFalse(ImplicitConversion(typeof(byte), typeof(char?))); - Assert.IsTrue(ImplicitConversion(typeof(int), typeof(long?))); - Assert.IsFalse(ImplicitConversion(typeof(long), typeof(int?))); - Assert.IsTrue(ImplicitConversion(typeof(int), typeof(float?))); - Assert.IsFalse(ImplicitConversion(typeof(bool), typeof(float?))); - Assert.IsTrue(ImplicitConversion(typeof(float), typeof(double?))); - Assert.IsFalse(ImplicitConversion(typeof(float), typeof(decimal?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(char), typeof(ushort?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(byte), typeof(char?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(int), typeof(long?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(long), typeof(int?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(int), typeof(float?))); + Assert.AreEqual(C.None , ImplicitConversion(typeof(bool), typeof(float?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(float), typeof(double?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(float), typeof(decimal?))); } [Test] public void NullableConversions2() { - Assert.IsTrue(ImplicitConversion(typeof(char?), typeof(ushort?))); - Assert.IsFalse(ImplicitConversion(typeof(byte?), typeof(char?))); - Assert.IsTrue(ImplicitConversion(typeof(int?), typeof(long?))); - Assert.IsFalse(ImplicitConversion(typeof(long?), typeof(int?))); - Assert.IsTrue(ImplicitConversion(typeof(int?), typeof(float?))); - Assert.IsFalse(ImplicitConversion(typeof(bool?), typeof(float?))); - Assert.IsTrue(ImplicitConversion(typeof(float?), typeof(double?))); - Assert.IsFalse(ImplicitConversion(typeof(float?), typeof(decimal?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(char?), typeof(ushort?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(byte?), typeof(char?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(int?), typeof(long?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(long?), typeof(int?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(int?), typeof(float?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(bool?), typeof(float?))); + Assert.AreEqual(C.ImplicitNullableConversion, ImplicitConversion(typeof(float?), typeof(double?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(float?), typeof(decimal?))); } [Test] public void NullLiteralConversions() { - Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int?))); - Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(char?))); - Assert.IsFalse(ImplicitConversion(typeof(Null), typeof(int))); - Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(object))); - Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(dynamic))); - Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(string))); - Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int[]))); + Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(int?))); + Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(char?))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(Null), typeof(int))); + Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(object))); + Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(dynamic))); + Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(string))); + Assert.AreEqual(C.NullLiteralConversion, ImplicitConversion(typeof(Null), typeof(int[]))); } [Test] public void SimpleReferenceConversions() { - Assert.IsTrue(ImplicitConversion(typeof(string), typeof(object))); - Assert.IsTrue(ImplicitConversion(typeof(BitArray), typeof(ICollection))); - Assert.IsTrue(ImplicitConversion(typeof(IList), typeof(IEnumerable))); - Assert.IsFalse(ImplicitConversion(typeof(object), typeof(string))); - Assert.IsFalse(ImplicitConversion(typeof(ICollection), typeof(BitArray))); - Assert.IsFalse(ImplicitConversion(typeof(IEnumerable), typeof(IList))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string), typeof(object))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(BitArray), typeof(ICollection))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(IList), typeof(IEnumerable))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(object), typeof(string))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(ICollection), typeof(BitArray))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(IEnumerable), typeof(IList))); } [Test] public void SimpleDynamicConversions() { - Assert.IsTrue(ImplicitConversion(typeof(string), typeof(dynamic))); - Assert.IsTrue(ImplicitConversion(typeof(dynamic), typeof(string))); - Assert.IsTrue(ImplicitConversion(typeof(int), typeof(dynamic))); - Assert.IsTrue(ImplicitConversion(typeof(dynamic), typeof(int))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string), typeof(dynamic))); + Assert.AreEqual(C.ImplicitDynamicConversion, ImplicitConversion(typeof(dynamic), typeof(string))); + Assert.AreEqual(C.BoxingConversion, ImplicitConversion(typeof(int), typeof(dynamic))); + Assert.AreEqual(C.ImplicitDynamicConversion, ImplicitConversion(typeof(dynamic), typeof(int))); } [Test] public void ParameterizedTypeConversions() { - Assert.IsTrue(ImplicitConversion(typeof(List), typeof(ICollection))); - Assert.IsTrue(ImplicitConversion(typeof(IList), typeof(ICollection))); - Assert.IsFalse(ImplicitConversion(typeof(List), typeof(ICollection))); - Assert.IsFalse(ImplicitConversion(typeof(IList), typeof(ICollection))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(List), typeof(ICollection))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(IList), typeof(ICollection))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(List), typeof(ICollection))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(IList), typeof(ICollection))); } [Test] public void ArrayConversions() { - Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(object[]))); - Assert.IsTrue(ImplicitConversion(typeof(string[,]), typeof(object[,]))); - Assert.IsFalse(ImplicitConversion(typeof(string[]), typeof(object[,]))); - Assert.IsFalse(ImplicitConversion(typeof(object[]), typeof(string[]))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(object[]))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[,]), typeof(object[,]))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(string[]), typeof(object[,]))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(object[]), typeof(string[]))); - Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(IList))); - Assert.IsFalse(ImplicitConversion(typeof(string[,]), typeof(IList))); - Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(IList))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(IList))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(string[,]), typeof(IList))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(IList))); - Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(Array))); - Assert.IsTrue(ImplicitConversion(typeof(string[]), typeof(ICloneable))); - Assert.IsFalse(ImplicitConversion(typeof(Array), typeof(string[]))); - Assert.IsFalse(ImplicitConversion(typeof(object), typeof(object[]))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(Array))); + Assert.AreEqual(C.ImplicitReferenceConversion, ImplicitConversion(typeof(string[]), typeof(ICloneable))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(Array), typeof(string[]))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(object), typeof(object[]))); } [Test] public void VarianceConversions() { - Assert.IsTrue(ImplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.IsFalse(ImplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.IsTrue(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - Assert.IsFalse(ImplicitConversion(typeof(ICollection), typeof(ICollection))); + Assert.AreEqual(C.ImplicitReferenceConversion, + ImplicitConversion(typeof(List), typeof(IEnumerable))); + Assert.AreEqual(C.None, + ImplicitConversion(typeof(List), typeof(IEnumerable))); + Assert.AreEqual(C.ImplicitReferenceConversion, + ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); + Assert.AreEqual(C.None, + ImplicitConversion(typeof(ICollection), typeof(ICollection))); - Assert.IsTrue(ImplicitConversion(typeof(Comparer), typeof(IComparer))); - Assert.IsTrue(ImplicitConversion(typeof(Comparer), typeof(IComparer))); - Assert.IsFalse(ImplicitConversion(typeof(Comparer), typeof(Comparer))); + Assert.AreEqual(C.ImplicitReferenceConversion, + ImplicitConversion(typeof(Comparer), typeof(IComparer))); + Assert.AreEqual(C.ImplicitReferenceConversion, + ImplicitConversion(typeof(Comparer), typeof(IComparer))); + Assert.AreEqual(C.None, + ImplicitConversion(typeof(Comparer), typeof(Comparer))); - Assert.IsFalse(ImplicitConversion(typeof(List), typeof(IEnumerable))); - Assert.IsTrue(ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); + Assert.AreEqual(C.None, + ImplicitConversion(typeof(List), typeof(IEnumerable))); + Assert.AreEqual(C.ImplicitReferenceConversion, + ImplicitConversion(typeof(IEnumerable), typeof(IEnumerable))); - Assert.IsTrue(ImplicitConversion(typeof(Func), typeof(Func))); - Assert.IsTrue(ImplicitConversion(typeof(Func), typeof(Func))); - Assert.IsFalse(ImplicitConversion(typeof(Func), typeof(Func))); - Assert.IsFalse(ImplicitConversion(typeof(Func), typeof(Func))); + Assert.AreEqual(C.ImplicitReferenceConversion, + ImplicitConversion(typeof(Func), typeof(Func))); + Assert.AreEqual(C.ImplicitReferenceConversion, + ImplicitConversion(typeof(Func), typeof(Func))); + Assert.AreEqual(C.None, + ImplicitConversion(typeof(Func), typeof(Func))); + Assert.AreEqual(C.None, + ImplicitConversion(typeof(Func), typeof(Func))); + } + + [Test] + public void ImplicitPointerConversion() + { + Assert.AreEqual(C.ImplicitPointerConversion, ImplicitConversion(typeof(Null), typeof(int*))); + Assert.AreEqual(C.ImplicitPointerConversion, ImplicitConversion(typeof(int*), typeof(void*))); } [Test] - public void PointerConversion() + public void ExplicitPointerConversion() { - Assert.IsTrue(ImplicitConversion(typeof(Null), typeof(int*))); - Assert.IsTrue(ImplicitConversion(typeof(int*), typeof(void*))); + Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(int*), typeof(short))); + Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(short), typeof(void*))); + + Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(void*), typeof(int*))); + Assert.AreEqual(C.ExplicitPointerConversion, ExplicitConversion(typeof(long*), typeof(byte*))); } [Test] public void NoConversionFromPointerTypeToObject() { - Assert.IsFalse(ImplicitConversion(typeof(int*), typeof(object))); - Assert.IsFalse(ImplicitConversion(typeof(int*), typeof(dynamic))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(int*), typeof(object))); + Assert.AreEqual(C.None, ImplicitConversion(typeof(int*), typeof(dynamic))); } [Test] @@ -202,16 +250,16 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver DefaultTypeParameter t2 = new DefaultTypeParameter(EntityType.TypeDefinition, 1, "T2"); DefaultTypeParameter tm = new DefaultTypeParameter(EntityType.Method, 0, "TM"); - Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); - Assert.IsTrue(conversions.ImplicitConversion(t, t)); - Assert.IsFalse(conversions.ImplicitConversion(t2, t)); - Assert.IsFalse(conversions.ImplicitConversion(t, t2)); - Assert.IsFalse(conversions.ImplicitConversion(t, tm)); - Assert.IsFalse(conversions.ImplicitConversion(tm, t)); + Assert.AreEqual(C.IdentityConversion, conversions.ImplicitConversion(t, t)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t2, t)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, t2)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, tm)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(tm, t)); } [Test] @@ -220,10 +268,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.HasReferenceTypeConstraint = true; - Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.NullLiteralConversion, conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.AreEqual(C.ImplicitReferenceConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); } [Test] @@ -232,10 +280,10 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.HasValueTypeConstraint = true; - Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.AreEqual(C.BoxingConversion, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); } [Test] @@ -244,14 +292,20 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.Constraints.Add(ctx.GetTypeDefinition(typeof(StringComparer))); - Assert.IsTrue(conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); - Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(StringComparer)))); - Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IComparer)))); - Assert.IsFalse(conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); - Assert.IsTrue(conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); + Assert.AreEqual(C.NullLiteralConversion, + conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.AreEqual(C.ImplicitReferenceConversion, + conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.AreEqual(C.ImplicitReferenceConversion, + conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.ImplicitReferenceConversion, + conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(StringComparer)))); + Assert.AreEqual(C.ImplicitReferenceConversion, + conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IComparer)))); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); + Assert.AreEqual(C.ImplicitReferenceConversion, + conversions.ImplicitConversion(t, typeof(IComparer).ToTypeReference().Resolve(ctx))); } [Test] @@ -260,19 +314,26 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver DefaultTypeParameter t = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T"); t.Constraints.Add(ctx.GetTypeDefinition(typeof(IList))); - Assert.IsFalse(conversions.ImplicitConversion(SharedTypes.Null, t)); - Assert.IsTrue(conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); - Assert.IsTrue(conversions.ImplicitConversion(t, SharedTypes.Dynamic)); - Assert.IsFalse(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); - Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IList)))); - Assert.IsTrue(conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IEnumerable)))); + Assert.AreEqual(C.None, conversions.ImplicitConversion(SharedTypes.Null, t)); + Assert.AreEqual(C.BoxingConversion, + conversions.ImplicitConversion(t, KnownTypeReference.Object.Resolve(ctx))); + Assert.AreEqual(C.BoxingConversion, + conversions.ImplicitConversion(t, SharedTypes.Dynamic)); + Assert.AreEqual(C.None, conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(ValueType)))); + Assert.AreEqual(C.BoxingConversion, + conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IList)))); + Assert.AreEqual(C.BoxingConversion, + conversions.ImplicitConversion(t, ctx.GetTypeDefinition(typeof(IEnumerable)))); } [Test] public void UserDefinedImplicitConversion() { - Assert.IsTrue(ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset))); - Assert.IsFalse(ImplicitConversion(typeof(DateTimeOffset), typeof(DateTime))); + Conversion c = ImplicitConversion(typeof(DateTime), typeof(DateTimeOffset)); + Assert.IsTrue(c.IsImplicitConversion && c.IsUserDefined); + Assert.AreEqual("System.DateTimeOffset.op_Implicit", c.Method.FullName); + + Assert.AreEqual(C.None, ImplicitConversion(typeof(DateTimeOffset), typeof(DateTime))); } [Test] @@ -286,7 +347,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.IsFalse(ImplicitConversion(typeof(DateTime?), typeof(DateTimeOffset))); } - bool IntegerLiteralConversion(object value, Type to) + Conversion IntegerLiteralConversion(object value, Type to) { IType fromType = value.GetType().ToTypeReference().Resolve(ctx); ConstantResolveResult crr = new ConstantResolveResult(fromType, value); @@ -417,5 +478,24 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreEqual(2, BetterConversion(typeof(ushort?), typeof(long?), typeof(int?))); Assert.AreEqual(0, BetterConversion(typeof(sbyte), typeof(int?), typeof(uint?))); } + + [Test] + public void ExpansiveInheritance() + { + SimpleProjectContent pc = new SimpleProjectContent(); + DefaultTypeDefinition a = new DefaultTypeDefinition(pc, string.Empty, "A"); + DefaultTypeDefinition b = new DefaultTypeDefinition(pc, string.Empty, "B"); + // interface A + a.Kind = TypeKind.Interface; + a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "U") { Variance = VarianceModifier.Contravariant }); + // interface B : A>> { } + DefaultTypeParameter x = new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X"); + b.TypeParameters.Add(x); + b.BaseTypes.Add(new ParameterizedType(a, new[] { new ParameterizedType(a, new [] { new ParameterizedType(b, new [] { x }) } ) })); + + IType type1 = new ParameterizedType(b, new[] { KnownTypeReference.Double.Resolve(ctx) }); + IType type2 = new ParameterizedType(a, new [] { new ParameterizedType(b, new[] { KnownTypeReference.String.Resolve(ctx) }) }); + Assert.IsFalse(conversions.ImplicitConversion(type1, type2)); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs index 3a9f0a739..26fcec5e4 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ExtensionMethodTests.cs @@ -1,7 +1,23 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; @@ -33,31 +49,31 @@ namespace XN { } } "; - MemberResolveResult mrr; + InvocationResolveResult mrr; - mrr = Resolve(program.Replace("$", "$a.F(1)$")); + mrr = Resolve(program.Replace("$", "$a.F(1)$")); Assert.AreEqual("XN.XC.F", mrr.Member.FullName); - Assert.AreEqual("System.Int32", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); + Assert.AreEqual("System.Int32", mrr.Member.Parameters[1].Type.Resolve(context).FullName); - mrr = Resolve(program.Replace("$", "$a.F(\"text\")$")); + mrr = Resolve(program.Replace("$", "$a.F(\"text\")$")); Assert.AreEqual("XN.XC.F", mrr.Member.FullName); - Assert.AreEqual("System.String", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); + Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.Resolve(context).FullName); - mrr = Resolve(program.Replace("$", "$b.F(1)$")); + mrr = Resolve(program.Replace("$", "$b.F(1)$")); Assert.AreEqual("B.F", mrr.Member.FullName); - mrr = Resolve(program.Replace("$", "$b.F(\"text\")$")); + mrr = Resolve(program.Replace("$", "$b.F(\"text\")$")); Assert.AreEqual("XN.XC.F", mrr.Member.FullName); - Assert.AreEqual("System.String", ((IMethod)mrr.Member).Parameters[1].Type.Resolve(context).FullName); + Assert.AreEqual("System.String", mrr.Member.Parameters[1].Type.Resolve(context).FullName); - mrr = Resolve(program.Replace("$", "$c.F(1)$")); + mrr = Resolve(program.Replace("$", "$c.F(1)$")); Assert.AreEqual("C.F", mrr.Member.FullName); - mrr = Resolve(program.Replace("$", "$c.F(\"text\")$")); + mrr = Resolve(program.Replace("$", "$c.F(\"text\")$")); Assert.AreEqual("C.F", mrr.Member.FullName); } - [Test, Ignore("Anonymous methods not yet implemented")] + [Test] public void ExtensionMethodsTest2() { string program = @"using System; using System.Collections.Generic; @@ -72,18 +88,18 @@ public static class XC { public static IEnumerable Filter(this IEnumerable source, Predicate predicate) { throw new NotImplementedException(); } } "; - MemberResolveResult mrr; + CSharpInvocationResolveResult mrr; - mrr = Resolve(program.Replace("$", "$\"text\".ToInt32()$")); + mrr = Resolve(program.Replace("$", "$\"text\".ToInt32()$")); Assert.AreEqual("XC.ToInt32", mrr.Member.FullName); - mrr = Resolve(program.Replace("$", "$args.Slice(1, 2)$")); + mrr = Resolve(program.Replace("$", "$args.Slice(1, 2)$")); Assert.AreEqual("XC.Slice", mrr.Member.FullName); Assert.AreEqual("System.String[]", mrr.Type.ReflectionName); - mrr = Resolve(program.Replace("$", "$args.Filter(delegate { return true; })$")); + mrr = Resolve(program.Replace("$", "$args.Filter(delegate { return true; })$")); Assert.AreEqual("XC.Filter", mrr.Member.FullName); - Assert.AreEqual("System.Collections.Generic.IEnumerable{System.String}", mrr.Type.ReflectionName); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", mrr.Type.ReflectionName); } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs index b59b2941e..0382c3c13 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/InvocationTests.cs @@ -1,8 +1,26 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -10,8 +28,6 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class InvocationTests : ResolverTestBase { - // TODO: do we want to return the MemberResolveResult for the InvocationExpression, or only for it's target? - [Test] public void MethodCallTest() { @@ -25,7 +41,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } "; - MemberResolveResult result = Resolve(program); + InvocationResolveResult result = Resolve(program); Assert.AreEqual("A.TargetMethod", result.Member.FullName); Assert.AreEqual("System.Int32", result.Type.ReflectionName); } @@ -49,7 +65,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreSame(SharedTypes.UnknownType, result.Type); } - [Test, Ignore("Resolver returns the member from the base class, which is correct according to C# spec, but not what we want to show in tooltips")] + [Test] public void OverriddenMethodCall() { string program = @"class A { @@ -66,11 +82,11 @@ class B : A { } } "; - MemberResolveResult result = Resolve(program); + InvocationResolveResult result = Resolve(program); Assert.AreEqual("B.GetRandomNumber", result.Member.FullName); } - [Test, Ignore("Resolver returns the member from the base class, which is correct according to C# spec, but not what we want to show in tooltips")] + [Test] public void OverriddenMethodCall2() { string program = @"class A { @@ -82,12 +98,11 @@ class B : A { } class B : A { public override int GetRandomNumber(string b, A a) { - return 4; // chosen by fair dice roll. - // guaranteed to be random + return 4; } } "; - MemberResolveResult result = Resolve(program); + InvocationResolveResult result = Resolve(program); Assert.AreEqual("B.GetRandomNumber", result.Member.FullName); } @@ -104,7 +119,7 @@ class B : A { } } "; - MemberResolveResult result = Resolve(program); + InvocationResolveResult result = Resolve(program); Assert.AreEqual("A.TargetMethod", result.Member.FullName); Assert.AreEqual("System.Int32", result.Type.ReflectionName); } @@ -202,14 +217,14 @@ class Program { static void T(ref int y) {} }"; - MemberResolveResult mrr = Resolve(program, "T(a)"); - Assert.IsFalse(((IMethod)mrr.Member).Parameters[0].IsRef); + InvocationResolveResult mrr = Resolve(program.Replace("T(a)", "$T(a)$")); + Assert.IsFalse(mrr.Member.Parameters[0].IsRef); - mrr = Resolve(program, "T(ref a)"); - Assert.IsTrue(((IMethod)mrr.Member).Parameters[0].IsRef); + mrr = Resolve(program.Replace("T(ref a)", "$T(ref a)$")); + Assert.IsTrue(mrr.Member.Parameters[0].IsRef); } - [Test, Ignore("Grouping by declaring type not yet implemented")] + [Test] public void AddedOverload() { string program = @"class BaseClass { @@ -221,10 +236,25 @@ class Program { class DerivedClass : BaseClass { public void Test(object a) { } }"; - MemberResolveResult mrr = Resolve(program); + InvocationResolveResult mrr = Resolve(program); Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); } + [Test] + public void AddedOverloadOnInterface() + { + string program = @" +interface IBase { void Method(int a); } +interface IDerived { void Method(object a); } +class Test { + static void Main(IDerived d) { + $d.Method(3)$; + } +}"; + InvocationResolveResult mrr = Resolve(program); + Assert.AreEqual("IDerived.Method", mrr.Member.FullName); + } + [Test] public void AddedNonApplicableOverload() { @@ -237,14 +267,14 @@ class DerivedClass : BaseClass { class DerivedClass : BaseClass { public void Test(string a) { } }"; - MemberResolveResult mrr = Resolve(program); + InvocationResolveResult mrr = Resolve(program); Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); - mrr = Resolve(program.Replace("(3)", "(\"3\")")); + mrr = Resolve(program.Replace("(3)", "(\"3\")")); Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); } - [Test, Ignore("Grouping by declaring type not yet implemented")] + [Test] public void OverrideShadowed() { string program = @"using System; @@ -261,8 +291,189 @@ class DerivedClass : MiddleClass { public override void Test(int a) { } }"; - MemberResolveResult mrr = Resolve(program); + InvocationResolveResult mrr = Resolve(program); Assert.AreEqual("MiddleClass.Test", mrr.Member.FullName); } + + [Test] + public void SubstituteClassAndMethodTypeParametersAtOnce() + { + string program = @"class C { static void M(X a, T b) { $C.M(b, a)$; } }"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + + var m = (SpecializedMethod)rr.Member; + Assert.AreEqual("X", m.TypeArguments.Single().Name); + Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name); + Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name); + } + + [Test] + public void MemberHiddenOnOneAccessPath() + { + // If a member is hidden in any access path, it is hidden in all access paths + string program = @" +interface IBase { int F { get; } } +interface ILeft: IBase { new int F { get; } } +interface IRight: IBase { void G(); } +interface IDerived: ILeft, IRight {} +class A { + void Test(IDerived d) { var a = $d.F$; } +}"; + var rr = Resolve(program); + Assert.AreEqual("ILeft.F", rr.Member.FullName); + } + + [Test] + public void PropertyClashesWithMethod() + { + string program = @" +interface IList { int Count { get; set; } } +interface ICounter { void Count(int i); } +interface IListCounter: IList, ICounter {} +class A { + void Test(IListCounter x) { var a = $x.Count$; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("ICounter.Count", rr.Methods.Single().FullName); + } + + [Test] + public void OverloadAmbiguousWithMethodInTwoInterfaces() + { + string program = @" +interface ILeft { void Method(); } +interface IRight { void Method(); } +interface IBoth : ILeft, IRight {} +class A { + void Test(IBoth x) { $x.Method()$; } +}"; + var rr = Resolve(program); + Assert.IsTrue(rr.IsError); + Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, rr.OverloadResolutionErrors); + } + + [Test] + public void AddedOverloadInOneInterfaceAndBetterOverloadInOtherInterface1() + { + string program = @" +interface IBase { void Method(int x); } +interface ILeft : IBase { void Method(object x); } +interface IRight { void Method(int x); } +interface IBoth : ILeft, IRight {} +class A { + void Test(IBoth x) { $x.Method(1)$; } +}"; + // IBase.Method is "hidden" because ILeft.Method is also applicable, + // so IRight.Method is unambiguously the chosen overload. + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("IRight.Method", rr.Member.FullName); + } + + [Test] + public void AddedOverloadInOneInterfaceAndBetterOverloadInOtherInterface2() + { + // repeat the above test with Left/Right swapped to make sure we aren't order-sensitive + string program = @" +interface IBase { void Method(int x); } +interface ILeft : IBase { void Method(object x); } +interface IRight { void Method(int x); } +interface IBoth : IRight, ILeft {} +class A { + void Test(IBoth x) { $x.Method(1)$; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("IRight.Method", rr.Member.FullName); + } + + [Test] + public void AddedOverloadHidesCommonBaseMethod_Generic1() + { + string program = @" +interface IBase { + void Method(int x); +} +interface ILeft : IBase { void Method(object x); } +interface IRight : IBase { } +interface IBoth : ILeft, IRight {} +class A { + void Test(IBoth x) { $x.Method(1)$; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("ILeft.Method", rr.Member.FullName); + } + + [Test] + public void AddedOverloadHidesCommonBaseMethod_Generic2() + { + string program = @" +interface IBase { + void Method(int x); +} +interface ILeft : IBase { void Method(object x); } +interface IRight : IBase { } +interface IBoth : ILeft, IRight {} +class A { + void Test(IBoth x) { $x.Method(1)$; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("ILeft.Method", rr.Member.FullName); + } + + [Test] + public void AddedOverloadDoesNotHideCommonBaseMethodWithDifferentTypeArgument1() + { + string program = @" +interface IBase { + void Method(int x); +} +interface ILeft : IBase { void Method(object x); } +interface IRight : IBase { } +interface IBoth : IRight, ILeft {} +class A { + void Test(IBoth x) { $x.Method(1)$; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("IBase`1[[System.Int64]]", rr.Member.DeclaringType.ReflectionName); + } + + [Test] + public void AddedOverloadDoesNotHideCommonBaseMethodWithDifferentTypeArgument2() + { + string program = @" +interface IBase { + void Method(int x); +} +interface ILeft : IBase { void Method(object x); } +interface IRight : IBase { } +interface IBoth : IRight, ILeft {} +class A { + void Test(IBoth x) { $x.Method(1)$; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("IBase`1[[System.Int64]]", rr.Member.DeclaringType.ReflectionName); + } + + [Test] + public void AmbiguityBetweenMemberAndMethodIsNotAnError() + { + string program = @" +interface ILeft { void Method(object x); } +interface IRight { Action Method { get; } } +interface IBoth : ILeft, IRight {} +class A { + void Test(IBoth x) { $x.Method(null)$; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("ILeft.Method", rr.Member.FullName); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs index 4a2106704..c17e2cbde 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LambdaTests.cs @@ -1,12 +1,29 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver { - [TestFixture, Ignore("Lambdas not supported by resolver")] + [TestFixture] public class LambdaTests : ResolverTestBase { [Test] @@ -56,9 +73,9 @@ class SomeClass { Assert.AreEqual("System.String", lrr.Type.ReflectionName); } - #region Lambda In Initializer + #region Lambda In Array Initializer [Test] - public void LambdaInCollectionInitializerTest1() + public void LambdaInArrayInitializer1() { string program = @"using System; class TestClass { @@ -67,71 +84,127 @@ class TestClass { i => $i$.ToString() }; } -} -"; +}"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] - public void LambdaInCollectionInitializerTest2() + public void LambdaInArrayInitializer2() { - string program = @"using System; using System.Collections.Generic; + string program = @"using System; class TestClass { static void Main() { - a = new List> { + a = new Converter[] { i => $i$.ToString() }; } -} -"; +}"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] - public void LambdaInCollectionInitializerTest3() + public void LambdaInArrayInitializer3() { string program = @"using System; class TestClass { - static void Main() { - a = new Converter[] { - i => $i$.ToString() - }; - } -} -"; + Converter[] field = new Converter[] { + i => $i$.ToString() + }; +}"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] - public void LambdaInCollectionInitializerTest4() + public void LambdaInArrayInitializer4() { string program = @"using System; class TestClass { - Converter[] field = new Converter[] { + Converter[] field = { i => $i$.ToString() }; -} -"; +}"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } [Test] - public void LambdaInCollectionInitializerTest5() + public void LambdaIn2DArrayInitializer() { string program = @"using System; class TestClass { - Converter[] field = { - i => $i$.ToString() - }; -} -"; + static void Main() { + Converter[,] arr = { + { i => $i$.ToString() } + }; + } +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test, Ignore("Fails due to parser problem")] + public void LambdaInInferred2DArrayInitializer() + { + string program = @"using System; +class TestClass { + static void Main() { + var c = new [,] { { null, (Converter)null }, { a => $a$.ToString(), b => b.ToString() }}; + } +}"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } + #endregion + + #region Lambda In Collection Initializer + [Test] + public void LambdaInCollectionInitializer1() + { + string program = @"using System; using System.Collections.Generic; +class TestClass { + static void Main() { + a = new List> { + i => $i$.ToString() + }; + } +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInCollectionInitializer2() + { + string program = @"using System; using System.Collections.Generic; +class TestClass { + static void Main() { + a = new Dictionary, Converter> { + { i => $i$.ToString(), i => i.ToString() } + }; + } +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Char", lrr.Type.ReflectionName); + } + + [Test] + public void LambdaInCollectionInitializer3() + { + string program = @"using System; using System.Collections.Generic; +class TestClass { + static void Main() { + a = new Dictionary, Converter> { + { i => i.ToString(), $i$ => i.ToString() } + }; + } +}"; + var lrr = Resolve(program); + Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); + } + #endregion [Test] public void LambdaInObjectInitializerTest() @@ -146,12 +219,10 @@ class X { } class Helper { public Converter F; -} -"; +}"; var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } - #endregion [Test] public void LambdaExpressionInCastExpression() @@ -167,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() { @@ -176,7 +261,7 @@ static class TestClass { return i => $i$.ToString(); } }"; - var lrr = Resolve(program, "i"); + var lrr = Resolve(program); Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } @@ -275,6 +360,26 @@ class TestClass { Assert.AreEqual("System.Int32", lrr.Type.ReflectionName); } + [Test] + public void ConvertAllInGenericMethod() + { + string program = @"using System; +class TestClass { + static void Method(System.Collections.Generic.List list) { + $list.ConvertAll(x => (int)x)$; + } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + SpecializedMethod m = (SpecializedMethod)rr.Member; + Assert.AreEqual("System.Int32", m.TypeArguments[0].ReflectionName); + Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", m.Parameters[0].Type.Resolve(context).ReflectionName); + + var crr = (ConversionResolveResult)rr.Arguments[0]; + Assert.IsTrue(crr.Conversion.IsAnonymousFunctionConversion); + Assert.AreEqual("System.Converter`2[[``0],[System.Int32]]", crr.Type.ReflectionName); + } + /* TODO write test for this class A { diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs index 9f5f4eaef..f25973fc8 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LinqTests.cs @@ -1,17 +1,33 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver { - [TestFixture, Ignore("LINQ not yet implemented")] + [TestFixture] public class LinqTests : ResolverTestBase { [Test] - public void SimpleLinqTest() + public void SimpleLinq() { string program = @"using System; using System.Linq; class TestClass { @@ -36,7 +52,7 @@ class TestClass { } [Test] - public void LinqGroupTest() + public void Group() { string program = @"using System; using System.Linq; class TestClass { @@ -56,7 +72,7 @@ class TestClass { } [Test] - public void LinqQueryableGroupTest() + public void QueryableGroup() { string program = @"using System; using System.Linq; class TestClass { @@ -76,7 +92,7 @@ class TestClass { } [Test] - public void ParenthesizedLinqTest() + public void Parenthesized() { string program = @"using System; using System.Linq; class TestClass { @@ -85,13 +101,14 @@ class TestClass { } } "; - ResolveResult rr = Resolve(program); + var rr = Resolve(program); + Assert.AreEqual("System.Linq.Enumerable.Select", rr.Member.FullName); Assert.AreEqual("System.Collections.Generic.IEnumerable", rr.Type.FullName); Assert.AreEqual("System.Int32", ((ParameterizedType)rr.Type).TypeArguments[0].FullName); } [Test] - public void LinqSelectReturnTypeTest() + public void SelectReturnType() { string program = @"using System; class TestClass { static void M() { @@ -100,12 +117,13 @@ class TestClass { static void M() { class XYZ { public int Select(Func f) { return 42; } }"; - ResolveResult rr = Resolve(program); + var rr = Resolve(program); + Assert.AreEqual("XYZ.Select", rr.Member.FullName); Assert.AreEqual("System.Int32", rr.Type.FullName); } [Test] - public void LinqQueryContinuationTest() + public void Continuation() { string program = @"using System; using System.Linq; class TestClass { @@ -132,5 +150,188 @@ class TestClass { lrr = Resolve(program.Replace("r.ToString", "$r$.ToString")); Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.Int32]]", lrr.Type.ReflectionName); } + + [Test] + public void OrderingWithSelectCall() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $var$ r = from x in input + orderby x.Length + select x + x; + } +} +"; + TypeResolveResult rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName); + } + + [Test] + public void OrderingWithoutSelectCall() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $var$ r = from x in input + orderby x.Length + select x; + } +} +"; + TypeResolveResult rr = Resolve(program); + Assert.AreEqual("System.Linq.IOrderedEnumerable`1[[System.String]]", rr.Type.ReflectionName); + } + + [Test] + public void OrderingWithSelectCallDueToSecondRangeVariable1() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $var$ r = from x in input + from y in input + orderby x.Length + select x; + } +} +"; + TypeResolveResult rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName); + } + + [Test] + public void OrderingWithSelectCallDueToSecondRangeVariable2() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $var$ r = from x in input + join y in input on x equals y + orderby x.Length + select x; + } +} +"; + TypeResolveResult rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName); + } + + [Test] + public void OrderingWithSelectCallDueToSecondRangeVariable3() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $var$ r = from x in input + join y in input on x equals y into g + orderby x.Length + select x; + } +} +"; + TypeResolveResult rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName); + } + + [Test] + public void OrderingWithSelectCallDueToSecondRangeVariable4() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $var$ r = from x in input + let y = x + orderby x.Length + select x; + } +} +"; + TypeResolveResult rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName); + } + + [Test] + public void DegenerateQuery() + { + string program = @"using System; using System.Linq; +class TestClass { + void Test(string[] input) { + $var$ r = from x in input select x; + } +} +"; + TypeResolveResult rr = Resolve(program); + Assert.AreEqual("System.Collections.Generic.IEnumerable`1[[System.String]]", rr.Type.ReflectionName); + } + + [Test, Ignore("Parser bug (incorrect position), but also resolver bug (handles Select as a separate call when it's combined into the GroupJoin)")] + public void GroupJoinWithCustomMethod() + { + string program = @"using System; +using System.Collections.Generic; +class TestClass { static void M(long [] args) { + var q = (from a in new XYZ() join b in args on a equals b into g select g); +}} +class XYZ { + public XYZ GroupJoin(IEnumerable f, Func key1, Func key2, Func s) { return this; } + public int Select(Func f) { return 42; } +}"; + var local = Resolve(program.Replace("into g", "into $g$")); + Assert.AreEqual("System.Decimal", local.Type.FullName); + + local = Resolve(program.Replace("select g", "select $g$")); + Assert.AreEqual("System.Decimal", local.Type.FullName); + + var trr = Resolve(program.Replace("var", "$var$")); + Assert.AreEqual("XYZ", trr.Type.FullName); // because 'Select' is done as part of GroupJoin() + } + + [Test] + public void GroupJoinWithOverloadedCustomMethod() + { + string program = @"using System; +using System.Collections.Generic; +class TestClass +{ + static void M(string[] args) + { + var q = $(from a in new XYZ() join b in args on a equals b into g select g.ToUpper())$; + } +} +class XYZ +{ + public int GroupJoin(IEnumerable f, Func key1, Func key2, Func s) { return 0; } + public decimal GroupJoin(IEnumerable f, Func key1, Func key2, Func s) { return 0; } +}"; + var rr = Resolve(program); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("GroupJoin", rr.Member.Name); + Assert.AreEqual("System.Decimal", rr.Type.FullName); + + rr = Resolve(program.Replace("g.ToUpper()", "g.CompareTo(42)")); + Assert.IsFalse(rr.IsError); + Assert.AreEqual("GroupJoin", rr.Member.Name); + Assert.AreEqual("System.Int32", rr.Type.FullName); + } + + [Test] + public void GroupWithQueryContinuation() + { + string program = @"using System; using System.Linq; +class TestClass +{ + static void M(string[] args) + { + var query = + from w in ""one to three"".Split() + group w by w.Length into g + orderby g.Key descending + select new { g.Key, Count = g.Count(), Avg = g.Average ($w$ => w.Length) }; + } +}"; + var rr = Resolve(program); + Assert.AreEqual("System.String", rr.Type.FullName); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs index def97c563..16017e7e5 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/LocalTypeInferenceTests.cs @@ -1,7 +1,23 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs index f3836eaaf..6c477d851 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/NameLookupTests.cs @@ -1,11 +1,28 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver @@ -17,7 +34,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public void SimpleNameLookupWithoutContext() { // nothing should be found without specifying any UsingScope - however, the resolver also must not crash - resolver.UsingScope = null; + resolver.CurrentUsingScope = null; Assert.IsTrue(resolver.ResolveSimpleName("System", new IType[0]).IsError); } @@ -32,7 +49,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void NamespaceInParentNamespaceLookup() { - resolver.UsingScope = MakeUsingScope("System.Collections.Generic"); + resolver.CurrentUsingScope = MakeUsingScope("System.Collections.Generic"); NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("Text", new IType[0]); Assert.AreEqual("System.Text", nrr.NamespaceName); } @@ -87,7 +104,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public void AliasToImportedType2() { AddUsing("System"); - resolver.UsingScope = new UsingScope(resolver.UsingScope, "SomeNamespace"); + resolver.CurrentUsingScope = new UsingScope(resolver.CurrentUsingScope, "SomeNamespace"); AddUsingAlias("x", "String"); TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("x", new IType[0]); Assert.AreEqual("System.String", trr.Type.FullName); @@ -117,7 +134,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void FindClassInCurrentNamespace() { - resolver.UsingScope = MakeUsingScope("System.Collections"); + resolver.CurrentUsingScope = MakeUsingScope("System.Collections"); TypeResolveResult trr = (TypeResolveResult)resolver.ResolveSimpleName("String", new IType[0]); Assert.AreEqual("System.String", trr.Type.FullName); } @@ -125,7 +142,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void FindNeighborNamespace() { - resolver.UsingScope = MakeUsingScope("System.Collections"); + resolver.CurrentUsingScope = MakeUsingScope("System.Collections"); NamespaceResolveResult nrr = (NamespaceResolveResult)resolver.ResolveSimpleName("Text", new IType[0]); Assert.AreEqual("System.Text", nrr.NamespaceName); } @@ -133,7 +150,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void FindTypeParameters() { - resolver.UsingScope = MakeUsingScope("System.Collections.Generic"); + resolver.CurrentUsingScope = MakeUsingScope("System.Collections.Generic"); resolver.CurrentTypeDefinition = context.GetTypeDefinition(typeof(List<>)); resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.Single(m => m.Name == "ConvertAll"); @@ -191,27 +208,45 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreSame(SharedTypes.UnknownType, result.Type); } - [Test] - public void PropertyNameAmbiguousWithTypeName() - { - string program = @"class A { + const string propertyNameAmbiguousWithTypeNameProgram = @"class A { public Color Color { get; set; } void Method() { $ } } -class Color { public static readonly Color Empty = null; } +class Color { + public static readonly Color Empty = null; + public static int M() { } + public int M(int a) { } +} "; + + [Test] + public void PropertyNameAmbiguousWithTypeName() + { + string program = propertyNameAmbiguousWithTypeNameProgram; TypeResolveResult trr = Resolve(program.Replace("$", "$Color$ c;")); Assert.AreEqual("Color", trr.Type.Name); MemberResolveResult mrr = Resolve(program.Replace("$", "x = $Color$;")); Assert.AreEqual("Color", mrr.Member.Name); - + } + + [Test] + public void PropertyNameAmbiguousWithTypeName_MemberAccessOnAmbiguousIdentifier() + { + string program = propertyNameAmbiguousWithTypeNameProgram; Resolve(program.Replace("$", "$Color$ = Color.Empty;")); Resolve(program.Replace("$", "Color = $Color$.Empty;")); - Resolve(program.Replace("$", "x = $Color$.ToString();")); + } + + [Test] + public void PropertyNameAmbiguousWithTypeName_MethodInvocationOnAmbiguousIdentifier() + { + string program = propertyNameAmbiguousWithTypeNameProgram; + Resolve(program.Replace("$", "x = $Color$.M(1);")); + Resolve(program.Replace("$", "x = $Color$.M();")); } [Test] @@ -263,7 +298,7 @@ class Color { public static readonly Color Empty = null; } Assert.AreEqual("value", result.Variable.Name); } - [Test, Ignore("Anonymous methods not supported in resolver")] + [Test] public void AnonymousMethodParameters() { string program = @"using System; @@ -358,11 +393,11 @@ class TestClass { COL.ArrayList ff; } "; - TypeResolveResult type = Resolve(program, "COL.ArrayList"); + TypeResolveResult type = Resolve(program.Replace("COL.ArrayList", "$COL.ArrayList$")); Assert.IsNotNull(type, "COL.ArrayList should resolve to a type"); Assert.AreEqual("System.Collections.ArrayList", type.Type.FullName, "TypeResolveResult"); - MemberResolveResult member = Resolve(program, "ff"); + MemberResolveResult member = Resolve(program.Replace("ff", "$ff$")); Assert.AreEqual("System.Collections.ArrayList", member.Type.FullName, "the full type should be resolved"); } @@ -390,7 +425,7 @@ class TestClass { "; TypeResolveResult trr = Resolve(program.Replace("COL a", "$COL$ a")); Assert.AreEqual("System.Collections.ArrayList", trr.Type.FullName, "COL"); - ResolveResult rr = Resolve(program.Replace("new COL()", "$new COL()$")); + ResolveResult rr = Resolve(program.Replace("new COL()", "$new COL()$")); Assert.AreEqual("System.Collections.ArrayList", rr.Type.FullName, "a"); } @@ -463,7 +498,7 @@ namespace A.B { [Test] - public void InnerTypeResolve () + public void InnerTypeResolve1 () { string program = @"public class C { public class Inner { } } class TestClass { @@ -474,19 +509,23 @@ class TestClass { "; TypeResolveResult trr = Resolve(program); Assert.AreEqual("C.Inner", trr.Type.FullName); - - program = @"public class C { public class D { public class Inner { } }} + } + + [Test] + public void InnerTypeResolve2 () + { + string program = @"public class C { public class D { public class Inner { } }} class TestClass { void Test() { $C.D.Inner$ a; } } "; - trr = Resolve(program); + TypeResolveResult trr = Resolve(program); Assert.AreEqual("C.D.Inner", trr.Type.FullName); } - [Test, Ignore("parser is broken and produces IdentifierExpression instead of PrimitiveType")] + [Test] public void ShortMaxValueTest() { string program = @"using System; @@ -521,7 +560,7 @@ class TestClass { trr = Resolve(program.Replace("$", "$global::XX.XX$")); Assert.AreEqual("XX.XX", trr.Type.FullName); - MemberResolveResult mrr = Resolve(program.Replace("$", "$XX.Test()$")); + InvocationResolveResult mrr = Resolve(program.Replace("$", "$XX.Test()$")); Assert.AreEqual("XX.XX.Test", mrr.Member.FullName); } @@ -633,7 +672,7 @@ namespace A { class BaseClass { public static string Test() {} }"; - MemberResolveResult mrr = Resolve(program.Replace("$", "$BaseClass.Test()$")); + MemberResolveResult mrr = Resolve(program.Replace("$", "$BaseClass.Test()$")); Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); mrr = Resolve(program.Replace("$", "$Test$")); @@ -643,7 +682,7 @@ namespace A { Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); // returns BaseClass.Test because DerivedClass.Test is not invocable - mrr = Resolve(program.Replace("$", "$DerivedClass.Test()$")); + mrr = Resolve(program.Replace("$", "$DerivedClass.Test()$")); Assert.AreEqual("BaseClass.Test", mrr.Member.FullName); } @@ -730,7 +769,7 @@ namespace A { Assert.AreEqual("DerivedClass.Test", mrr.Member.FullName); } - [Test, Ignore("Resolver Bug")] + [Test] public void SD_1487() { string program = @"using System; @@ -744,12 +783,15 @@ class C1 { }"; MemberResolveResult mrr; mrr = Resolve(program.Replace("$", "$Field$")); + Assert.IsFalse(mrr.IsError); Assert.AreEqual("C1.Field", mrr.Member.FullName); mrr = Resolve(program.Replace("$", "$C1.Field$")); + Assert.IsFalse(mrr.IsError); Assert.AreEqual("C1.Field", mrr.Member.FullName); mrr = Resolve(program.Replace("$", "$C2.Field$")); + Assert.IsFalse(mrr.IsError); Assert.AreEqual("C1.Field", mrr.Member.FullName); } @@ -767,7 +809,7 @@ class Test { Assert.AreEqual("System.Int32", rr.Member.ReturnType.Resolve(context).FullName); } - [Test, Ignore("Resolver bug")] + [Test] public void MethodHidesEvent() { // see SD-1542 @@ -788,7 +830,7 @@ class Form { Assert.AreEqual("Test.KeyDown", mgrr.Methods.Single().FullName); } - [Test, Ignore("partial classes not yet supported")] + [Test] public void ProtectedMemberVisibleWhenBaseTypeReferenceIsInOtherPart() { string program = @"using System; @@ -805,5 +847,18 @@ class B var mrr = Resolve(program); Assert.AreEqual("B.x", mrr.Member.FullName); } + + [Test, Ignore("Parser produces incorrect positions")] + public void SubstituteClassAndMethodTypeParametersAtOnce() + { + string program = @"class C { static void M(X a, T b) { $C.M$(b, a); } }"; + var rr = Resolve(program); + Assert.AreEqual("X", rr.TypeArguments.Single().Name); + + var m = (SpecializedMethod)rr.Methods.Single(); + Assert.AreSame(rr.TypeArguments.Single(), m.TypeArguments.Single()); + Assert.AreEqual("T", m.Parameters[0].Type.Resolve(context).Name); + Assert.AreEqual("X", m.Parameters[1].Type.Resolve(context).Name); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs index d3a130212..95186ca45 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ObjectCreationTests.cs @@ -1,7 +1,23 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using NUnit.Framework; @@ -20,7 +36,7 @@ class A { } } "; - MemberResolveResult result = Resolve(program); + var result = Resolve(program); Assert.AreEqual("System.Collections.Generic.List..ctor", result.Member.FullName); Assert.AreEqual("System.Collections.Generic.List`1[[System.String]]", result.Type.ReflectionName); @@ -35,7 +51,7 @@ class A { } } "; - ResolveResult result = Resolve(program); + ResolveResult result = Resolve(program); Assert.AreSame(SharedTypes.UnknownType, result.Type); } @@ -67,21 +83,18 @@ class A { A(double dblVal) {} } "; - MemberResolveResult result = Resolve(program.Replace("$", "$new A()$")); - IMethod m = (IMethod)result.Member; - Assert.IsFalse(m.IsStatic, "new A() is static"); - Assert.AreEqual(0, m.Parameters.Count, "new A() parameter count"); + var result = Resolve(program.Replace("$", "$new A()$")); + Assert.IsFalse(result.Member.IsStatic, "new A() is static"); + Assert.AreEqual(0, result.Member.Parameters.Count, "new A() parameter count"); Assert.AreEqual("A", result.Type.FullName); - result = Resolve(program.Replace("$", "$new A(10)$")); - m = (IMethod)result.Member; - Assert.AreEqual(1, m.Parameters.Count, "new A(10) parameter count"); - Assert.AreEqual("intVal", m.Parameters[0].Name, "new A(10) parameter"); + result = Resolve(program.Replace("$", "$new A(10)$")); + Assert.AreEqual(1, result.Member.Parameters.Count, "new A(10) parameter count"); + Assert.AreEqual("intVal", result.Member.Parameters[0].Name, "new A(10) parameter"); - result = Resolve(program.Replace("$", "$new A(11.1)$")); - m = (IMethod)result.Member; - Assert.AreEqual(1, m.Parameters.Count, "new A(11.1) parameter count"); - Assert.AreEqual("dblVal", m.Parameters[0].Name, "new A(11.1) parameter"); + result = Resolve(program.Replace("$", "$new A(11.1)$")); + Assert.AreEqual(1, result.Member.Parameters.Count, "new A(11.1) parameter count"); + Assert.AreEqual("dblVal", result.Member.Parameters[0].Name, "new A(11.1) parameter"); } [Test] @@ -93,14 +106,12 @@ class A { } } "; - MemberResolveResult result = Resolve(program); - IMethod m = (IMethod)result.Member; - Assert.IsNotNull(m); + var result = Resolve(program); Assert.AreEqual("A", result.Type.ReflectionName); - Assert.AreEqual(0, m.Parameters.Count); + Assert.AreEqual(0, result.Member.Parameters.Count); } - [Test, Ignore("Not implemented")] + [Test, Ignore("Parser returns incorrect positions")] public void ChainedConstructorCall() { string program = @"using System; @@ -122,14 +133,69 @@ class C : B { {} } "; - MemberResolveResult mrr = Resolve(program, "base(b)"); + InvocationResolveResult mrr = Resolve(program.Replace("base(b)", "$base(b)$")); Assert.AreEqual("A..ctor", mrr.Member.FullName); - mrr = Resolve(program, "base(c)"); + mrr = Resolve(program.Replace("base(c)", "$base(c)$")); Assert.AreEqual("B..ctor", mrr.Member.FullName); - mrr = Resolve(program, "this(0)"); + mrr = Resolve(program.Replace("this(0)", "$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); + } + + [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.Tests/CSharp/Resolver/OverloadResolutionTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs index f1701156c..75620bf37 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/OverloadResolutionTests.cs @@ -1,8 +1,27 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Linq; +using System.Linq.Expressions; + +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; @@ -12,7 +31,8 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [TestFixture] public class OverloadResolutionTests { - readonly ITypeResolveContext context = CecilLoaderTests.Mscorlib; + readonly ITypeResolveContext context = new CompositeTypeResolveContext( + new[] { CecilLoaderTests.Mscorlib, CecilLoaderTests.SystemCore }); readonly DefaultTypeDefinition dummyClass = new DefaultTypeDefinition(CecilLoaderTests.Mscorlib, string.Empty, "DummyClass"); ResolveResult[] MakeArgumentList(params Type[] argumentTypes) @@ -181,5 +201,102 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreEqual(OverloadResolutionErrors.None, o.AddCandidate(m3)); Assert.AreSame(m3, o.BestCandidate); } + + /// + /// A lambda of the form "() => default(returnType)" + /// + class MockLambda : LambdaResolveResult + { + IType inferredReturnType; + List parameters = new List(); + + public MockLambda(IType returnType) + { + this.inferredReturnType = returnType; + } + + public override IList Parameters { + get { return parameters; } + } + + public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions) + { + return conversions.ImplicitConversion(inferredReturnType, returnType); + } + + public override bool IsImplicitlyTyped { + get { return false; } + } + + public override bool IsAnonymousMethod { + get { return false; } + } + + public override bool HasParameterList { + get { return true; } + } + + public override bool IsAsync { + get { return false; } + } + + public override IType GetInferredReturnType(IType[] parameterTypes) + { + return inferredReturnType; + } + } + + [Test] + public void BetterConversionByLambdaReturnValue() + { + var m1 = MakeMethod(typeof(Func)); + var m2 = MakeMethod(typeof(Func)); + + // M(() => default(byte)); + ResolveResult[] args = { + new MockLambda(KnownTypeReference.Byte.Resolve(context)) + }; + + OverloadResolution r = new OverloadResolution(context, args); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); + Assert.AreSame(m2, r.BestCandidate); + Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors); + } + + [Test] + public void BetterConversionByLambdaReturnValue_ExpressionTree() + { + var m1 = MakeMethod(typeof(Func)); + var m2 = MakeMethod(typeof(Expression>)); + + // M(() => default(byte)); + ResolveResult[] args = { + new MockLambda(KnownTypeReference.Byte.Resolve(context)) + }; + + OverloadResolution r = new OverloadResolution(context, args); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); + Assert.AreSame(m2, r.BestCandidate); + Assert.AreEqual(OverloadResolutionErrors.None, r.BestCandidateErrors); + } + + [Test] + public void Lambda_DelegateAndExpressionTreeOverloadsAreAmbiguous() + { + var m1 = MakeMethod(typeof(Func)); + var m2 = MakeMethod(typeof(Expression>)); + + // M(() => default(int)); + ResolveResult[] args = { + new MockLambda(KnownTypeReference.Int32.Resolve(context)) + }; + + OverloadResolution r = new OverloadResolution(context, args); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m1)); + Assert.AreEqual(OverloadResolutionErrors.None, r.AddCandidate(m2)); + Assert.AreEqual(OverloadResolutionErrors.AmbiguousMatch, r.BestCandidateErrors); + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs new file mode 100644 index 000000000..b6d6bae85 --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolveAtLocationTests.cs @@ -0,0 +1,121 @@ +// 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 ICSharpCode.NRefactory.Semantics; +using ICSharpCode.NRefactory.TypeSystem; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.CSharp.Resolver +{ + [TestFixture] + public class ResolveAtLocationTests : ResolverTestBase + { + [Test] + public void UsingDeclaration() + { + Assert.IsNull(ResolveAtLocation("usi$ng System;")); + } + + [Test] + public void UsingDeclarationNamespace() + { + var rr = ResolveAtLocation("using $System;"); + Assert.AreEqual("System", rr.NamespaceName); + } + + [Test] + public void CatchClauseVariable() + { + var rr = ResolveAtLocation("using System; public class A { void M() { try { } catch (Exception e$x) { } } }"); + Assert.AreEqual("ex", rr.Variable.Name); + Assert.AreEqual("System.Exception", rr.Type.FullName); + } + + [Test] + public void MethodInvocation() + { + var rr = ResolveAtLocation(@"using System; +class A { void M() { + Console.W$riteLine(1); +}}"); + Assert.AreEqual("System.Console.WriteLine", rr.Member.FullName); + Assert.AreEqual("System.Int32", rr.Member.Parameters[0].Type.Resolve(context).FullName); + } + + [Test] + public void ImplicitlyTypedVariable() + { + var rr = ResolveAtLocation(@"using System; +class A { void M() { + v$ar x = Environment.TickCount; +}}"); + Assert.AreEqual("System.Int32", rr.Type.FullName); + } + + [Test, Ignore("Parser returns incorrect positions")] + public void BaseCtorCall() + { + var rr = ResolveAtLocation(@"using System; +class A { public A() : ba$se() {} }"); + Assert.AreEqual("System.Object..ctor", rr.Member.FullName); + } + + [Test] + public void Field() + { + var rr = ResolveAtLocation("public class A { int te$st; }"); + Assert.AreEqual("test", rr.Member.Name); + } + + [Test] + public void Field1InLineWithTwoFields() + { + var rr = ResolveAtLocation("public class A { int te$st, test2; }"); + Assert.AreEqual("test", rr.Member.Name); + } + + [Test] + public void Field2InLineWithTwoFields() + { + var rr = ResolveAtLocation("public class A { int test, te$st2; }"); + Assert.AreEqual("test2", rr.Member.Name); + } + + [Test] + public void Event() + { + var rr = ResolveAtLocation("public class A { event EventHandler Te$st; }"); + Assert.AreEqual("Test", rr.Member.Name); + } + + [Test] + public void Event1InLineWithTwoEvents() + { + var rr = ResolveAtLocation("public class A { event EventHandler Te$st, Test2; }"); + Assert.AreEqual("Test", rr.Member.Name); + } + + [Test] + public void Event2InLineWithTwoEvents() + { + var rr = ResolveAtLocation("public class A { event EventHandler Test, Te$st2; }"); + Assert.AreEqual("Test2", rr.Member.Name); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs index e93bcce1b..2585e70ba 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/ResolverTestBase.cs @@ -1,12 +1,29 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using ICSharpCode.NRefactory.CSharp.Parser; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; @@ -27,9 +44,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver public virtual void SetUp() { project = new SimpleProjectContent(); - context = new CompositeTypeResolveContext(new [] { project, mscorlib }); + context = new CompositeTypeResolveContext(new [] { project, mscorlib, CecilLoaderTests.SystemCore }); resolver = new CSharpResolver(context); - resolver.UsingScope = MakeUsingScope(""); + resolver.CurrentUsingScope = MakeUsingScope(""); } protected UsingScope MakeUsingScope(string namespaceName) @@ -48,7 +65,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// protected void AddUsing(string namespaceName) { - resolver.UsingScope.Usings.Add(MakeReference(namespaceName)); + resolver.CurrentUsingScope.Usings.Add(MakeReference(namespaceName)); } /// @@ -56,15 +73,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver /// protected void AddUsingAlias(string alias, string target) { - resolver.UsingScope.UsingAliases.Add(new KeyValuePair(alias, MakeReference(target))); + resolver.CurrentUsingScope.UsingAliases.Add(new KeyValuePair(alias, MakeReference(target))); } protected ITypeOrNamespaceReference MakeReference(string namespaceName) { string[] nameParts = namespaceName.Split('.'); - ITypeOrNamespaceReference r = new SimpleTypeOrNamespaceReference(nameParts[0], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.UsingScope, true); + ITypeOrNamespaceReference r = new SimpleTypeOrNamespaceReference(nameParts[0], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.CurrentUsingScope, SimpleNameLookupMode.TypeInUsingDeclaration); for (int i = 1; i < nameParts.Length; i++) { - r = new MemberTypeOrNamespaceReference(r, nameParts[i], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.UsingScope); + r = new MemberTypeOrNamespaceReference(r, nameParts[i], new ITypeReference[0], resolver.CurrentTypeDefinition, resolver.CurrentUsingScope); } return r; } @@ -72,7 +89,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver protected IType ResolveType(Type type) { IType t = type.ToTypeReference().Resolve(context); - if (t == SharedTypes.UnknownType) + if (SharedTypes.UnknownType.Equals(t)) throw new InvalidOperationException("Could not resolve type"); return t; } @@ -82,7 +99,7 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver if (value == null) return new ConstantResolveResult(SharedTypes.Null, null); IType type = ResolveType(value.GetType()); - if (type.IsEnum()) + if (type.Kind == TypeKind.Enum) value = Convert.ChangeType(value, Enum.GetUnderlyingType(value.GetType())); return new ConstantResolveResult(type, value); } @@ -121,13 +138,46 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver Assert.AreEqual(expectedType.ToTypeReference().Resolve(context), rr.Type); } - IEnumerable FindDollarSigns(string code) + protected void TestOperator(UnaryOperatorType op, ResolveResult input, + Conversion expectedConversion, Type expectedResultType) + { + var rr = resolver.ResolveUnaryOperator(op, input); + AssertType(expectedResultType, rr); + Assert.AreEqual(typeof(UnaryOperatorResolveResult), rr.GetType()); + var uorr = (UnaryOperatorResolveResult)rr; + AssertConversion(uorr.Input, input, expectedConversion, "Conversion"); + } + + protected void TestOperator(ResolveResult lhs, BinaryOperatorType op, ResolveResult rhs, + Conversion expectedLeftConversion, Conversion expectedRightConversion, Type expectedResultType) + { + var rr = resolver.ResolveBinaryOperator(op, lhs, rhs); + AssertType(expectedResultType, rr); + Assert.AreEqual(typeof(BinaryOperatorResolveResult), rr.GetType()); + var borr = (BinaryOperatorResolveResult)rr; + AssertConversion(borr.Left, lhs, expectedLeftConversion, "Left conversion"); + AssertConversion(borr.Right, rhs, expectedRightConversion, "Right conversion"); + } + + protected void AssertConversion(ResolveResult conversionResult, ResolveResult expectedRR, Conversion expectedConversion, string text) + { + if (expectedConversion == Conversion.IdentityConversion) { + Assert.AreSame(expectedRR, conversionResult, "Expected no " + text); + } else { + ConversionResolveResult crr = conversionResult as ConversionResolveResult; + Assert.IsNotNull(crr, "Could not find ConversionResolveResult for " + text); + Assert.AreEqual(expectedConversion, crr.Conversion, text); + Assert.AreSame(expectedRR, crr.Input, "Input of " + text); + } + } + + IEnumerable FindDollarSigns(string code) { int line = 1; int col = 1; foreach (char c in code) { if (c == '$') { - yield return new AstLocation(line, col); + yield return new TextLocation(line, col); } else if (c == '\n') { line++; col = 1; @@ -141,15 +191,13 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { CompilationUnit cu = new CSharpParser().Parse(new StringReader(code.Replace("$", ""))); - AstLocation[] dollars = FindDollarSigns(code).ToArray(); + TextLocation[] dollars = FindDollarSigns(code).ToArray(); Assert.AreEqual(2, dollars.Length, "Expected 2 dollar signs marking start+end of desired node"); - UsingScope rootUsingScope = resolver.UsingScope; - while (rootUsingScope.Parent != null) - rootUsingScope = rootUsingScope.Parent; + SetUp(); - ParsedFile parsedFile = new ParsedFile("test.cs", rootUsingScope); - TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.UsingScope, null); + CSharpParsedFile parsedFile = new CSharpParsedFile("test.cs", resolver.CurrentUsingScope); + TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.CurrentUsingScope, null); cu.AcceptVisitor(convertVisitor, null); project.UpdateProjectContent(null, convertVisitor.ParsedFile); @@ -157,6 +205,9 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver cu.AcceptVisitor(fnv, null); Assert.IsNotNull(fnv.ResultNode, "Did not find DOM node at the specified location"); + Debug.WriteLine(new string('=', 70)); + Debug.WriteLine("Starting new resolver for " + fnv.ResultNode); + var navigator = new NodeListResolveVisitorNavigator(new[] { fnv.ResultNode }); ResolveResult rr; using (var context = this.context.Synchronize()) { @@ -165,28 +216,25 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver rr = rv.GetResolveResult(fnv.ResultNode); } Assert.IsNotNull(rr, "ResolveResult is null - did something go wrong while navigating to the target node?"); + Debug.WriteLine("ResolveResult is " + rr); return rr; } protected T Resolve(string code) where T : ResolveResult { ResolveResult rr = Resolve(code); - Assert.IsTrue(rr is T, "Resolve should be " + typeof(T).Name + ", but was " + (rr != null ? rr.GetType().Name : "null")); + Assert.IsNotNull(rr); + Assert.IsTrue(rr.GetType() == typeof(T), "Resolve should be " + typeof(T).Name + ", but was " + rr.GetType().Name); return (T)rr; } - protected T Resolve(string code, string exprToResolve) where T : ResolveResult - { - return Resolve(code.Replace(exprToResolve, "$" + exprToResolve + "$")); - } - sealed class FindNodeVisitor : DepthFirstAstVisitor { - readonly AstLocation start; - readonly AstLocation end; + readonly TextLocation start; + readonly TextLocation end; public AstNode ResultNode; - public FindNodeVisitor(AstLocation start, AstLocation end) + public FindNodeVisitor(TextLocation start, TextLocation end) { this.start = start; this.end = end; @@ -203,5 +251,31 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } } } + + protected ResolveResult ResolveAtLocation(string code) + { + CompilationUnit cu = new CSharpParser().Parse(new StringReader(code.Replace("$", ""))); + + TextLocation[] dollars = FindDollarSigns(code).ToArray(); + Assert.AreEqual(1, dollars.Length, "Expected 1 dollar signs marking the location"); + + SetUp(); + + CSharpParsedFile parsedFile = new CSharpParsedFile("test.cs", resolver.CurrentUsingScope); + TypeSystemConvertVisitor convertVisitor = new TypeSystemConvertVisitor(parsedFile, resolver.CurrentUsingScope, null); + cu.AcceptVisitor(convertVisitor, null); + project.UpdateProjectContent(null, convertVisitor.ParsedFile); + + ResolveResult rr = Resolver.ResolveAtLocation.Resolve(this.context, parsedFile, cu, dollars[0]); + return rr; + } + + protected T ResolveAtLocation(string code) where T : ResolveResult + { + ResolveResult rr = ResolveAtLocation(code); + Assert.IsNotNull(rr); + Assert.IsTrue(rr.GetType() == typeof(T), "Resolve should be " + typeof(T).Name + ", but was " + rr.GetType().Name); + return (T)rr; + } } } diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs index 21911d656..12bdcdfe2 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/TypeInferenceTests.cs @@ -1,11 +1,28 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; + +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; @@ -75,6 +92,164 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver } #endregion + #region Inference with Method Groups + [Test] + public void CannotInferFromMethodParameterTypes() + { + // static void M(Func f) {} + // M(int.Parse); // type inference fails + DefaultTypeParameter A = new DefaultTypeParameter(EntityType.Method, 0, "A"); + DefaultTypeParameter B = new DefaultTypeParameter(EntityType.Method, 1, "B"); + + ITypeDefinition declType = ctx.GetTypeDefinition(typeof(int)); + var methods = new MethodListWithDeclaringType(declType, declType.Methods.Where(m => m.Name == "Parse")); + var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "Parse", new[] { methods }, new IType[0]); + + bool success; + ti.InferTypeArguments(new [] { A, B }, new [] { argument }, + new [] { new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<,>)), new[] { A, B }) }, + out success); + Assert.IsFalse(success); + } + + [Test] + public void InferFromMethodReturnType() + { + // static void M(Func f) {} + // M(Console.ReadKey); // type inference produces ConsoleKeyInfo + + DefaultTypeParameter T = new DefaultTypeParameter(EntityType.Method, 0, "T"); + + ITypeDefinition declType = ctx.GetTypeDefinition(typeof(Console)); + var methods = new MethodListWithDeclaringType(declType, declType.Methods.Where(m => m.Name == "ReadKey")); + var argument = new MethodGroupResolveResult(new TypeResolveResult(declType), "ReadKey", new[] { methods }, new IType[0]); + + bool success; + Assert.AreEqual( + new [] { ctx.GetTypeDefinition(typeof(ConsoleKeyInfo)) }, + ti.InferTypeArguments(new [] { T }, new [] { argument }, + new [] { new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<>)), new[] { T }) }, + out success)); + Assert.IsTrue(success); + } + #endregion + + #region Inference with Lambda + #region MockImplicitLambda + sealed class MockImplicitLambda : LambdaResolveResult + { + IType[] expectedParameterTypes; + IType inferredReturnType; + IParameter[] parameters; + + public MockImplicitLambda(IType[] expectedParameterTypes, IType inferredReturnType) + { + this.expectedParameterTypes = expectedParameterTypes; + this.inferredReturnType = inferredReturnType; + this.parameters = new IParameter[expectedParameterTypes.Length]; + for (int i = 0; i < parameters.Length; i++) { + // UnknownType because this lambda is implicitly typed + parameters[i] = new DefaultParameter(SharedTypes.UnknownType, "X" + i); + } + } + + public override IList Parameters { + get { return parameters; } + } + + public override Conversion IsValid(IType[] parameterTypes, IType returnType, Conversions conversions) + { + Assert.AreEqual(expectedParameterTypes, parameterTypes); + return conversions.ImplicitConversion(inferredReturnType, returnType); + } + + public override bool IsImplicitlyTyped { + get { return true; } + } + + public override bool IsAnonymousMethod { + get { return false; } + } + + public override bool HasParameterList { + get { return true; } + } + + public override bool IsAsync { + get { return false; } + } + + public override IType GetInferredReturnType(IType[] parameterTypes) + { + Assert.AreEqual(expectedParameterTypes, parameterTypes, "Parameters types passed to " + this); + return inferredReturnType; + } + + public override string ToString() + { + return "[MockImplicitLambda (" + string.Join(", ", expectedParameterTypes) + ") => " + inferredReturnType + "]"; + } + } + #endregion + + [Test] + public void TestLambdaInference() + { + ITypeParameter[] typeParameters = { + new DefaultTypeParameter(EntityType.Method, 0, "X"), + new DefaultTypeParameter(EntityType.Method, 1, "Y"), + new DefaultTypeParameter(EntityType.Method, 2, "Z") + }; + IType[] parameterTypes = { + typeParameters[0], + new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<,>)), new[] { typeParameters[0], typeParameters[1] }), + new ParameterizedType(ctx.GetTypeDefinition(typeof(Func<,>)), new[] { typeParameters[1], typeParameters[2] }) + }; + // Signature: M(X x, Func y, Func z) {} + // Invocation: M(default(string), s => default(int), t => default(float)); + ResolveResult[] arguments = { + new ResolveResult(KnownTypeReference.String.Resolve(ctx)), + new MockImplicitLambda(new[] { KnownTypeReference.String.Resolve(ctx) }, KnownTypeReference.Int32.Resolve(ctx)), + new MockImplicitLambda(new[] { KnownTypeReference.Int32.Resolve(ctx) }, KnownTypeReference.Single.Resolve(ctx)) + }; + bool success; + Assert.AreEqual( + new [] { + KnownTypeReference.String.Resolve(ctx), + KnownTypeReference.Int32.Resolve(ctx), + KnownTypeReference.Single.Resolve(ctx) + }, + ti.InferTypeArguments(typeParameters, arguments, parameterTypes, out success)); + Assert.IsTrue(success); + } + + [Test] + public void ConvertAllLambdaInference() + { + ITypeParameter[] classTypeParameters = { new DefaultTypeParameter(EntityType.TypeDefinition, 0, "T") }; + ITypeParameter[] methodTypeParameters = { new DefaultTypeParameter(EntityType.Method, 0, "R") }; + + IType[] parameterTypes = { + new ParameterizedType(ctx.GetTypeDefinition(typeof(Converter<,>)), + new[] { classTypeParameters[0], methodTypeParameters[0] }) + }; + + // Signature: List.ConvertAll(Converter converter); + // Invocation: listOfString.ConvertAll(s => default(int)); + ResolveResult[] arguments = { + new MockImplicitLambda(new[] { KnownTypeReference.String.Resolve(ctx) }, KnownTypeReference.Int32.Resolve(ctx)) + }; + IType[] classTypeArguments = { + KnownTypeReference.String.Resolve(ctx) + }; + + bool success; + Assert.AreEqual( + new [] { KnownTypeReference.Int32.Resolve(ctx) }, + ti.InferTypeArguments(methodTypeParameters, arguments, parameterTypes, out success, classTypeArguments)); + } + #endregion + #region FindTypeInBounds IType[] FindAllTypesInBounds(IList lowerBounds, IList upperBounds = null) { diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs index 7793efc31..9ab041853 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnaryOperatorTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.TypeSystem; @@ -16,33 +31,59 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver [Test] public void TestAddressOf() { - AssertType(typeof(int*), resolver.ResolveUnaryOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(int)))); - AssertType(typeof(byte**), resolver.ResolveUnaryOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(byte*)))); - AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(dynamic)))); + TestOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(int)), + Conversion.IdentityConversion, typeof(int*)); + + TestOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(byte*)), + Conversion.IdentityConversion, typeof(byte**)); + + TestOperator(UnaryOperatorType.AddressOf, MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, typeof(dynamic)); } [Test] public void TestDereference() { - AssertType(typeof(int), resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(int*)))); - AssertType(typeof(long*), resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(long**)))); + TestOperator(UnaryOperatorType.Dereference, MakeResult(typeof(int*)), + Conversion.IdentityConversion, typeof(int)); + + TestOperator(UnaryOperatorType.Dereference, MakeResult(typeof(long**)), + Conversion.IdentityConversion, typeof(long*)); + Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(int))).IsError); - AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, MakeResult(typeof(dynamic)))); + + TestOperator(UnaryOperatorType.Dereference, MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, typeof(dynamic)); } [Test] public void TestIncrementDecrement() { - AssertType(typeof(byte), resolver.ResolveUnaryOperator(UnaryOperatorType.Increment, MakeResult(typeof(byte)))); - AssertType(typeof(ulong), resolver.ResolveUnaryOperator(UnaryOperatorType.Decrement, MakeResult(typeof(ulong)))); - AssertType(typeof(short?), resolver.ResolveUnaryOperator(UnaryOperatorType.PostDecrement, MakeResult(typeof(short?)))); - AssertType(typeof(TypeCode), resolver.ResolveUnaryOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(TypeCode)))); - AssertType(typeof(TypeCode?), resolver.ResolveUnaryOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(TypeCode?)))); - AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(dynamic)))); + TestOperator(UnaryOperatorType.Increment, MakeResult(typeof(byte)), + Conversion.IdentityConversion, typeof(byte)); + + TestOperator(UnaryOperatorType.Decrement, MakeResult(typeof(ulong)), + Conversion.IdentityConversion, typeof(ulong)); + + TestOperator(UnaryOperatorType.PostDecrement, MakeResult(typeof(short?)), + Conversion.IdentityConversion, typeof(short?)); + + TestOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(TypeCode)), + Conversion.IdentityConversion, typeof(TypeCode)); + + TestOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(TypeCode?)), + Conversion.IdentityConversion, typeof(TypeCode?)); + + TestOperator(UnaryOperatorType.PostIncrement, MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, typeof(dynamic)); + AssertError(typeof(object), resolver.ResolveUnaryOperator(UnaryOperatorType.Increment, MakeResult(typeof(object)))); - AssertType(typeof(int*), resolver.ResolveUnaryOperator(UnaryOperatorType.Increment, MakeResult(typeof(int*)))); - AssertType(typeof(uint*), resolver.ResolveUnaryOperator(UnaryOperatorType.PostDecrement, MakeResult(typeof(uint*)))); + TestOperator(UnaryOperatorType.Increment, MakeResult(typeof(int*)), + Conversion.IdentityConversion, typeof(int*)); + + TestOperator(UnaryOperatorType.PostDecrement, MakeResult(typeof(uint*)), + Conversion.IdentityConversion, typeof(uint*)); } [Test] @@ -58,8 +99,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertConstant(1L, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((long)1))); AssertConstant((ulong)1, resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeConstant((ulong)1))); - AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeResult(typeof(dynamic)))); - AssertType(typeof(int?), resolver.ResolveUnaryOperator(UnaryOperatorType.Plus, MakeResult(typeof(ushort?)))); + TestOperator(UnaryOperatorType.Plus, MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, typeof(dynamic)); + + TestOperator(UnaryOperatorType.Plus, MakeResult(typeof(ushort?)), + Conversion.ImplicitNullableConversion, typeof(int?)); } [Test] @@ -73,8 +117,11 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertConstant(1m, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant(-1m))); AssertConstant(-65, resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeConstant('A'))); - AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeResult(typeof(dynamic)))); - AssertType(typeof(long?), resolver.ResolveUnaryOperator(UnaryOperatorType.Minus, MakeResult(typeof(uint?)))); + TestOperator(UnaryOperatorType.Minus, MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, typeof(dynamic)); + + TestOperator(UnaryOperatorType.Minus, MakeResult(typeof(uint?)), + Conversion.ImplicitNullableConversion, typeof(long?)); } [Test] @@ -104,9 +151,17 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver AssertConstant(~(ulong)1, resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant((ulong)1))); Assert.IsTrue(resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeConstant(1.0)).IsError); - AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(dynamic)))); - AssertType(typeof(uint), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(uint)))); - AssertType(typeof(int?), resolver.ResolveUnaryOperator(UnaryOperatorType.BitNot, MakeResult(typeof(ushort?)))); + TestOperator(UnaryOperatorType.BitNot, MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, typeof(dynamic)); + + TestOperator(UnaryOperatorType.BitNot, MakeResult(typeof(uint)), + Conversion.IdentityConversion, typeof(uint)); + + TestOperator(UnaryOperatorType.BitNot, MakeResult(typeof(sbyte)), + Conversion.ImplicitNumericConversion, typeof(int)); + + TestOperator(UnaryOperatorType.BitNot, MakeResult(typeof(ushort?)), + Conversion.ImplicitNullableConversion, typeof(int?)); } [Test] @@ -114,9 +169,15 @@ namespace ICSharpCode.NRefactory.CSharp.Resolver { AssertConstant(true, resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeConstant(false))); AssertConstant(false, resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeConstant(true))); - AssertType(typeof(dynamic), resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(dynamic)))); - AssertType(typeof(bool), resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(bool)))); - AssertType(typeof(bool?), resolver.ResolveUnaryOperator(UnaryOperatorType.Not, MakeResult(typeof(bool?)))); + + TestOperator(UnaryOperatorType.Not, MakeResult(typeof(dynamic)), + Conversion.IdentityConversion, typeof(dynamic)); + + TestOperator(UnaryOperatorType.Not, MakeResult(typeof(bool)), + Conversion.IdentityConversion, typeof(bool)); + + TestOperator(UnaryOperatorType.Not, MakeResult(typeof(bool?)), + Conversion.IdentityConversion, typeof(bool?)); } [Test] diff --git a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs index a336cd23c..931c52fa4 100644 --- a/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs +++ b/ICSharpCode.NRefactory.Tests/CSharp/Resolver/UnsafeCodeTests.cs @@ -1,7 +1,23 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; using NUnit.Framework; namespace ICSharpCode.NRefactory.CSharp.Resolver diff --git a/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs b/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs new file mode 100644 index 000000000..cbe549f3a --- /dev/null +++ b/ICSharpCode.NRefactory.Tests/Documentation/IDStringTests.cs @@ -0,0 +1,335 @@ +// 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.Collections.Generic; +using System.IO; +using System.Linq; +using ICSharpCode.NRefactory.CSharp; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; +using NUnit.Framework; + +namespace ICSharpCode.NRefactory.Documentation +{ + [TestFixture] + public class IDStringTests + { + class IDStringTestProjectContent : SimpleProjectContent, IDocumentationProvider + { + public string GetDocumentation(IEntity entity) + { + // Note: there's no mscorlib in the context. + // These tests only use primitive types from mscorlib, so the full name is known + // without resolving them. + return IDStringProvider.GetIDString(entity, this); + } + } + + IDStringTestProjectContent pc; + + void Init(string program) + { + pc = new IDStringTestProjectContent(); + + var cu = new CSharpParser().Parse(new StringReader(program)); + var parsedFile = new TypeSystemConvertVisitor(pc, "program.cs").Convert(cu); + pc.UpdateProjectContent(null, parsedFile); + } + + ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount = 0) + { + return pc.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal); + } + + [Test] + public void TypeDefinitions() + { + string program = @" +enum Color { Red, Blue, Green } +namespace Acme +{ + interface IProcess {} + struct ValueType {} + class Widget: IProcess + { + public class NestedClass {} + + public interface IMenuItem {} + + public delegate void Del(int i); + + public enum Direction { North, South, East, West } + } + class MyList + { + class Helper {} + } +}"; + Init(program); + Assert.AreEqual("T:Color", GetTypeDefinition(string.Empty, "Color").Documentation); + Assert.AreEqual("T:Acme.IProcess", GetTypeDefinition("Acme", "IProcess").Documentation); + Assert.AreEqual("T:Acme.ValueType", GetTypeDefinition("Acme", "ValueType").Documentation); + + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("T:Acme.Widget", widget.Documentation); + Assert.AreEqual("T:Acme.Widget.NestedClass", widget.NestedTypes.Single(t => t.Name == "NestedClass").Documentation); + Assert.AreEqual("T:Acme.Widget.IMenuItem", widget.NestedTypes.Single(t => t.Name == "IMenuItem").Documentation); + Assert.AreEqual("T:Acme.Widget.Del", widget.NestedTypes.Single(t => t.Name == "Del").Documentation); + Assert.AreEqual("T:Acme.Widget.Direction", widget.NestedTypes.Single(t => t.Name == "Direction").Documentation); + Assert.AreEqual("T:Acme.MyList`1", GetTypeDefinition("Acme", "MyList", 1).Documentation); + Assert.AreEqual("T:Acme.MyList`1.Helper`2", GetTypeDefinition("Acme", "MyList", 1).NestedTypes.Single().Documentation); + } + + [Test] + public void Fields() + { + string program = @" +namespace Acme +{ + class Widget : IProcess + { + public class NestedClass + { + private int value; + } + + private string message; + private const double PI = 3.14159; + private unsafe float **ppValues; + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("F:Acme.Widget.NestedClass.value", widget.NestedTypes.Single().Fields.Single().Documentation); + Assert.AreEqual("F:Acme.Widget.message", widget.Fields.Single(f => f.Name == "message").Documentation); + Assert.AreEqual("F:Acme.Widget.PI", widget.Fields.Single(f => f.Name == "PI").Documentation); + Assert.AreEqual("F:Acme.Widget.ppValues", widget.Fields.Single(f => f.Name == "ppValues").Documentation); + } + + [Test] + public void Constructors() + { + string program = @" +namespace Acme +{ + class Widget: IProcess + { + static Widget() {} + public Widget() {} + public Widget(string s) {} + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("M:Acme.Widget.#cctor", widget.Methods.Single(m => m.IsStatic).Documentation); + Assert.AreEqual("M:Acme.Widget.#ctor", widget.Methods.Single(m => !m.IsStatic && m.Parameters.Count == 0).Documentation); + Assert.AreEqual("M:Acme.Widget.#ctor(System.String)", widget.Methods.Single(m => m.Parameters.Count == 1).Documentation); + } + + [Test] + public void Destructor() + { + string program = @" +namespace Acme +{ + class Widget: IProcess + { + ~Widget() { } + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("M:Acme.Widget.Finalize", widget.Methods.Single().Documentation); + } + + [Test] + public void Methods() + { + string program = @" +enum Color {} +namespace Acme +{ + struct ValueType { } + class Widget: IProcess + { + public class NestedClass + { + public void M(int i) {} + } + + public static void M0() {...} + public void M1(char c, out float f, ref ValueType v) {...} + public void M2(short[] x1, int[,] x2, long[][] x3) {...} + public void M3(long[][] x3, Widget[][,,] x4) {...} + public unsafe void M4(char *pc, Color **pf) {...} + public unsafe void M5(void *pv, double *[][,] pd) {...} + public void M6(int? i, params object[] args) {...} + } + + class MyList + { + public void Test(T t) { } + } + + class UseList + { + public void Process(MyList list) { } + public MyList GetValues(T inputValue) { return null; } + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("M:Acme.Widget.NestedClass.M(System.Int32)", widget.NestedTypes.Single().Methods.Single().Documentation); + Assert.AreEqual("M:Acme.Widget.M0", widget.Methods.Single(m => m.Name == "M0").Documentation); + Assert.AreEqual("M:Acme.Widget.M1(System.Char,System.Single@,Acme.ValueType@)", + widget.Methods.Single(m => m.Name == "M1").Documentation); + Assert.AreEqual("M:Acme.Widget.M2(System.Int16[],System.Int32[0:,0:],System.Int64[][])", + widget.Methods.Single(m => m.Name == "M2").Documentation); + Assert.AreEqual("M:Acme.Widget.M3(System.Int64[][],Acme.Widget[0:,0:,0:][])", + widget.Methods.Single(m => m.Name == "M3").Documentation); + Assert.AreEqual("M:Acme.Widget.M4(System.Char*,Color**)", + widget.Methods.Single(m => m.Name == "M4").Documentation); + Assert.AreEqual("M:Acme.Widget.M5(System.Void*,System.Double*[0:,0:][])", + widget.Methods.Single(m => m.Name == "M5").Documentation); + Assert.AreEqual("M:Acme.Widget.M6(System.Nullable{System.Int32},System.Object[])", + widget.Methods.Single(m => m.Name == "M6").Documentation); + + Assert.AreEqual("M:Acme.MyList`1.Test(`0)", + GetTypeDefinition("Acme", "MyList", 1).Methods.Single().Documentation); + + Assert.AreEqual("M:Acme.UseList.Process(Acme.MyList{Color})", + GetTypeDefinition("Acme", "UseList").Methods.Single(m => m.Name == "Process").Documentation); + Assert.AreEqual("M:Acme.UseList.GetValues``1(``0)", + GetTypeDefinition("Acme", "UseList").Methods.Single(m => m.Name == "GetValues").Documentation); + } + + [Test] + public void NestedGenerics() + { + Init("class A { class B { void M(A.B a) { } } }"); + ITypeDefinition b = GetTypeDefinition("", "A", 1).NestedTypes.Single(); + Assert.AreEqual("T:A`1.B`1", b.Documentation); + Assert.AreEqual("M:A`1.B`1.M(A{`1}.B{`0})", b.Methods.Single().Documentation); + } + + [Test] + public void Properties() + { + string program = @" +namespace Acme +{ + class Widget: IProcess + { + public int Width { get {...} set {...} } + public int this[int i] { get {...} set {...} } + public int this[string s, int i] { get {...} set {...} } + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("P:Acme.Widget.Width", widget.Properties.Single(p => p.Parameters.Count == 0).Documentation); + Assert.AreEqual("P:Acme.Widget.Item(System.Int32)", + widget.Properties.Single(p => p.Parameters.Count == 1).Documentation); + Assert.AreEqual("P:Acme.Widget.Item(System.String,System.Int32)", + widget.Properties.Single(p => p.Parameters.Count == 2).Documentation); + + } + + [Test] + public void Event() + { + string program = @" +namespace Acme +{ + class Widget: IProcess + { + public event Del AnEvent; + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("E:Acme.Widget.AnEvent", widget.Events.Single().Documentation); + + } + + [Test] + public void UnaryOperator() + { + string program = @" +namespace Acme +{ + class Widget: IProcess + { + public static Widget operator+(Widget x) { } + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("M:Acme.Widget.op_UnaryPlus(Acme.Widget)", widget.Methods.Single().Documentation); + } + + [Test] + public void BinaryOperator() + { + string program = @" +namespace Acme +{ + class Widget: IProcess + { + public static Widget operator+(Widget x1, Widget x2) { } + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("M:Acme.Widget.op_Addition(Acme.Widget,Acme.Widget)", widget.Methods.Single().Documentation); + } + + [Test] + public void ConversionOperator() + { + string program = @" +namespace Acme +{ + class Widget: IProcess + { + public static explicit operator int(Widget x) { } + public static implicit operator long(Widget x) { } + } +}"; + Init(program); + ITypeDefinition widget = GetTypeDefinition("Acme", "Widget"); + Assert.AreEqual("M:Acme.Widget.op_Explicit(Acme.Widget)~System.Int32", widget.Methods.First().Documentation); + Assert.AreEqual("M:Acme.Widget.op_Implicit(Acme.Widget)~System.Int64", widget.Methods.Last().Documentation); + } + + [Test] + public void CorlibIDStrings() + { + var list = CecilLoaderTests.Mscorlib.GetTypeDefinition(typeof(List<>)); + Assert.AreEqual("T:System.Collections.Generic.List`1", + IDStringProvider.GetIDString(list)); + Assert.AreEqual("M:System.Collections.Generic.List`1.Add(`0)", + IDStringProvider.GetIDString(list.Methods.Single(m => m.Name == "Add"))); + Assert.AreEqual("M:System.Collections.Generic.List`1.AddRange(System.Collections.Generic.IEnumerable{`0})", + IDStringProvider.GetIDString(list.Methods.Single(m => m.Name == "AddRange"))); + Assert.AreEqual("M:System.Collections.Generic.List`1.ConvertAll``1(System.Converter{`0,``0})", + IDStringProvider.GetIDString(list.Methods.Single(m => m.Name == "ConvertAll"))); + } + } +} diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs index 7557859e6..d231327f1 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestBlankLineFormatting.cs @@ -31,7 +31,6 @@ using ICSharpCode.NRefactory.CSharp; namespace ICSharpCode.NRefactory.FormattingTests { - [Ignore ("TODO")] [TestFixture()] public class TestBlankLineFormatting : TestBase { diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs index 3746b3b0f..033bf1924 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestBraceStlye.cs @@ -34,7 +34,6 @@ namespace ICSharpCode.NRefactory.FormattingTests [TestFixture()] public class TestBraceStyle : TestBase { - [Ignore ("TODO")] [Test()] public void TestNamespaceBraceStyle () { @@ -222,7 +221,6 @@ namespace B { }"); } - [Ignore ("TODO")] [Test()] public void TestAllowPropertyGetBlockInline () { @@ -264,7 +262,6 @@ namespace B { }"); } - [Ignore ("TODO")] [Test()] public void TestAllowPropertySetBlockInline () { diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs index 8e667542e..ea509e221 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestFormattingBugs.cs @@ -1,4 +1,4 @@ -// +// // TestFormattingBugs.cs // // Author: @@ -31,7 +31,6 @@ using ICSharpCode.NRefactory.CSharp; namespace ICSharpCode.NRefactory.FormattingTests { - [Ignore()] [TestFixture()] public class TestFormattingBugs : TestBase { @@ -131,9 +130,9 @@ using (IDisposable b = null) { " + input + @" } }"); - int start = result.GetLineOffset (5); - int end = result.GetLineOffset (result.LineCount - 1); - string text = result.GetTextAt (start, end - start).Trim (); + int start = result.GetOffset (5, 1); + int end = result.GetOffset (result.LineCount - 1, 1); + string text = result.GetText (start, end - start).Trim (); expectedOutput = expectedOutput.Replace ("\n", "\n\t\t"); Assert.AreEqual (expectedOutput, text); } diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs index 87d61ee51..3f0c23602 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestSpacingVisitor.cs @@ -1,4 +1,4 @@ -// +// // TestFormattingVisitor.cs // // Author: @@ -142,7 +142,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i2 = result.Text.IndexOf ("right") + "right".Length; if (i1 < 0 || i2 < 0) Assert.Fail ("text invalid:" + result.Text); - Assert.AreEqual ("left " + op + " right", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual ("left " + op + " right", result.GetText (i1, i2 - i1)); } [Test()] @@ -234,7 +234,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("condition"); int i2 = result.Text.IndexOf ("falseexpr") + "falseexpr".Length; - Assert.AreEqual (@"condition ? trueexpr : falseexpr", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"condition ? trueexpr : falseexpr", result.GetText (i1, i2 - i1)); policy.SpaceBeforeConditionalOperatorCondition = false; @@ -250,7 +250,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); i1 = result.Text.IndexOf ("true"); i2 = result.Text.IndexOf ("falseexpr") + "falseexpr".Length; - Assert.AreEqual (@"true?trueexpr:falseexpr", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"true?trueexpr:falseexpr", result.GetText (i1, i2 - i1)); } [Test()] @@ -268,7 +268,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.IndexOf ("MethodCall"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"MethodCall ();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"MethodCall ();", result.GetText (i1, i2 - i1)); result = GetResult (policy, @"class Test { @@ -282,7 +282,7 @@ namespace ICSharpCode.NRefactory.FormattingTests result = GetResult (policy, result.Text); i1 = result.Text.IndexOf ("MethodCall"); i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"MethodCall();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"MethodCall();", result.GetText (i1, i2 - i1)); } [Test()] @@ -299,7 +299,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( true )", result.GetText (i1, i2 - i1)); policy.SpaceWithinMethodCallParentheses = false; @@ -312,7 +312,7 @@ namespace ICSharpCode.NRefactory.FormattingTests i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(true)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(true)", result.GetText (i1, i2 - i1)); } [Test()] @@ -329,7 +329,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("if"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"if (true)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"if (true)", result.GetText (i1, i2 - i1)); } [Test()] @@ -346,7 +346,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( true )", result.GetText (i1, i2 - i1)); } [Test()] @@ -363,7 +363,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("while"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"while (true)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"while (true)", result.GetText (i1, i2 - i1)); } [Test()] @@ -381,7 +381,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( true )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( true )", result.GetText (i1, i2 - i1)); } [Test()] @@ -398,7 +398,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("for"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"for (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"for (", result.GetText (i1, i2 - i1)); } [Test()] @@ -415,7 +415,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( ;; )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( ;; )", result.GetText (i1, i2 - i1)); } [Test()] @@ -432,7 +432,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("foreach"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"foreach (var o in list)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"foreach (var o in list)", result.GetText (i1, i2 - i1)); } [Test()] @@ -449,7 +449,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( var o in list )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( var o in list )", result.GetText (i1, i2 - i1)); } [Test()] @@ -466,7 +466,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("catch"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"catch (Exception)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"catch (Exception)", result.GetText (i1, i2 - i1)); } [Test()] @@ -483,7 +483,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( Exception )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( Exception )", result.GetText (i1, i2 - i1)); } [Test()] @@ -500,7 +500,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.IndexOf ("lock"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"lock (this)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"lock (this)", result.GetText (i1, i2 - i1)); } [Test()] @@ -517,7 +517,7 @@ namespace ICSharpCode.NRefactory.FormattingTests }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( this )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( this )", result.GetText (i1, i2 - i1)); } [Test()] @@ -535,7 +535,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.LastIndexOf ("for"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"for (int i; true; i++)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"for (int i; true; i++)", result.GetText (i1, i2 - i1)); } [Test()] @@ -554,7 +554,7 @@ namespace ICSharpCode.NRefactory.FormattingTests int i1 = result.Text.LastIndexOf ("for"); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"for (int i ;true ;i++)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"for (int i ;true ;i++)", result.GetText (i1, i2 - i1)); } [Test()] @@ -572,7 +572,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("return"); int i2 = result.Text.LastIndexOf ("null") + "null".Length; - Assert.AreEqual (@"return (Test) null", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"return (Test) null", result.GetText (i1, i2 - i1)); } [Test()] @@ -589,7 +589,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("using"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"using (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"using (", result.GetText (i1, i2 - i1)); } [Test()] @@ -606,7 +606,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a )", result.GetText (i1, i2 - i1)); } static void TestAssignmentOperator (CSharpFormattingOptions policy, string op) @@ -617,7 +617,7 @@ return (Test)null; int i2 = result.Text.IndexOf ("right") + "right".Length; if (i1 < 0 || i2 < 0) Assert.Fail ("text invalid:" + result.Text); - Assert.AreEqual ("left " + op + " right", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual ("left " + op + " right", result.GetText (i1, i2 - i1)); } [Test()] @@ -653,7 +653,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("left"); int i2 = result.Text.LastIndexOf ("right") + "right".Length; - Assert.AreEqual (@"left = right", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"left = right", result.GetText (i1, i2 - i1)); } [Test()] @@ -670,7 +670,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("switch"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"switch (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"switch (", result.GetText (i1, i2 - i1)); } [Test()] @@ -687,7 +687,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( test )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( test )", result.GetText (i1, i2 - i1)); } [Test()] @@ -704,7 +704,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( test )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( test )", result.GetText (i1, i2 - i1)); } [Test()] @@ -720,7 +720,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -737,7 +737,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int )", result.GetText (i1, i2 - i1)); } [Test()] @@ -754,7 +754,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int )", result.GetText (i1, i2 - i1)); } [Test()] @@ -771,7 +771,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("sizeof"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"sizeof (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"sizeof (", result.GetText (i1, i2 - i1)); } [Test()] @@ -788,7 +788,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int )", result.GetText (i1, i2 - i1)); } [Test()] @@ -806,7 +806,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("typeof"); int i2 = result.Text.LastIndexOf ("(") + "(".Length; - Assert.AreEqual (@"typeof (", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"typeof (", result.GetText (i1, i2 - i1)); } [Test()] @@ -823,7 +823,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a + b )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a + b )", result.GetText (i1, i2 - i1)); result = GetResult (policy, @"class Test { void TestMe () @@ -835,7 +835,7 @@ return (Test)null; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a + b )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a + b )", result.GetText (i1, i2 - i1)); } [Test()] @@ -852,7 +852,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test ();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test ();", result.GetText (i1, i2 - i1)); } [Test()] @@ -869,7 +869,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test ( 1 );", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test ( 1 );", result.GetText (i1, i2 - i1)); } [Test()] @@ -886,7 +886,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test ( );", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test ( );", result.GetText (i1, i2 - i1)); } [Test()] @@ -904,7 +904,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test (1 ,2);", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test (1 ,2);", result.GetText (i1, i2 - i1)); } [Test()] @@ -921,7 +921,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("new"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"new Test (1, 2);", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"new Test (1, 2);", result.GetText (i1, i2 - i1)); } [Test()] @@ -936,20 +936,20 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("int"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"int a, b, c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a, b, c;", result.GetText (i1, i2 - i1)); policy.SpaceBeforeFieldDeclarationComma = true; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("int"); i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"int a , b , c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a , b , c;", result.GetText (i1, i2 - i1)); policy.SpaceBeforeFieldDeclarationComma = false; policy.SpaceAfterFieldDeclarationComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("int"); i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"int a,b,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a,b,c;", result.GetText (i1, i2 - i1)); } [Test()] @@ -964,13 +964,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeMethodDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -985,13 +985,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a, int b, int c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterMethodDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1008,7 +1008,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("x"); int i2 = result.Text.LastIndexOf ("null") + "null".Length; - Assert.AreEqual (@"x => x != null", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"x => x != null", result.GetText (i1, i2 - i1)); } [Test()] @@ -1026,7 +1026,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("int"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a ,b ,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a ,b ,c;", result.GetText (i1, i2 - i1)); result = GetResult (policy, result.Text); @@ -1035,7 +1035,7 @@ return (Test)null; result = GetResult (policy, result.Text); i1 = result.Text.IndexOf ("int"); i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a,b,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a,b,c;", result.GetText (i1, i2 - i1)); } [Test()] @@ -1053,7 +1053,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("int"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a = 5 , b = 6 , c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a = 5 , b = 6 , c;", result.GetText (i1, i2 - i1)); result = GetResult (policy, result.Text); @@ -1063,7 +1063,7 @@ return (Test)null; result = GetResult (policy, result.Text); i1 = result.Text.IndexOf ("int"); i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"int a = 5,b = 6,c;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"int a = 5,b = 6,c;", result.GetText (i1, i2 - i1)); } [Test()] @@ -1081,7 +1081,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("List"); int i2 = result.Text.IndexOf (";") + ";".Length; - Assert.AreEqual (@"List a;", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"List a;", result.GetText (i1, i2 - i1)); } @@ -1121,14 +1121,14 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeConstructorDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1143,13 +1143,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a, int b, int c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterConstructorDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1165,7 +1165,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -1181,7 +1181,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( )", result.GetText (i1, i2 - i1)); } #endregion @@ -1220,13 +1220,13 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a ,int b ,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a ,int b ,int c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeDelegateDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1240,13 +1240,13 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a, int b, int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a, int b, int c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterDelegateDeclarationParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(int a,int b,int c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(int a,int b,int c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1258,7 +1258,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( int a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( int a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -1270,7 +1270,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( )", result.GetText (i1, i2 - i1)); } #endregion @@ -1315,13 +1315,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a ,b ,c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a ,b ,c)", result.GetText (i1, i2 - i1)); policy.SpaceBeforeMethodCallParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a,b,c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a,b,c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1340,13 +1340,13 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a, b, c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a, b, c)", result.GetText (i1, i2 - i1)); policy.SpaceAfterMethodCallParameterComma = false; result = GetResult (policy, result.Text); i1 = result.Text.LastIndexOf ("("); i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"(a,b,c)", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"(a,b,c)", result.GetText (i1, i2 - i1)); } [Test()] @@ -1364,7 +1364,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( a )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( a )", result.GetText (i1, i2 - i1)); } [Test()] @@ -1382,7 +1382,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("("); int i2 = result.Text.LastIndexOf (")") + ")".Length; - Assert.AreEqual (@"( )", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"( )", result.GetText (i1, i2 - i1)); } #endregion @@ -1430,7 +1430,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[int a ,int b]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[int a ,int b]", result.GetText (i1, i2 - i1)); } @@ -1450,7 +1450,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[int a, int b]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[int a, int b]", result.GetText (i1, i2 - i1)); } [Test()] @@ -1469,7 +1469,7 @@ return (Test)null; }"); int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[ int a, int b ]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[ int a, int b ]", result.GetText (i1, i2 - i1)); } #endregion @@ -1540,7 +1540,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[1 ,2 ,3]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[1 ,2 ,3]", result.GetText (i1, i2 - i1)); } [Test()] @@ -1558,7 +1558,7 @@ return (Test)null; int i1 = result.Text.LastIndexOf ("["); int i2 = result.Text.LastIndexOf ("]") + "]".Length; - Assert.AreEqual (@"[1, 2, 3]", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"[1, 2, 3]", result.GetText (i1, i2 - i1)); } #endregion @@ -1595,7 +1595,7 @@ return (Test)null; }"); int i1 = result.Text.IndexOf ("Foo"); int i2 = result.Text.LastIndexOf (";") + ";".Length; - Assert.AreEqual (@"Foo ();", result.GetTextAt (i1, i2 - i1)); + Assert.AreEqual (@"Foo ();", result.GetText (i1, i2 - i1)); } } diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs index 96d06c1c2..e0bf27ad9 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestStatementIndentation.cs @@ -55,7 +55,6 @@ this.TestMethod (); }"); } - [Ignore ("TODO")] [Test()] public void TestIndentBlocks () { @@ -499,7 +498,6 @@ using (var o = new MyObj()) { }"); } - [Ignore ("TODO")] [Test()] public void TestUsingAlignment () { @@ -946,7 +944,6 @@ do { }"); } - [Ignore ("TODO")] [Test()] public void TestIfAlignment () { diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs index 1ba5ef5f5..6bef2a780 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TestTypeLevelIndentation.cs @@ -45,6 +45,20 @@ namespace ICSharpCode.NRefactory.FormattingTests @"class Test {}"); } + [Test()] + public void TestAttributeIndentation () + { + CSharpFormattingOptions policy = new CSharpFormattingOptions (); + policy.ClassBraceStyle = BraceStyle.DoNotChange; + + Test (policy, +@" [Attribute1] + [Attribute2()] + class Test {}", +@"[Attribute1] +[Attribute2()] +class Test {}"); + } [Test()] public void TestClassIndentationInNamespaces () @@ -249,7 +263,6 @@ A }"); } - [Ignore ("TODO")] [Test()] public void TestIndentMethodBodyOperatorCase () { @@ -284,7 +297,6 @@ A }"); } - [Ignore ("TODO")] [Test()] public void TestIndentPropertyBody () { @@ -356,7 +368,6 @@ set; }"); } - [Ignore ("TODO")] [Test()] public void TestIndentPropertyBodyIndexerCase () { @@ -401,7 +412,6 @@ set { }"); } - [Ignore ("TODO")] [Test()] public void TestPropertyAlignment () { @@ -435,7 +445,6 @@ set { } - [Ignore ("TODO")] [Test()] public void TestIndentNamespaceBody () { @@ -515,7 +524,6 @@ set; } - [Ignore ("TODO")] [Test()] public void TestIndentEventBody () { diff --git a/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs b/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs index a9cef844f..b127d1052 100644 --- a/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs +++ b/ICSharpCode.NRefactory.Tests/FormattingTests/TextEditorTestAdapter.cs @@ -1,218 +1,14 @@ using System; using System.Collections.Generic; +using System.Text; using ICSharpCode.NRefactory.CSharp; using System.IO; +using ICSharpCode.NRefactory.Editor; using NUnit.Framework; using ICSharpCode.NRefactory.CSharp.Refactoring; namespace ICSharpCode.NRefactory.FormattingTests { - /// - /// Text editor test adapter. Only implemented for testing purposes. Don't use in production code. - /// - class TextEditorTestAdapter : ITextEditorAdapter - { - string text; - - public string Text { - get { - return this.text; - } - } - - List delimiters; - - struct Delimiter - { - public readonly int Offset; - public readonly int Length; - - public int EndOffset { - get { return Offset + Length; } - } - - public Delimiter (int offset, int length) - { - Offset = offset; - Length = length; - } - - public override string ToString () - { - return string.Format ("[Delimiter: Offset={0}, Length={1}]", Offset, Length); - } - } - public void Replace (int offset, int count, string value) - { - this.text = this.text.Substring (0, offset) + value + this.text.Substring (offset + count); - } - static IEnumerable FindDelimiter (string text) - { - for (int i = 0; i < text.Length; i++) { - switch (text [i]) { - case '\r': - if (i + 1 < text.Length && text [i + 1] == '\n') { - yield return new Delimiter (i, 2); - i++; - } else { - yield return new Delimiter (i, 1); - } - break; - case '\n': - yield return new Delimiter (i, 1); - break; - } - } - } - - public TextEditorTestAdapter (string text) - { - this.text = text; - delimiters = new List (FindDelimiter (text)); - } - - class Segment - { - public readonly int Offset; - public readonly int Length; - public readonly int DelimiterLength; - - public Segment (int offset, int length, int delimiterLength) - { - this.Offset = offset; - this.Length = length; - this.DelimiterLength = delimiterLength; - } - - public override string ToString () - { - return string.Format ("[Segment: Offset={0}, Length={1}, DelimiterLength={2}]", Offset, Length, DelimiterLength); - } - } - - Segment Get (int number) - { - number--; - if (number < 0 || number - 1 >= delimiters.Count) - return null; - int startOffset = number > 0 ? delimiters [number - 1].EndOffset : 0; - int endOffset; - int delimiterLength; - if (number < delimiters.Count) { - endOffset = delimiters [number].EndOffset; - delimiterLength = delimiters [number].Length; - } else { - endOffset = text.Length; - delimiterLength = 0; - } - return new Segment (startOffset, endOffset - startOffset, delimiterLength); - } - - #region ITextEditorAdapter implementation - public int LocationToOffset (int line, int col) - { - Segment seg = Get (line); - if (seg == null) - return 0; - return seg.Offset + col - 1; - } - - public char GetCharAt (int offset) - { - if (offset < 0 || offset >= text.Length) - return '\0'; - return text [offset]; - } - - public string GetTextAt (int offset, int length) - { - if (offset < 0 || offset + length >= text.Length) - return ""; - if (length <= 0) - return ""; - - return text.Substring (offset, length); - } - - public int GetEditableLength (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Length - seg.DelimiterLength; - } - - public string GetIndentation (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return ""; - int start = seg.Offset; - int end = seg.Offset; - int endOffset = seg.Offset + seg.Length - seg.DelimiterLength; - - while (end < endOffset && (text[end] == ' ' || text[end] == '\t')) - end++; - - return start < end ? text.Substring (start, end - start) : ""; - } - - public int GetLineOffset (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Offset; - } - - public int GetLineLength (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Length; - } - - public int GetLineEndOffset (int lineNumber) - { - var seg = Get (lineNumber); - if (seg == null) - return 0; - return seg.Offset + seg.Length; - } - - public bool TabsToSpaces { - get { - return false; - } - } - - public int TabSize { - get { - return 4; - } - } - - public string EolMarker { - get { - return Environment.NewLine; - } - } - - public int Length { - get { - return text.Length; - } - } - - public int LineCount { - get { - return delimiters.Count + 1; - } - } - #endregion - } - public abstract class TestBase { static IActionFactory factory = new TestFactory (); @@ -236,59 +32,55 @@ namespace ICSharpCode.NRefactory.FormattingTests } } - static void ApplyChanges (TextEditorTestAdapter adapter, List changes) + static string ApplyChanges (string text, List changes) { changes.Sort ((x, y) => y.Offset.CompareTo (x.Offset)); + StringBuilder b = new StringBuilder(text); foreach (var change in changes) { // Console.WriteLine ("---- apply:" + change); // Console.WriteLine (adapter.Text); - if (change.Offset > adapter.Length) + if (change.Offset > b.Length) continue; - adapter.Replace (change.Offset, change.RemovedChars, change.InsertedText); + b.Remove(change.Offset, change.RemovedChars); + b.Insert(change.Offset, change.InsertedText); } // Console.WriteLine ("---result:"); // Console.WriteLine (adapter.Text); + return b.ToString(); } - protected static ITextEditorAdapter GetResult (CSharpFormattingOptions policy, string input) + protected static IDocument GetResult (CSharpFormattingOptions policy, string input) { - var adapter = new TextEditorTestAdapter (input); - var visitior = new AstFormattingVisitor (policy, adapter, factory); + var adapter = new ReadOnlyDocument (input); + var visitor = new AstFormattingVisitor (policy, adapter, factory); - var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); - compilationUnit.AcceptVisitor (visitior, null); + var compilationUnit = new CSharpParser ().Parse (new StringReader (input)); + compilationUnit.AcceptVisitor (visitor, null); - ApplyChanges (adapter, visitior.Changes); - - return adapter; + return new ReadOnlyDocument(ApplyChanges (input, visitor.Changes)); } - protected static ITextEditorAdapter Test (CSharpFormattingOptions policy, string input, string expectedOutput) + protected static IDocument Test (CSharpFormattingOptions policy, string input, string expectedOutput) { - var adapter = new TextEditorTestAdapter (input); - var visitior = new AstFormattingVisitor (policy, adapter, factory); - - var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); - compilationUnit.AcceptVisitor (visitior, null); - ApplyChanges (adapter, visitior.Changes); - if (expectedOutput != adapter.Text) { - Console.WriteLine (adapter.Text); + IDocument doc = GetResult(policy, input); + if (expectedOutput != doc.Text) { + Console.WriteLine (doc.Text); } - Assert.AreEqual (expectedOutput, adapter.Text); - return adapter; + Assert.AreEqual (expectedOutput, doc.Text); + return doc; } - protected static void Continue (CSharpFormattingOptions policy, ITextEditorAdapter adapter, string expectedOutput) + protected static void Continue (CSharpFormattingOptions policy, IDocument document, string expectedOutput) { - var visitior = new AstFormattingVisitor (policy, adapter, factory); + var visitior = new AstFormattingVisitor (policy, document, factory); - var compilationUnit = new CSharpParser ().Parse (new StringReader (adapter.Text)); + var compilationUnit = new CSharpParser ().Parse (new StringReader (document.Text)); compilationUnit.AcceptVisitor (visitior, null); - ApplyChanges (((TextEditorTestAdapter)adapter), visitior.Changes); - if (expectedOutput != adapter.Text) { - Console.WriteLine (adapter.Text); + string newText = ApplyChanges (document.Text, visitior.Changes); + if (expectedOutput != newText) { + Console.WriteLine (newText); } - Assert.AreEqual (expectedOutput, adapter.Text); + Assert.AreEqual (expectedOutput, newText); } diff --git a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj index cebee2aa5..2b1bcb8ce 100644 --- a/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj +++ b/ICSharpCode.NRefactory.Tests/ICSharpCode.NRefactory.Tests.csproj @@ -11,13 +11,14 @@ Properties 10.0.0 2.0 - - - x86 + True + False + 4 + false bin\Debug\ - True + true Full False True @@ -41,6 +42,26 @@ true ..\ICSharpCode.NRefactory\bin\Release\ + + AnyCPU + False + Auto + 4194304 + 4096 + + + 4 + true + ..\ICSharpCode.NRefactory\bin\Debug\ + + + 4 + true + ..\ICSharpCode.NRefactory\bin\Release\ + + + x86 + @@ -56,11 +77,16 @@ + + + + + @@ -89,9 +115,8 @@ - - - + + @@ -117,6 +142,8 @@ + + @@ -128,12 +155,14 @@ + + @@ -144,18 +173,22 @@ + - + + {53DCA265-3C3C-42F9-B647-F72BA678122B} + ICSharpCode.NRefactory.CSharp + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} ICSharpCode.NRefactory @@ -163,10 +196,12 @@ + + \ No newline at end of file diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs index e64e1f753..0a3746f58 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/CecilLoaderTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -13,7 +28,19 @@ namespace ICSharpCode.NRefactory.TypeSystem [TestFixture] public class CecilLoaderTests : TypeSystemTests { - public static readonly IProjectContent Mscorlib = new CecilLoader().LoadAssemblyFile(typeof(object).Assembly.Location); + static readonly Lazy mscorlib = new Lazy( + delegate { + return new CecilLoader().LoadAssemblyFile(typeof(object).Assembly.Location); + }); + + static readonly Lazy systemCore = new Lazy( + delegate { + return new CecilLoader().LoadAssemblyFile(typeof(System.Linq.Enumerable).Assembly.Location); + }); + + public static IProjectContent Mscorlib { get { return mscorlib.Value; } } + public static IProjectContent SystemCore { get { return systemCore.Value; } } + ITypeResolveContext ctx = Mscorlib; [TestFixtureSetUp] @@ -38,8 +65,9 @@ namespace ICSharpCode.NRefactory.TypeSystem string[] superTypes = c.GetAllBaseTypes(ctx).Select(t => t.ToString()).ToArray(); Assert.AreEqual(new string[] { - "System.SystemException", "System.Exception", "System.Object", - "System.Runtime.Serialization.ISerializable", "System.Runtime.InteropServices._Exception" + "System.Object", + "System.Runtime.Serialization.ISerializable", "System.Runtime.InteropServices._Exception", + "System.Exception", "System.SystemException" }, superTypes); } @@ -50,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/GetAllBaseTypesTest.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs index 095e455ca..c6bac492c 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/GetAllBaseTypesTest.cs @@ -1,15 +1,33 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; using System.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; namespace ICSharpCode.NRefactory.TypeSystem { + using Unbound = ReflectionHelper.UnboundTypeArgument; + [TestFixture] public class GetAllBaseTypesTest { @@ -76,7 +94,7 @@ namespace ICSharpCode.NRefactory.TypeSystem DefaultTypeDefinition c2 = new DefaultTypeDefinition(mscorlib, string.Empty, "C2"); c1.BaseTypes.Add(c2); c2.BaseTypes.Add(c1); - Assert.AreEqual(new [] { c1, c2 }, c1.GetAllBaseTypes(context).ToArray()); + Assert.AreEqual(new [] { c2, c1 }, c1.GetAllBaseTypes(context).ToArray()); } [Test] @@ -113,7 +131,7 @@ namespace ICSharpCode.NRefactory.TypeSystem // struct S : IEquatable {} // don't use a Cecil-loaded struct for this test; we're testing the implicit addition of System.ValueType DefaultTypeDefinition s = new DefaultTypeDefinition(mscorlib, string.Empty, "S"); - s.ClassType = ClassType.Struct; + s.Kind = TypeKind.Struct; s.BaseTypes.Add(new ParameterizedType(mscorlib.GetTypeDefinition(typeof(IEquatable<>)), new[] { s })); IType[] expected = { s, @@ -135,6 +153,25 @@ namespace ICSharpCode.NRefactory.TypeSystem GetAllBaseTypes(typeof(List))); } + [Test] + public void BaseTypesOfUnboundDictionary() + { + Assert.AreEqual( + new [] { + typeof(Dictionary<,>).FullName, + typeof(ICollection<>).FullName + "[[" + typeof(KeyValuePair<,>).FullName + "[[`0],[`1]]]]", + typeof(IDictionary<,>).FullName + "[[`0],[`1]]", + typeof(IEnumerable<>).FullName + "[[" + typeof(KeyValuePair<,>).FullName + "[[`0],[`1]]]]", + typeof(ICollection).FullName, + typeof(IDictionary).FullName, + typeof(IEnumerable).FullName, + typeof(object).FullName, + typeof(IDeserializationCallback).FullName, + typeof(ISerializable).FullName, + }, + GetAllBaseTypes(typeof(Dictionary<,>)).Select(t => t.ReflectionName).ToArray()); + } + [Test] public void BaseTypeDefinitionsOfListOfString() { @@ -144,5 +181,16 @@ namespace ICSharpCode.NRefactory.TypeSystem typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>)), typeof(List).ToTypeReference().Resolve(context).GetAllBaseTypeDefinitions(context).OrderBy(t => t.ReflectionName).ToArray()); } + + [Test] + public void BaseTypeDefinitionsOfStringArray() + { + Assert.AreEqual( + GetTypes(typeof(Array), typeof(object), + typeof(ICloneable), typeof(IStructuralComparable), typeof(IStructuralEquatable), + typeof(IList), typeof(ICollection), typeof(IEnumerable), + typeof(IEnumerable<>), typeof(ICollection<>), typeof(IList<>)), + typeof(string[]).ToTypeReference().Resolve(context).GetAllBaseTypeDefinitions(context).OrderBy(t => t.ReflectionName).ToArray()); + } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs index 6e0d9dc8b..8b9ad11fe 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/GetMembersTests.cs @@ -1,7 +1,23 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.TypeSystem.Implementation; using NUnit.Framework; @@ -24,15 +40,15 @@ namespace ICSharpCode.NRefactory.TypeSystem public void MultipleInheritanceTest() { DefaultTypeDefinition b1 = new DefaultTypeDefinition(mscorlib, string.Empty, "B1"); - b1.ClassType = ClassType.Interface; + b1.Kind = TypeKind.Interface; b1.Properties.Add(new DefaultProperty(b1, "P1")); DefaultTypeDefinition b2 = new DefaultTypeDefinition(mscorlib, string.Empty, "B1"); - b2.ClassType = ClassType.Interface; + b2.Kind = TypeKind.Interface; b2.Properties.Add(new DefaultProperty(b1, "P2")); DefaultTypeDefinition c = new DefaultTypeDefinition(mscorlib, string.Empty, "C"); - c.ClassType = ClassType.Interface; + c.Kind = TypeKind.Interface; c.BaseTypes.Add(b1); c.BaseTypes.Add(b2); @@ -71,5 +87,41 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual("System.Int32", indexer.Parameters[0].Type.Resolve(mscorlib).ReflectionName); Assert.AreEqual("System.Int32", indexer.Parameters[1].Type.Resolve(mscorlib).ReflectionName); } + + [Test] + public void GetNestedTypesOfUnboundGenericClass() + { + ITypeDefinition dictionary = mscorlib.GetTypeDefinition(typeof(Dictionary<,>)); + IType keyCollection = dictionary.GetNestedTypes(mscorlib).Single(t => t.Name == "KeyCollection"); + Assert.IsTrue(keyCollection is ITypeDefinition); + } + + [Test] + public void GetNestedTypesOfBoundGenericClass() + { + IType dictionary = typeof(Dictionary).ToTypeReference().Resolve(mscorlib); + IType keyCollection = dictionary.GetNestedTypes(mscorlib).Single(t => t.Name == "KeyCollection"); + Assert.AreEqual(typeof(Dictionary.KeyCollection).ToTypeReference().Resolve(mscorlib), keyCollection); + } + + [Test] + public void GetGenericNestedTypeOfBoundGenericClass() + { + // class A { class B { } } + DefaultTypeDefinition a = new DefaultTypeDefinition(mscorlib, string.Empty, "A"); + a.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 0, "X")); + + DefaultTypeDefinition b = new DefaultTypeDefinition(a, "B"); + b.TypeParameters.Add(a.TypeParameters[0]); + b.TypeParameters.Add(new DefaultTypeParameter(EntityType.TypeDefinition, 1, "Y")); + + a.NestedTypes.Add(b); + + // A<> gets self-parameterized, B<> stays unbound + Assert.AreEqual("A`1+B`1[[`0],[]]", a.GetNestedTypes(mscorlib).Single().ReflectionName); + + ParameterizedType pt = new ParameterizedType(a, new [] { KnownTypeReference.String.Resolve(mscorlib) }); + Assert.AreEqual("A`1+B`1[[System.String],[]]", pt.GetNestedTypes(mscorlib).Single().ReflectionName); + } } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs index 537ed2319..08dc83912 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/ReflectionHelperTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/SerializedCecilLoaderTests.cs new file mode 100644 index 000000000..9bbafb851 --- /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/StructureTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs index f4931bc33..ee797478b 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/StructureTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; @@ -10,7 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem public class StructureTests { [Test] - public void ClasesThatSupportInterningAreSealed() + public void ClassesThatSupportInterningAreSealed() { foreach (Type type in typeof(ISupportsInterning).Assembly.GetTypes()) { if (typeof(ISupportsInterning).IsAssignableFrom(type) && !type.IsInterface) { diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs index 11d53549a..a9984bb20 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TestInterningProvider.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs index edb0bce50..d7e32a3c1 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.TestCase.cs @@ -1,13 +1,31 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Runtime.InteropServices; +using System.Runtime.CompilerServices; [assembly: ICSharpCode.NRefactory.TypeSystem.TestCase.TypeTestAttribute( 42, typeof(System.Action<>), typeof(IDictionary>))] +[assembly: TypeForwardedTo(typeof(Func<,>))] + namespace ICSharpCode.NRefactory.TypeSystem.TestCase { public delegate S GenericDelegate(T input) where T : S where S : class; @@ -60,7 +78,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase } public class Base { - public class Nested {} + public class Nested {} } public class Derived : Base {} @@ -95,4 +113,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.TestCase public void MethodWithOutParameter(out int x) { x = 0; } public void MethodWithParamsArray(params object[] x) {} } + + [ComImport(), Guid("21B8916C-F28E-11D2-A473-00C04F8EF448"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + public interface IAssemblyEnum + { + [PreserveSig()] + int GetNextAssembly(uint dwFlags); + } + + public class ConstantTest + { + public const int Answer = 42; + + public const string NullString = null; + } } diff --git a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs index 80e4071ba..8b74b7267 100644 --- a/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs +++ b/ICSharpCode.NRefactory.Tests/TypeSystem/TypeSystemTests.cs @@ -1,9 +1,28 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; +using System.Runtime.CompilerServices; using System.Runtime.InteropServices; + +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.TypeSystem.TestCase; using NUnit.Framework; @@ -68,7 +87,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); } @@ -112,24 +131,36 @@ namespace ICSharpCode.NRefactory.TypeSystem public void AssemblyAttribute() { var attributes = testCasePC.AssemblyAttributes; - var typeTest = attributes.First(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeTestAttribute).FullName); + var typeTest = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeTestAttribute).FullName); var posArgs = typeTest.GetPositionalArguments(ctx); Assert.AreEqual(3, posArgs.Count); // first argument is (int)42 - Assert.AreEqual(42, (int)posArgs[0].GetValue(ctx)); + Assert.AreEqual(42, (int)posArgs[0].ConstantValue); // second argument is typeof(System.Action<>) - IType rt = (IType)posArgs[1].GetValue(ctx); - Assert.IsFalse(rt is ParameterizedType); // rt must not be constructed - it's just an unbound type - Assert.AreEqual("System.Action", rt.FullName); - Assert.AreEqual(1, rt.TypeParameterCount); + TypeOfResolveResult rt = (TypeOfResolveResult)posArgs[1]; + Assert.IsFalse(rt.ReferencedType is ParameterizedType); // rt must not be constructed - it's just an unbound type + Assert.AreEqual("System.Action", rt.ReferencedType.FullName); + Assert.AreEqual(1, rt.ReferencedType.TypeParameterCount); // third argument is typeof(IDictionary>) - ParameterizedType crt = (ParameterizedType)posArgs[2].GetValue(ctx); + rt = (TypeOfResolveResult)posArgs[2]; + ParameterizedType crt = (ParameterizedType)rt.ReferencedType; Assert.AreEqual("System.Collections.Generic.IDictionary", crt.FullName); Assert.AreEqual("System.String", crt.TypeArguments[0].FullName); // ? for NUnit.TestAttribute (because that assembly isn't in ctx) Assert.AreEqual("System.Collections.Generic.IList`1[[?]]", crt.TypeArguments[1].ReflectionName); } + [Test] + public void TypeForwardedTo_Attribute() + { + var attributes = testCasePC.AssemblyAttributes; + var forwardAttribute = attributes.Single(a => a.AttributeType.Resolve(ctx).FullName == typeof(TypeForwardedToAttribute).FullName); + var posArgs = forwardAttribute.GetPositionalArguments(ctx); + Assert.AreEqual(1, posArgs.Count); + TypeOfResolveResult rt = (TypeOfResolveResult)posArgs[0]; + Assert.AreEqual("System.Func`2", rt.ReferencedType.ReflectionName); + } + [Test] public void TestClassTypeParameters() { @@ -199,6 +230,7 @@ namespace ICSharpCode.NRefactory.TypeSystem { var testClass = testCasePC.GetTypeDefinition(typeof(PropertyTest)); IProperty p = testClass.Properties.Single(pr => pr.IsIndexer); + Assert.AreEqual("Item", p.Name); Assert.IsTrue(p.CanGet); Assert.AreEqual(Accessibility.Public, p.Accessibility); Assert.AreEqual(Accessibility.Public, p.Getter.Accessibility); @@ -210,7 +242,7 @@ namespace ICSharpCode.NRefactory.TypeSystem public void EnumTest() { var e = testCasePC.GetTypeDefinition(typeof(MyEnum)); - Assert.AreEqual(ClassType.Enum, e.ClassType); + Assert.AreEqual(TypeKind.Enum, e.Kind); Assert.AreEqual(false, e.IsReferenceType(ctx)); Assert.AreEqual("System.Int16", e.BaseTypes[0].Resolve(ctx).ReflectionName); Assert.AreEqual(new[] { "System.Enum" }, e.GetBaseTypes(ctx).Select(t => t.ReflectionName).ToArray()); @@ -226,32 +258,50 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.IsTrue(f.IsStatic); Assert.IsTrue(f.IsConst); Assert.AreEqual(Accessibility.Public, f.Accessibility); - Assert.AreSame(e, f.ConstantValue.GetValueType(ctx)); - Assert.AreEqual(typeof(short), f.ConstantValue.GetValue(ctx).GetType()); + Assert.AreSame(e, f.ConstantValue.Resolve(ctx).Type); + Assert.AreEqual(typeof(short), f.ConstantValue.Resolve(ctx).ConstantValue.GetType()); } Assert.AreEqual("First", e.Fields[0].Name); - Assert.AreEqual(0, e.Fields[0].ConstantValue.GetValue(ctx)); + Assert.AreEqual(0, e.Fields[0].ConstantValue.Resolve(ctx).ConstantValue); Assert.AreEqual("Second", e.Fields[1].Name); - Assert.AreSame(e, e.Fields[1].ConstantValue.GetValueType(ctx)); - Assert.AreEqual(1, e.Fields[1].ConstantValue.GetValue(ctx)); + Assert.AreSame(e, e.Fields[1].ConstantValue.Resolve(ctx).Type); + Assert.AreEqual(1, e.Fields[1].ConstantValue.Resolve(ctx).ConstantValue); Assert.AreEqual("Flag1", e.Fields[2].Name); - Assert.AreEqual(0x10, e.Fields[2].ConstantValue.GetValue(ctx)); + Assert.AreEqual(0x10, e.Fields[2].ConstantValue.Resolve(ctx).ConstantValue); Assert.AreEqual("Flag2", e.Fields[3].Name); - Assert.AreEqual(0x20, e.Fields[3].ConstantValue.GetValue(ctx)); + Assert.AreEqual(0x20, e.Fields[3].ConstantValue.Resolve(ctx).ConstantValue); Assert.AreEqual("CombinedFlags", e.Fields[4].Name); - Assert.AreEqual(0x30, e.Fields[4].ConstantValue.GetValue(ctx)); + Assert.AreEqual(0x30, e.Fields[4].ConstantValue.Resolve(ctx).ConstantValue); + } + + [Test] + public void GetNestedTypesFromBaseClassTest() + { + ITypeDefinition d = ctx.GetTypeDefinition(typeof(Derived<,>)); + + IType pBase = d.BaseTypes.Single().Resolve(ctx); + Assert.AreEqual(typeof(Base<>).FullName + "[[`1]]", pBase.ReflectionName); + // Base[`1].GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } + Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" }, + pBase.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); + + // Derived.GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } + Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[`1],[]]" }, + d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); + // This is 'leaking' the type parameter from B as is usual when retrieving any members from an unbound type. } [Test] public void ParameterizedTypeGetNestedTypesFromBaseClassTest() { + // Derived[string,int].GetNestedTypes() = { Base`1+Nested`1[int, unbound] } var d = typeof(Derived).ToTypeReference().Resolve(ctx); - Assert.AreEqual(new[] { typeof(Base<>.Nested).FullName + "[[System.Int32]]" }, + Assert.AreEqual(new[] { typeof(Base<>.Nested<>).FullName + "[[System.Int32],[]]" }, d.GetNestedTypes(ctx).Select(n => n.ReflectionName).ToArray()); } @@ -282,20 +332,20 @@ namespace ICSharpCode.NRefactory.TypeSystem { IAttribute attr = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Attributes.Single(); Assert.AreEqual("System.Runtime.InteropServices.StructLayoutAttribute", attr.AttributeType.Resolve(ctx).FullName); - IConstantValue arg1 = attr.GetPositionalArguments(ctx).Single(); - Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.GetValueType(ctx).FullName); - Assert.AreEqual((int)LayoutKind.Explicit, arg1.GetValue(ctx)); + ResolveResult arg1 = attr.GetPositionalArguments(ctx).Single(); + Assert.AreEqual("System.Runtime.InteropServices.LayoutKind", arg1.Type.FullName); + Assert.AreEqual((int)LayoutKind.Explicit, arg1.ConstantValue); var namedArgs = attr.GetNamedArguments(ctx); var arg2 = namedArgs[0]; Assert.AreEqual("CharSet", arg2.Key); - Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.GetValueType(ctx).FullName); - Assert.AreEqual((int)CharSet.Unicode, arg2.Value.GetValue(ctx)); + Assert.AreEqual("System.Runtime.InteropServices.CharSet", arg2.Value.Type.FullName); + Assert.AreEqual((int)CharSet.Unicode, arg2.Value.ConstantValue); var arg3 = namedArgs[1]; Assert.AreEqual("Pack", arg3.Key); - Assert.AreEqual("System.Int32", arg3.Value.GetValueType(ctx).FullName); - Assert.AreEqual(8, arg3.Value.GetValue(ctx)); + Assert.AreEqual("System.Int32", arg3.Value.Type.FullName); + Assert.AreEqual(8, arg3.Value.ConstantValue); } [Test] @@ -303,15 +353,15 @@ namespace ICSharpCode.NRefactory.TypeSystem { IField field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field0"); Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); - IConstantValue arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); - Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName); - Assert.AreEqual(0, arg.GetValue(ctx)); + ResolveResult arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); + Assert.AreEqual("System.Int32", arg.Type.FullName); + Assert.AreEqual(0, arg.ConstantValue); field = ctx.GetTypeDefinition(typeof(ExplicitFieldLayoutStruct)).Fields.Single(f => f.Name == "Field100"); Assert.AreEqual("System.Runtime.InteropServices.FieldOffsetAttribute", field.Attributes.Single().AttributeType.Resolve(ctx).FullName); arg = field.Attributes.Single().GetPositionalArguments(ctx).Single(); - Assert.AreEqual("System.Int32", arg.GetValueType(ctx).FullName); - Assert.AreEqual(100, arg.GetValue(ctx)); + Assert.AreEqual("System.Int32", arg.Type.FullName); + Assert.AreEqual(100, arg.ConstantValue); } [Test] @@ -320,8 +370,8 @@ namespace ICSharpCode.NRefactory.TypeSystem IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IAttribute dllImport = method.Attributes.Single(); Assert.AreEqual("System.Runtime.InteropServices.DllImportAttribute", dllImport.AttributeType.Resolve(ctx).FullName); - Assert.AreEqual("unmanaged.dll", dllImport.GetPositionalArguments(ctx)[0].GetValue(ctx)); - Assert.AreEqual((int)CharSet.Unicode, dllImport.GetNamedArguments(ctx).Single().Value.GetValue(ctx)); + Assert.AreEqual("unmanaged.dll", dllImport.GetPositionalArguments(ctx)[0].ConstantValue); + Assert.AreEqual((int)CharSet.Unicode, dllImport.GetNamedArguments(ctx).Single().Value.ConstantValue); } [Test] @@ -340,7 +390,7 @@ namespace ICSharpCode.NRefactory.TypeSystem { IMethod method = ctx.GetTypeDefinition(typeof(NonCustomAttributes)).Methods.Single(m => m.Name == "DllMethod"); IAttribute marshalAs = method.ReturnTypeAttributes.Single(); - Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.GetPositionalArguments(ctx).Single().GetValue(ctx)); + Assert.AreEqual((int)UnmanagedType.Bool, marshalAs.GetPositionalArguments(ctx).Single().ConstantValue); } [Test] @@ -364,14 +414,14 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.IsTrue(p.Type is ArrayTypeReference); } - [Test, Ignore("C# Parser does not set the variance")] + [Test] public void GenericDelegate_Variance() { ITypeDefinition type = ctx.GetTypeDefinition(typeof(GenericDelegate<,>)); Assert.AreEqual(VarianceModifier.Contravariant, type.TypeParameters[0].Variance); Assert.AreEqual(VarianceModifier.Covariant, type.TypeParameters[1].Variance); - Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].Constraints[0]); + Assert.AreSame(type.TypeParameters[1], type.TypeParameters[0].Constraints[0].Resolve(ctx)); } [Test] @@ -394,5 +444,37 @@ namespace ICSharpCode.NRefactory.TypeSystem Assert.AreEqual("System.Object", m.ReturnType.Resolve(ctx).FullName); Assert.AreEqual("System.String", m.Parameters[0].Type.Resolve(ctx).FullName); } + + [Test] + public void ComInterfaceTest() + { + ITypeDefinition type = ctx.GetTypeDefinition(typeof(IAssemblyEnum)); + // [ComImport] + Assert.AreEqual(1, type.Attributes.Count(a => a.AttributeType.Resolve(ctx).FullName == typeof(ComImportAttribute).FullName)); + + IMethod m = type.Methods.Single(); + Assert.AreEqual("GetNextAssembly", m.Name); + Assert.AreEqual(Accessibility.Public, m.Accessibility); + Assert.IsTrue(m.IsAbstract); + Assert.IsFalse(m.IsVirtual); + } + + [Test] + public void ConstantAnswer() + { + ITypeDefinition type = ctx.GetTypeDefinition(typeof(ConstantTest)); + IField answer = type.Fields.Single(f => f.Name == "Answer"); + Assert.IsTrue(answer.IsConst); + Assert.AreEqual(42, answer.ConstantValue.Resolve(ctx).ConstantValue); + } + + [Test] + public void ConstantNullString() + { + ITypeDefinition type = ctx.GetTypeDefinition(typeof(ConstantTest)); + IField answer = type.Fields.Single(f => f.Name == "NullString"); + Assert.IsTrue(answer.IsConst); + Assert.IsNull(answer.ConstantValue.Resolve(ctx).ConstantValue); + } } } diff --git a/ICSharpCode.NRefactory.Tests/Untested.cs b/ICSharpCode.NRefactory.Tests/Untested.cs deleted file mode 100644 index 3555418c4..000000000 --- a/ICSharpCode.NRefactory.Tests/Untested.cs +++ /dev/null @@ -1,41 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.NRefactory -{ - // This file contains unit tests from SharpDevelop 4.0 which are not (yet) ported to NRefactory - - /* - - class ReflectionOrCecilLayerTests { - [Test] - public void ParameterComparisonTest() - { - DefaultParameter p1 = new DefaultParameter("a", mscorlib.GetClass("System.String", 0).DefaultReturnType, DomRegion.Empty); - DefaultParameter p2 = new DefaultParameter("b", new GetClassReturnType(mscorlib, "System.String", 0), DomRegion.Empty); - IList a1 = new List(); - IList a2 = new List(); - a1.Add(p1); - a2.Add(p2); - Assert.AreEqual(0, DiffUtility.Compare(a1, a2)); - } - - [Test] - public void GenericDocumentationTagNamesTest() - { - DefaultClass c = (DefaultClass)mscorlib.GetClass("System.Collections.Generic.List", 1); - Assert.AreEqual("T:System.Collections.Generic.List`1", - c.DocumentationTag); - Assert.AreEqual("M:System.Collections.Generic.List`1.Add(`0)", - GetMethod(c, "Add").DocumentationTag); - Assert.AreEqual("M:System.Collections.Generic.List`1.AddRange(System.Collections.Generic.IEnumerable{`0})", - GetMethod(c, "AddRange").DocumentationTag); - Assert.AreEqual("M:System.Collections.Generic.List`1.ConvertAll``1(System.Converter{`0,``0})", - GetMethod(c, "ConvertAll").DocumentationTag); - } - } - - */ -} diff --git a/ICSharpCode.NRefactory.Tests/Utils/CSharpPrimitiveCastTests.cs b/ICSharpCode.NRefactory.Tests/Utils/CSharpPrimitiveCastTests.cs index fc73adcd7..2207011b4 100644 --- a/ICSharpCode.NRefactory.Tests/Utils/CSharpPrimitiveCastTests.cs +++ b/ICSharpCode.NRefactory.Tests/Utils/CSharpPrimitiveCastTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 NUnit.Framework; diff --git a/ICSharpCode.NRefactory.Tests/Utils/TreeTraversalTests.cs b/ICSharpCode.NRefactory.Tests/Utils/TreeTraversalTests.cs index dae0f43c8..e655fe80d 100644 --- a/ICSharpCode.NRefactory.Tests/Utils/TreeTraversalTests.cs +++ b/ICSharpCode.NRefactory.Tests/Utils/TreeTraversalTests.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj b/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj index f0da0835c..aab1620cb 100644 --- a/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj +++ b/ICSharpCode.NRefactory.VB.Tests/ICSharpCode.NRefactory.VB.Tests.csproj @@ -15,7 +15,6 @@ Library ..\..\..\..\bin\UnitTests\ False - x86 4 v4.0 false @@ -43,11 +42,27 @@ Auto 4194304 4096 + AnyCPU + + + True + DEBUG + False + + + True + False + + + False + Auto + 4194304 + 4096 + x86 - ..\lib\nunit.framework.dll - True + ..\..\Mono.Cecil\Test\libs\nunit-2.4.8\nunit.framework.dll diff --git a/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs b/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs index 553ba27a6..8525f63f8 100644 --- a/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs +++ b/ICSharpCode.NRefactory.VB.Tests/Lexer/LexerPositionTests.cs @@ -23,15 +23,15 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer Token t = l.NextToken(); Assert.AreEqual(Tokens.Public, t.Kind); Assert.AreEqual(new AstLocation(1, 1), t.Location); - Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + Assert.AreEqual(new AstLocation(1, 7), t.EndLocation); t = l.NextToken(); Assert.AreEqual(Tokens.EOL, t.Kind); - Assert.AreEqual(new AstLocation(7, 1), t.Location); - Assert.AreEqual(new AstLocation(1, 2), t.EndLocation); + Assert.AreEqual(new AstLocation(1, 7), t.Location); + Assert.AreEqual(new AstLocation(2, 1), t.EndLocation); t = l.NextToken(); Assert.AreEqual(Tokens.Static, t.Kind); - Assert.AreEqual(new AstLocation(1, 2), t.Location); - Assert.AreEqual(new AstLocation(7, 2), t.EndLocation); + Assert.AreEqual(new AstLocation(2, 1), t.Location); + Assert.AreEqual(new AstLocation(2, 7), t.EndLocation); } [Test] @@ -41,15 +41,15 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer Token t = l.NextToken(); Assert.AreEqual(Tokens.Public, t.Kind); Assert.AreEqual(new AstLocation(1, 1), t.Location); - Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + Assert.AreEqual(new AstLocation(1, 7), t.EndLocation); t = l.NextToken(); Assert.AreEqual(Tokens.EOL, t.Kind); - Assert.AreEqual(new AstLocation(7, 1), t.Location); - Assert.AreEqual(new AstLocation(1, 2), t.EndLocation); + Assert.AreEqual(new AstLocation(1, 7), t.Location); + Assert.AreEqual(new AstLocation(2, 1), t.EndLocation); t = l.NextToken(); Assert.AreEqual(Tokens.Static, t.Kind); - Assert.AreEqual(new AstLocation(1, 2), t.Location); - Assert.AreEqual(new AstLocation(7, 2), t.EndLocation); + Assert.AreEqual(new AstLocation(2, 1), t.Location); + Assert.AreEqual(new AstLocation(2, 7), t.EndLocation); } [Test] @@ -59,13 +59,13 @@ namespace ICSharpCode.NRefactory.VB.Tests.Lexer l.NextToken(); // public Token t = l.NextToken(); Assert.AreEqual(Tokens.EOL, t.Kind); - Assert.AreEqual(new AstLocation(7, 1), t.Location); - Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + Assert.AreEqual(new AstLocation(1, 7), t.Location); + Assert.AreEqual(new AstLocation(1, 7), t.EndLocation); t = l.NextToken(); Assert.AreEqual(Tokens.EOF, t.Kind); - Assert.AreEqual(new AstLocation(7, 1), t.Location); - Assert.AreEqual(new AstLocation(7, 1), t.EndLocation); + Assert.AreEqual(new AstLocation(1, 7), t.Location); + Assert.AreEqual(new AstLocation(1, 7), t.EndLocation); } [Test] diff --git a/ICSharpCode.NRefactory.VB/Ast/AstLocation.cs b/ICSharpCode.NRefactory.VB/Ast/AstLocation.cs deleted file mode 100644 index 4a3a1bc68..000000000 --- a/ICSharpCode.NRefactory.VB/Ast/AstLocation.cs +++ /dev/null @@ -1,137 +0,0 @@ -// -// DomLocation.cs -// -// Author: -// Mike Krüger -// -// Copyright (C) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -namespace ICSharpCode.NRefactory.VB -{ - [Serializable] - public struct AstLocation : IComparable, IEquatable - { - public static readonly AstLocation Empty = new AstLocation(0, 0); - - readonly int line, column; - - public AstLocation (int line, int column) - { - this.line = line; - this.column = column; - } - - public bool IsEmpty { - get { - return line <= 0; - } - } - - public int Line { - get { return line; } - } - - public int Column { - get { return column; } - } - - public override bool Equals (object obj) - { - if (!(obj is AstLocation)) - return false; - return (AstLocation)obj == this; - } - - public override int GetHashCode () - { - unchecked { - return line + column * 5000; - } - } - - public bool Equals (AstLocation other) - { - return other == this; - } - - public int CompareTo (AstLocation other) - { - if (this == other) - return 0; - if (this < other) - return -1; - return 1; - } - - public override string ToString () - { - return String.Format ("(Line {0}, Column {1})", Line, Column); - } - - public static AstLocation FromInvariantString (string invariantString) - { - if (string.Equals(invariantString, "EMPTY", StringComparison.OrdinalIgnoreCase)) - return AstLocation.Empty; - string[] splits = invariantString.Split (',', '/'); - if (splits.Length == 2) - return new AstLocation (Int32.Parse (splits[0]), Int32.Parse (splits[1])); - return AstLocation.Empty; - } - - public string ToInvariantString () - { - if (IsEmpty) - return "Empty"; - return String.Format ("{0}/{1}", line, column); - } - - public static bool operator==(AstLocation left, AstLocation right) - { - return left.line == right.line && left.column == right.column; - } - - public static bool operator!=(AstLocation left, AstLocation right) - { - return left.line != right.line || left.column != right.column; - } - - public static bool operator<(AstLocation left, AstLocation right) - { - return left.line < right.line || left.line == right.line && left.column < right.column; - } - public static bool operator>(AstLocation left, AstLocation right) - { - return left.line > right.line || left.line == right.line && left.column > right.column; - } - public static bool operator<=(AstLocation left, AstLocation right) - { - return !(left > right); - } - public static bool operator>=(AstLocation left, AstLocation right) - { - return !(left < right); - } - } -} diff --git a/ICSharpCode.NRefactory.VB/Ast/AstNode.cs b/ICSharpCode.NRefactory.VB/Ast/AstNode.cs index 7a79baf68..448ae471b 100644 --- a/ICSharpCode.NRefactory.VB/Ast/AstNode.cs +++ b/ICSharpCode.NRefactory.VB/Ast/AstNode.cs @@ -1,28 +1,5 @@ -// -// AstNode.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2009 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections; @@ -105,20 +82,20 @@ namespace ICSharpCode.NRefactory.VB } } - public virtual AstLocation StartLocation { + public virtual TextLocation StartLocation { get { var child = firstChild; if (child == null) - return AstLocation.Empty; + return TextLocation.Empty; return child.StartLocation; } } - public virtual AstLocation EndLocation { + public virtual TextLocation EndLocation { get { var child = lastChild; if (child == null) - return AstLocation.Empty; + return TextLocation.Empty; return child.EndLocation; } } @@ -532,13 +509,13 @@ namespace ICSharpCode.NRefactory.VB public static readonly Role XmlIdentifier = new Role("XmlIdentifier", Ast.XmlIdentifier.Null); public static readonly Role XmlLiteralString = new Role("XmlLiteralString", Ast.XmlLiteralString.Null); -// public static readonly Role Body = new Role("Body", CSharp.BlockStatement.Null); + public static readonly Role Body = new Role("Body", Ast.BlockStatement.Null); public static readonly Role Parameter = new Role("Parameter"); public static readonly Role Argument = new Role("Argument", Ast.Expression.Null); public static readonly Role Type = new Role("Type", AstType.Null); public static readonly Role Expression = new Role("Expression", Ast.Expression.Null); -// public static readonly Role TargetExpression = new Role("Target", CSharp.Expression.Null); -// public readonly static Role Condition = new Role("Condition", CSharp.Expression.Null); + public static readonly Role TargetExpression = new Role("Target", Ast.Expression.Null); + public readonly static Role Condition = new Role("Condition", Ast.Expression.Null); // public static readonly Role TypeParameter = new Role("TypeParameter"); public static readonly Role TypeArgument = new Role("TypeArgument", AstType.Null); @@ -558,6 +535,7 @@ namespace ICSharpCode.NRefactory.VB public static readonly Role LChevron = new Role("LChevron", VBTokenNode.Null); public static readonly Role RChevron = new Role("RChevron", VBTokenNode.Null); public static readonly Role Comma = new Role("Comma", VBTokenNode.Null); + public static readonly Role QuestionMark = new Role("QuestionMark", VBTokenNode.Null); public static readonly Role Dot = new Role("Dot", VBTokenNode.Null); public static readonly Role Semicolon = new Role("Semicolon", VBTokenNode.Null); public static readonly Role Assign = new Role("Assign", VBTokenNode.Null); @@ -579,8 +557,5 @@ namespace ICSharpCode.NRefactory.VB } } - public class Comment - { - - } + } diff --git a/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs b/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs index 236f27a0b..aa91bb5c9 100644 --- a/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs +++ b/ICSharpCode.NRefactory.VB/Ast/AstNodeCollection.cs @@ -133,28 +133,17 @@ namespace ICSharpCode.NRefactory.VB } #region Equals and GetHashCode implementation - public override bool Equals(object obj) - { - if (obj is AstNodeCollection) { - return ((AstNodeCollection)obj) == this; - } else { - return false; - } - } - public override int GetHashCode() { return node.GetHashCode() ^ role.GetHashCode(); } - public static bool operator ==(AstNodeCollection left, AstNodeCollection right) - { - return left.role == right.role && left.node == right.node; - } - - public static bool operator !=(AstNodeCollection left, AstNodeCollection right) + public override bool Equals(object obj) { - return !(left.role == right.role && left.node == right.node); + AstNodeCollection other = obj as AstNodeCollection; + if (other == null) + return false; + return this.node == other.node && this.role == other.role; } #endregion diff --git a/ICSharpCode.NRefactory.VB/Ast/Comment.cs b/ICSharpCode.NRefactory.VB/Ast/Comment.cs new file mode 100644 index 000000000..fc3a600d8 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Comment.cs @@ -0,0 +1,67 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB +{ + public class Comment : AstNode + { + public bool IsDocumentationComment { get; set; } + + public bool StartsLine { + get; + set; + } + + public string Content { + get; + set; + } + + TextLocation startLocation; + public override TextLocation StartLocation { + get { + return startLocation; + } + } + + TextLocation endLocation; + public override TextLocation EndLocation { + get { + return endLocation; + } + } + + public Comment (string content, bool isDocumentation = false) + { + this.IsDocumentationComment = isDocumentation; + this.Content = content; + } + + public Comment (bool isDocumentation, TextLocation startLocation, TextLocation endLocation) + { + this.IsDocumentationComment = isDocumentation; + this.startLocation = startLocation; + this.endLocation = endLocation; + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitComment(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + Comment o = other as Comment; + return o != null && this.IsDocumentationComment == o.IsDocumentationComment && MatchString(this.Content, o.Content); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Enums.cs b/ICSharpCode.NRefactory.VB/Ast/Enums.cs index d0fc13929..a3fa8d618 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Enums.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Enums.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -45,6 +45,12 @@ namespace ICSharpCode.NRefactory.VB.Ast ParamArray = 0x800000, Optional = 0x1000000, + Narrowing = 0x2000000, + Widening = 0x4000000, + + Iterator = 0x8000000, + Async = 0x10000000, + /// /// Special value used to match any modifiers during pattern matching. /// @@ -67,13 +73,6 @@ namespace ICSharpCode.NRefactory.VB.Ast Ref } - public enum VarianceModifier - { - Invariant, - Covariant, - Contravariant - }; - public enum AssignmentOperatorType { None, @@ -83,7 +82,6 @@ namespace ICSharpCode.NRefactory.VB.Ast Subtract, Multiply, Divide, - Modulus, Power, // (VB only) DivideInteger, // (VB only) @@ -91,117 +89,6 @@ namespace ICSharpCode.NRefactory.VB.Ast ShiftLeft, ShiftRight, - - BitwiseAnd, - BitwiseOr, - ExclusiveOr, - } - - public enum BinaryOperatorType - { - None, - - /// '&' in C#, 'And' in VB. - BitwiseAnd, - /// '|' in C#, 'Or' in VB. - BitwiseOr, - /// '&&' in C#, 'AndAlso' in VB. - LogicalAnd, - /// '||' in C#, 'OrElse' in VB. - LogicalOr, - /// '^' in C#, 'Xor' in VB. - ExclusiveOr, - - /// > - GreaterThan, - /// >= - GreaterThanOrEqual, - /// '==' in C#, '=' in VB. - Equality, - /// '!=' in C#, '<>' in VB. - InEquality, - /// < - LessThan, - /// <= - LessThanOrEqual, - - /// + - Add, - /// - - Subtract, - /// * - Multiply, - /// / - Divide, - /// '%' in C#, 'Mod' in VB. - Modulus, - /// VB-only: \ - DivideInteger, - /// VB-only: ^ - Power, - /// VB-only: & - Concat, - - /// C#: << - ShiftLeft, - /// C#: >> - ShiftRight, - /// VB-only: Is - ReferenceEquality, - /// VB-only: IsNot - ReferenceInequality, - - /// VB-only: Like - Like, - /// - /// C#: ?? - /// VB: IF(x, y) - /// - NullCoalescing, - - /// VB-only: ! - DictionaryAccess - } - - public enum CastType - { - /// - /// direct cast (C#, VB "DirectCast") - /// - Cast, - /// - /// try cast (C# "as", VB "TryCast") - /// - TryCast, - /// - /// converting cast (VB "CType") - /// - Conversion, - /// - /// primitive converting cast (VB "CString" etc.) - /// - PrimitiveConversion - } - - public enum UnaryOperatorType - { - None, - Not, - BitNot, - - Minus, - Plus, - - Increment, - Decrement, - - PostIncrement, - PostDecrement, - - /// Dereferencing pointer - Dereference, - /// Get address of - AddressOf } public enum ContinueType @@ -215,38 +102,12 @@ namespace ICSharpCode.NRefactory.VB.Ast public enum ConditionType { None, - Until, - While, + LoopUntil, + LoopWhile, + DoUntil, DoWhile } - public enum ConditionPosition - { - None, - Start, - End - } - - public enum ExitType - { - None, - Sub, - Function, - Property, - Do, - For, - While, - Select, - Try - } - - public enum ConstructorInitializerType - { - None, - Base, - This - } - public enum ConversionType { None, @@ -254,66 +115,10 @@ namespace ICSharpCode.NRefactory.VB.Ast Explicit } - public enum OverloadableOperatorType - { - None, - - Add, - Subtract, - Multiply, - Divide, - Modulus, - Concat, - - UnaryPlus, - UnaryMinus, - - Not, - BitNot, - - BitwiseAnd, - BitwiseOr, - ExclusiveOr, - - ShiftLeft, - ShiftRight, - - GreaterThan, - GreaterThanOrEqual, - Equality, - InEquality, - LessThan, - LessThanOrEqual, - - Increment, - Decrement, - - IsTrue, - IsFalse, - - // VB specific - Like, - Power, - CType, - DivideInteger - } - - /// - /// Charset types, used in external methods - /// declarations (VB only). - /// - public enum CharsetModifier - { - None, - Auto, - Unicode, - Ansi - } - /// /// Specifies the ordering direction of a QueryExpressionOrdering node. /// - public enum QueryExpressionOrderingDirection + public enum QueryOrderingDirection { None, Ascending, @@ -324,7 +129,7 @@ namespace ICSharpCode.NRefactory.VB.Ast /// Specifies the partition type for a VB.NET /// query expression. /// - public enum QueryExpressionPartitionType + public enum PartitionKind { Take, TakeWhile, diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/AnonymousObjectCreationExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/AnonymousObjectCreationExpression.cs new file mode 100644 index 000000000..ac3f8d0da --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/AnonymousObjectCreationExpression.cs @@ -0,0 +1,41 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class AnonymousObjectCreationExpression : Expression + { + public AstNodeCollection Initializer { + get { return GetChildrenByRole(Roles.Expression); } + } + + public AnonymousObjectCreationExpression () + { + } + + public AnonymousObjectCreationExpression (IEnumerable initializer) + { + foreach (var ini in initializer) { + AddChild (ini, Roles.Expression); + } + } + + public AnonymousObjectCreationExpression (params Expression[] initializer) : this ((IEnumerable)initializer) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitAnonymousObjectCreationExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as AnonymousObjectCreationExpression; + return o != null && this.Initializer.DoMatch(o.Initializer, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs new file mode 100644 index 000000000..b3f580894 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayCreateExpression.cs @@ -0,0 +1,64 @@ +// Copyright (c) 2011 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; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// New Type[Dimensions] + /// + public class ArrayCreateExpression : Expression + { + public readonly static Role AdditionalArraySpecifierRole = new Role("AdditionalArraySpecifier"); + public readonly static Role InitializerRole = new Role("Initializer", ArrayInitializerExpression.Null); + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole (Roles.Argument); } + } + + /// + /// Gets additional array ranks (those without size info). + /// Empty for "New Integer(5,1)"; will contain a single element for "New Integer(5)()". + /// + public AstNodeCollection AdditionalArraySpecifiers { + get { return GetChildrenByRole(AdditionalArraySpecifierRole); } + } + + public ArrayInitializerExpression Initializer { + get { return GetChildByRole (InitializerRole); } + set { SetChildByRole (InitializerRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitArrayCreateExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ArrayCreateExpression o = other as ArrayCreateExpression; + return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match) && this.AdditionalArraySpecifiers.DoMatch(o.AdditionalArraySpecifiers, match) && this.Initializer.DoMatch(o.Initializer, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayInitializerExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayInitializerExpression.cs new file mode 100644 index 000000000..785f2c19b --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/ArrayInitializerExpression.cs @@ -0,0 +1,53 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// { Elements } + /// + public class ArrayInitializerExpression : Expression + { + #region Null + public new static readonly ArrayInitializerExpression Null = new NullArrayInitializerExpression (); + + sealed class NullArrayInitializerExpression : ArrayInitializerExpression + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public readonly static Role InitializerRole = new Role("Initializer", ArrayInitializerExpression.Null); + + public AstNodeCollection Elements { + get { return GetChildrenByRole(Roles.Expression); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitArrayInitializerExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ArrayInitializerExpression o = other as ArrayInitializerExpression; + return o != null && this.Elements.DoMatch(o.Elements, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/AssignmentExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/AssignmentExpression.cs new file mode 100644 index 000000000..bab517a57 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/AssignmentExpression.cs @@ -0,0 +1,44 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class AssignmentExpression : Expression + { + public readonly static Role LeftExpressionRole = BinaryOperatorExpression.LeftExpressionRole; + public readonly static Role OperatorRole = BinaryOperatorExpression.OperatorRole; + public readonly static Role RightExpressionRole = BinaryOperatorExpression.RightExpressionRole; + + public AssignmentExpression(Expression left, AssignmentOperatorType type, Expression right) + { + AddChild(left, LeftExpressionRole); + AddChild(right, RightExpressionRole); + Operator = type; + } + + public Expression Left { + get { return GetChildByRole(LeftExpressionRole); } + set { SetChildByRole(LeftExpressionRole, value); } + } + + public AssignmentOperatorType Operator { get; set; } + + public Expression Right { + get { return GetChildByRole(RightExpressionRole); } + set { SetChildByRole(RightExpressionRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitAssignmentExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/BinaryOperatorExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/BinaryOperatorExpression.cs new file mode 100644 index 000000000..b83a0909f --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/BinaryOperatorExpression.cs @@ -0,0 +1,110 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class BinaryOperatorExpression : Expression + { + public readonly static Role LeftExpressionRole = new Role("Left"); + public readonly static Role OperatorRole = new Role("Operator"); + public readonly static Role RightExpressionRole = new Role("Right"); + + public BinaryOperatorExpression(Expression left, BinaryOperatorType type, Expression right) + { + AddChild(left, LeftExpressionRole); + AddChild(right, RightExpressionRole); + Operator = type; + } + + public Expression Left { + get { return GetChildByRole(LeftExpressionRole); } + set { SetChildByRole(LeftExpressionRole, value); } + } + + public BinaryOperatorType Operator { get; set; } + + public Expression Right { + get { return GetChildByRole(RightExpressionRole); } + set { SetChildByRole(RightExpressionRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitBinaryOperatorExpression(this, data); + } + } + + public enum BinaryOperatorType + { + None, + + /// '&' in C#, 'And' in VB. + BitwiseAnd, + /// '|' in C#, 'Or' in VB. + BitwiseOr, + /// '&&' in C#, 'AndAlso' in VB. + LogicalAnd, + /// '||' in C#, 'OrElse' in VB. + LogicalOr, + /// '^' in C#, 'Xor' in VB. + ExclusiveOr, + + /// > + GreaterThan, + /// >= + GreaterThanOrEqual, + /// '==' in C#, '=' in VB. + Equality, + /// '!=' in C#, '<>' in VB. + InEquality, + /// < + LessThan, + /// <= + LessThanOrEqual, + + /// + + Add, + /// - + Subtract, + /// * + Multiply, + /// / + Divide, + /// '%' in C#, 'Mod' in VB. + Modulus, + /// VB-only: \ + DivideInteger, + /// VB-only: ^ + Power, + /// VB-only: & + Concat, + + /// C#: << + ShiftLeft, + /// C#: >> + ShiftRight, + /// VB-only: Is + ReferenceEquality, + /// VB-only: IsNot + ReferenceInequality, + + /// VB-only: Like + Like, + /// + /// C#: ?? + /// VB: IF(x, y) + /// + NullCoalescing, + + /// VB-only: ! + DictionaryAccess + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs new file mode 100644 index 000000000..5cdbd3fa6 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/CastExpression.cs @@ -0,0 +1,95 @@ +// Copyright (c) 2011 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; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// CastType(Expression, AstType) + /// + public class CastExpression : Expression + { + public CastType CastType { get; set; } + + public VBTokenNode CastTypeToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public CastExpression () + { + } + + public CastExpression (CastType castType, AstType castToType, Expression expression) + { + CastType = castType; + AddChild (castToType, Roles.Type); + AddChild (expression, Roles.Expression); + } + + public CastExpression (CastType castType, Expression expression) + { + CastType = castType; + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCastExpression (this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CastExpression o = other as CastExpression; + return o != null && this.CastType == o.CastType && this.Type.DoMatch(o.Type, match) && this.Expression.DoMatch(o.Expression, match); + } + } + + public enum CastType + { + DirectCast, + TryCast, + CType, + CBool, + CByte, + CChar, + CDate, + CDec, + CDbl, + CInt, + CLng, + CObj, + CSByte, + CShort, + CSng, + CStr, + CUInt, + CULng, + CUShort + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/CollectionRangeVariableDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/CollectionRangeVariableDeclaration.cs new file mode 100644 index 000000000..711341d0c --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/CollectionRangeVariableDeclaration.cs @@ -0,0 +1,42 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Identifier As Type In Expression + /// + public class CollectionRangeVariableDeclaration : AstNode + { + public static readonly Role CollectionRangeVariableDeclarationRole = new Role("CollectionRangeVariableDeclaration"); + + public VariableIdentifier Identifier { + get { return GetChildByRole(VariableIdentifier.VariableIdentifierRole); } + set { SetChildByRole(VariableIdentifier.VariableIdentifierRole, value); } + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitCollectionRangeVariableDeclaration(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + CollectionRangeVariableDeclaration o = other as CollectionRangeVariableDeclaration; + return o != null && this.Identifier.DoMatch(o.Identifier, match) && this.Type.DoMatch(o.Type, match) && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/ConditionalExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/ConditionalExpression.cs new file mode 100644 index 000000000..4b53d5663 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/ConditionalExpression.cs @@ -0,0 +1,44 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class ConditionalExpression : Expression + { + public readonly static Role ConditionExpressionRole = new Role("ConditionExpressionRole", Expression.Null); + public readonly static Role TrueExpressionRole = new Role("TrueExpressionRole", Expression.Null); + public readonly static Role FalseExpressionRole = new Role("FalseExpressionRole", Expression.Null); + + public VBTokenNode IfToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression ConditionExpression { + get { return GetChildByRole (ConditionExpressionRole); } + set { SetChildByRole (ConditionExpressionRole, value); } + } + + public Expression TrueExpression { + get { return GetChildByRole (TrueExpressionRole); } + set { SetChildByRole (TrueExpressionRole, value); } + } + + public Expression FalseExpression { + get { return GetChildByRole (FalseExpressionRole); } + set { SetChildByRole (FalseExpressionRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitConditionalExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/EmptyExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/EmptyExpression.cs new file mode 100644 index 000000000..01b2f140e --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/EmptyExpression.cs @@ -0,0 +1,59 @@ +// Copyright (c) 2011 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; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class EmptyExpression : Expression + { + TextLocation location; + + public override TextLocation StartLocation { + get { + return location; + } + } + + public override TextLocation EndLocation { + get { + return location; + } + } + + public EmptyExpression() + { + } + + public EmptyExpression(TextLocation location) + { + this.location = location; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitEmptyExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + var o = other as EmptyExpression; + return o != null; + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs index d15756e3e..dad5cd933 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/Expression.cs @@ -1,7 +1,8 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Collections.Generic; namespace ICSharpCode.NRefactory.VB.Ast { @@ -29,5 +30,78 @@ namespace ICSharpCode.NRefactory.VB.Ast } } #endregion + + #region Builder methods + /// + /// Builds an member reference expression using this expression as target. + /// + public MemberAccessExpression Member(string memberName) + { + return new MemberAccessExpression { Target = this, MemberName = memberName }; + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable arguments) + { + return Invoke(methodName, null, arguments); + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(string methodName, params Expression[] arguments) + { + return Invoke(methodName, null, arguments); + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable typeArguments, IEnumerable arguments) + { + InvocationExpression ie = new InvocationExpression(); + MemberAccessExpression mre = new MemberAccessExpression(); + mre.Target = this; + mre.MemberName = methodName; + mre.TypeArguments.AddRange(typeArguments); + ie.Target = mre; + ie.Arguments.AddRange(arguments); + return ie; + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(IEnumerable arguments) + { + InvocationExpression ie = new InvocationExpression(); + ie.Target = this; + ie.Arguments.AddRange(arguments); + return ie; + } + + /// + /// Builds an invocation expression using this expression as target. + /// + public InvocationExpression Invoke(params Expression[] arguments) + { + InvocationExpression ie = new InvocationExpression(); + ie.Target = this; + ie.Arguments.AddRange(arguments); + return ie; + } + + public CastExpression CastTo(AstType type) + { + return new CastExpression { CastType = CastType.CType, Type = type, Expression = this }; + } + + public CastExpression CastTo(Type type) + { + return new CastExpression { CastType = CastType.CType, Type = AstType.Create(type), Expression = this }; + } + #endregion } } diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/FieldInitializerExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/FieldInitializerExpression.cs new file mode 100644 index 000000000..bc77666c8 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/FieldInitializerExpression.cs @@ -0,0 +1,49 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// [ Key ] .Identifier = Expression + /// + public class FieldInitializerExpression : Expression + { + public bool IsKey { get; set; } + + public VBTokenNode KeyToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public VBTokenNode DotToken { + get { return GetChildByRole (Roles.Dot); } + } + + public Identifier Identifier { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public VBTokenNode 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.VisitFieldInitializerExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + FieldInitializerExpression o = other as FieldInitializerExpression; + return o != null && this.IsKey == o.IsKey && this.Identifier.DoMatch(o.Identifier, match) && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs new file mode 100644 index 000000000..573d1cf8b --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetTypeExpression.cs @@ -0,0 +1,31 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class GetTypeExpression : Expression + { + public GetTypeExpression() + { + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as GetTypeExpression; + return expr != null && + Type.DoMatch(expr.Type, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitGetTypeExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs new file mode 100644 index 000000000..390281d3f --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/GetXmlNamespaceExpression.cs @@ -0,0 +1,32 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class GetXmlNamespaceExpression : Expression + { + public GetXmlNamespaceExpression(XmlIdentifier namespaceName) + { + SetChildByRole(Roles.XmlIdentifier, namespaceName); + } + + public XmlIdentifier NamespaceName { + get { return GetChildByRole(Roles.XmlIdentifier); } + set { SetChildByRole(Roles.XmlIdentifier, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as GetXmlNamespaceExpression; + return expr != null && + NamespaceName.DoMatch(expr.NamespaceName, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitGetXmlNamespaceExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/IdentifierExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/IdentifierExpression.cs new file mode 100644 index 000000000..6bd77cb9b --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/IdentifierExpression.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class IdentifierExpression : Expression + { + public IdentifierExpression() + { + + } + + public IdentifierExpression(Identifier identifier) + { + this.Identifier = identifier; + } + + public Identifier Identifier { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole(Roles.TypeArgument); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitIdentifierExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/InstanceExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/InstanceExpression.cs new file mode 100644 index 000000000..321d387e9 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/InstanceExpression.cs @@ -0,0 +1,61 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of InstanceExpression. + /// + public class InstanceExpression : Expression + { + TextLocation location; + + public InstanceExpression(InstanceExpressionType type, TextLocation location) + { + this.Type = type; + this.location = location; + } + + public override TextLocation StartLocation { + get { return location; } + } + + public override TextLocation EndLocation { + get { + switch (Type) { + case InstanceExpressionType.Me: + return new TextLocation(location.Line, location.Column + "Me".Length); + case InstanceExpressionType.MyBase: + return new TextLocation(location.Line, location.Column + "MyBase".Length); + case InstanceExpressionType.MyClass: + return new TextLocation(location.Line, location.Column + "MyClass".Length); + default: + throw new Exception("Invalid value for InstanceExpressionType"); + } + } + } + + public InstanceExpressionType Type { get; set; } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as InstanceExpression; + return expr != null && + Type == expr.Type; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitInstanceExpression(this, data); + } + } + + public enum InstanceExpressionType + { + Me, + MyBase, + MyClass + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/InvocationExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/InvocationExpression.cs new file mode 100644 index 000000000..6a81c0376 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/InvocationExpression.cs @@ -0,0 +1,52 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Target(Arguments) + /// + public class InvocationExpression : Expression + { + public Expression Target { + get { return GetChildByRole (Roles.TargetExpression); } + set { SetChildByRole(Roles.TargetExpression, value); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole(Roles.Argument); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitInvocationExpression(this, data); + } + + public InvocationExpression () + { + } + + public InvocationExpression (Expression target, IEnumerable arguments) + { + AddChild (target, Roles.TargetExpression); + if (arguments != null) { + foreach (var arg in arguments) { + AddChild (arg, Roles.Argument); + } + } + } + + public InvocationExpression (Expression target, params Expression[] arguments) : this (target, (IEnumerable)arguments) + { + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + InvocationExpression o = other as InvocationExpression; + return o != null && this.Target.DoMatch(o.Target, match) && this.Arguments.DoMatch(o.Arguments, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/LambdaExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/LambdaExpression.cs new file mode 100644 index 000000000..fe238367b --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/LambdaExpression.cs @@ -0,0 +1,124 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public abstract class LambdaExpression : Expression + { + public static readonly Role ModifierRole = AttributedNode.ModifierRole; + + public LambdaExpressionModifiers Modifiers { + get { return GetModifiers(this); } + set { SetModifiers(this, value); } + } + + public AstNodeCollection ModifierTokens { + get { return GetChildrenByRole (ModifierRole); } + } + + internal static LambdaExpressionModifiers GetModifiers(AstNode node) + { + LambdaExpressionModifiers m = 0; + foreach (VBModifierToken t in node.GetChildrenByRole (ModifierRole)) { + m |= (LambdaExpressionModifiers)t.Modifier; + } + return m; + } + + internal static void SetModifiers(AstNode node, LambdaExpressionModifiers newValue) + { + LambdaExpressionModifiers oldValue = GetModifiers(node); + AstNode insertionPos = null; + foreach (Modifiers m in VBModifierToken.AllModifiers) { + if ((m & (Modifiers)newValue) != 0) { + if ((m & (Modifiers)oldValue) == 0) { + // Modifier was added + var newToken = new VBModifierToken(TextLocation.Empty, m); + node.InsertChildAfter(insertionPos, newToken, ModifierRole); + insertionPos = newToken; + } else { + // Modifier already exists + insertionPos = node.GetChildrenByRole(ModifierRole).First(t => t.Modifier == m); + } + } else { + if ((m & (Modifiers)oldValue) != 0) { + // Modifier was removed + node.GetChildrenByRole (ModifierRole).First(t => t.Modifier == m).Remove(); + } + } + } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + } + + public class SingleLineSubLambdaExpression : LambdaExpression + { + public static readonly Role StatementRole = BlockStatement.StatementRole; + + public Statement EmbeddedStatement { + get { return GetChildByRole(StatementRole); } + set { SetChildByRole(StatementRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSingleLineSubLambdaExpression(this, data); + } + } + + public class SingleLineFunctionLambdaExpression : LambdaExpression + { + public Expression EmbeddedExpression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSingleLineFunctionLambdaExpression(this, data); + } + } + + public class MultiLineLambdaExpression : LambdaExpression + { + public bool IsSub { get; set; } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitMultiLineLambdaExpression(this, data); + } + } + + public enum LambdaExpressionModifiers + { + Async = Modifiers.Async, + Iterator = Modifiers.Iterator + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs new file mode 100644 index 000000000..17e805775 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/MemberAccessExpression.cs @@ -0,0 +1,42 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class MemberAccessExpression : Expression + { + public MemberAccessExpression() + { + } + + public Expression Target { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public Identifier MemberName { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole(Roles.TypeArgument); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as MemberAccessExpression; + return expr != null && + Target.DoMatch(expr.Target, match) && + MemberName.DoMatch(expr.MemberName, match) && + TypeArguments.DoMatch(expr.TypeArguments, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitMemberAccessExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/NamedArgumentExpression.cs similarity index 54% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs rename to ICSharpCode.NRefactory.VB/Ast/Expressions/NamedArgumentExpression.cs index 73bcb2e27..730eaafaf 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/NamedArgumentExpression.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/NamedArgumentExpression.cs @@ -1,34 +1,22 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; +using System.Collections.Generic; -namespace ICSharpCode.NRefactory.CSharp +namespace ICSharpCode.NRefactory.VB.Ast { /// /// Represents a named argument passed to a method or attribute. /// public class NamedArgumentExpression : Expression { - public string Identifier { - get { - return GetChildByRole (Roles.Identifier).Name; - } - set { - SetChildByRole(Roles.Identifier, CSharp.Identifier.Create (value, AstLocation.Empty)); - } + public Identifier Identifier { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } } - public Identifier IdentifierToken { - get { - return GetChildByRole (Roles.Identifier); - } - set { - SetChildByRole(Roles.Identifier, value); - } - } - - public CSharpTokenNode AssignToken { + public VBTokenNode AssignToken { get { return GetChildByRole (Roles.Assign); } } @@ -45,7 +33,7 @@ namespace ICSharpCode.NRefactory.CSharp protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { NamedArgumentExpression o = other as NamedArgumentExpression; - return o != null && MatchString(this.Identifier, o.Identifier) && this.Expression.DoMatch(o.Expression, match); + return o != null && this.Identifier.DoMatch(o.Identifier, match) && this.Expression.DoMatch(o.Expression, match); } } } diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/ObjectCreationExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/ObjectCreationExpression.cs new file mode 100644 index 000000000..6e28b292d --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/ObjectCreationExpression.cs @@ -0,0 +1,59 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// New Type(Arguments) { Initializer } + /// + public class ObjectCreationExpression : Expression + { + public readonly static Role InitializerRole = ArrayInitializerExpression.InitializerRole; + + public AstType Type { + get { return GetChildByRole (Roles.Type); } + set { SetChildByRole (Roles.Type, value); } + } + + public AstNodeCollection Arguments { + get { return GetChildrenByRole (Roles.Argument); } + } + + public ArrayInitializerExpression Initializer { + get { return GetChildByRole (InitializerRole); } + set { SetChildByRole (InitializerRole, value); } + } + + public ObjectCreationExpression() + { + } + + public ObjectCreationExpression (AstType type, IEnumerable arguments = null) + { + AddChild (type, Roles.Type); + if (arguments != null) { + foreach (var arg in arguments) { + AddChild (arg, Roles.Argument); + } + } + } + + public ObjectCreationExpression (AstType type, params Expression[] arguments) : this (type, (IEnumerable)arguments) + { + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitObjectCreationExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ObjectCreationExpression o = other as ObjectCreationExpression; + return o != null && this.Type.DoMatch(o.Type, match) && this.Arguments.DoMatch(o.Arguments, match) && this.Initializer.DoMatch(o.Initializer, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/ParenthesizedExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/ParenthesizedExpression.cs new file mode 100644 index 000000000..31c234044 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/ParenthesizedExpression.cs @@ -0,0 +1,34 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Description of ParenthesizedExpression. + /// + public class ParenthesizedExpression : Expression + { + public ParenthesizedExpression() + { + } + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as ParenthesizedExpression; + return expr != null && + Expression.DoMatch(expr.Expression, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitParenthesizedExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/PrimitiveExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/PrimitiveExpression.cs index c01adaf8a..d1d5f2d1f 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Expressions/PrimitiveExpression.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/PrimitiveExpression.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using ICSharpCode.NRefactory.VB.PrettyPrinter; using System; @@ -13,17 +13,17 @@ namespace ICSharpCode.NRefactory.VB.Ast { public static readonly object AnyValue = new object(); - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } } int length; - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation(StartLocation.Line, StartLocation.Column + length); + return new TextLocation(StartLocation.Line, StartLocation.Column + length); } } @@ -32,7 +32,7 @@ namespace ICSharpCode.NRefactory.VB.Ast string stringValue; public string StringValue { - get { return stringValue; } // TODO ?? VBNetOutputVisitor.ToVBNetString(this); } + get { return stringValue ?? OutputVisitor.ToVBNetString(this); } } public PrimitiveExpression(object value) @@ -46,14 +46,14 @@ namespace ICSharpCode.NRefactory.VB.Ast this.stringValue = stringValue; } - public PrimitiveExpression(object value, AstLocation startLocation, int length) + public PrimitiveExpression(object value, TextLocation startLocation, int length) { this.Value = value; this.startLocation = startLocation; this.length = length; } - public PrimitiveExpression(object value, string stringValue, AstLocation startLocation, int length) + public PrimitiveExpression(object value, string stringValue, TextLocation startLocation, int length) { this.Value = value; this.stringValue = stringValue; diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/QueryExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/QueryExpression.cs new file mode 100644 index 000000000..2701d4e89 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/QueryExpression.cs @@ -0,0 +1,348 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class QueryExpression : Expression + { + public AstNodeCollection QueryOperators { + get { return GetChildrenByRole(QueryOperator.QueryOperatorRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitQueryExpression(this, data); + } + } + + public abstract class QueryOperator : AstNode + { + #region Null + public new static readonly QueryOperator Null = new NullQueryOperator(); + + sealed class NullQueryOperator : QueryOperator + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public static readonly Role QueryOperatorRole = new Role("QueryOperator", QueryOperator.Null); + } + + public class FromQueryOperator : QueryOperator + { + public AstNodeCollection Variables { + get { return GetChildrenByRole (CollectionRangeVariableDeclaration.CollectionRangeVariableDeclarationRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitFromQueryOperator(this, data); + } + } + + public class AggregateQueryOperator : QueryOperator + { + public CollectionRangeVariableDeclaration Variable { + get { return GetChildByRole(CollectionRangeVariableDeclaration.CollectionRangeVariableDeclarationRole); } + set { SetChildByRole(CollectionRangeVariableDeclaration.CollectionRangeVariableDeclarationRole, value); } + } + + public AstNodeCollection SubQueryOperators { + get { return GetChildrenByRole(QueryOperatorRole); } + } + + public AstNodeCollection IntoExpressions { + get { return GetChildrenByRole(VariableInitializer.VariableInitializerRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitAggregateQueryOperator(this, data); + } + } + + public class SelectQueryOperator : QueryOperator + { + public AstNodeCollection Variables { + get { return GetChildrenByRole(VariableInitializer.VariableInitializerRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSelectQueryOperator(this, data); + } + } + + public class DistinctQueryOperator : QueryOperator + { + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitDistinctQueryOperator(this, data); + } + } + + public class WhereQueryOperator : QueryOperator + { + public Expression Condition { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitWhereQueryOperator(this, data); + } + } + + public class OrderExpression : AstNode + { + public static readonly Role OrderExpressionRole = new Role("OrderExpression"); + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public QueryOrderingDirection Direction { get; set; } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitOrderExpression(this, data); + } + } + + public class OrderByQueryOperator : QueryOperator + { + public AstNodeCollection Expressions { + get { return GetChildrenByRole(OrderExpression.OrderExpressionRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitOrderByQueryOperator(this, data); + } + } + + public class PartitionQueryOperator : QueryOperator + { + public PartitionKind Kind { get; set; } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPartitionQueryOperator(this, data); + } + } + + public class LetQueryOperator : QueryOperator + { + public AstNodeCollection Variables { + get { return GetChildrenByRole(VariableInitializer.VariableInitializerRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitLetQueryOperator(this, data); + } + } + + public class GroupByQueryOperator : QueryOperator + { + public static readonly Role GroupExpressionRole = new Role("GroupExpression"); + public static readonly Role ByExpressionRole = new Role("ByExpression"); + public static readonly Role IntoExpressionRole = new Role("IntoExpression"); + + public AstNodeCollection GroupExpressions { + get { return GetChildrenByRole(GroupExpressionRole); } + } + + public AstNodeCollection ByExpressions { + get { return GetChildrenByRole(ByExpressionRole); } + } + + public AstNodeCollection IntoExpressions { + get { return GetChildrenByRole(IntoExpressionRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitGroupByQueryOperator(this, data); + } + } + + public class JoinQueryOperator : QueryOperator + { + #region Null + public new static readonly JoinQueryOperator Null = new NullJoinQueryOperator(); + + sealed class NullJoinQueryOperator : JoinQueryOperator + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public static readonly Role JoinQueryOperatorRole = new Role("JoinQueryOperator", JoinQueryOperator.Null); + + public CollectionRangeVariableDeclaration JoinVariable { + get { return GetChildByRole(CollectionRangeVariableDeclaration.CollectionRangeVariableDeclarationRole); } + set { SetChildByRole(CollectionRangeVariableDeclaration.CollectionRangeVariableDeclarationRole, value); } + } + + public JoinQueryOperator SubJoinQuery { + get { return GetChildByRole(JoinQueryOperatorRole); } + set { SetChildByRole(JoinQueryOperatorRole, value); } + } + + public AstNodeCollection JoinConditions { + get { return GetChildrenByRole(JoinCondition.JoinConditionRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitJoinQueryOperator(this, data); + } + } + + public class JoinCondition : AstNode + { + public static readonly Role JoinConditionRole = new Role("JoinCondition"); + + public static readonly Role LeftExpressionRole = BinaryOperatorExpression.LeftExpressionRole; + public static readonly Role RightExpressionRole = BinaryOperatorExpression.RightExpressionRole; + + public Expression Left { + get { return GetChildByRole (LeftExpressionRole); } + set { SetChildByRole (LeftExpressionRole, value); } + } + + public Expression Right { + get { return GetChildByRole (RightExpressionRole); } + set { SetChildByRole (RightExpressionRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitJoinCondition(this, data); + } + } + + public class GroupJoinQueryOperator : JoinQueryOperator + { + public static readonly Role IntoExpressionRole = GroupByQueryOperator.IntoExpressionRole; + + public AstNodeCollection IntoExpressions { + get { return GetChildrenByRole(IntoExpressionRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitGroupJoinQueryOperator(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs index 257b8e744..0face5c9e 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/SimpleNameExpression.cs @@ -1,22 +1,27 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; namespace ICSharpCode.NRefactory.VB.Ast { /// - /// Description of IdentifierExpression. + /// Description of SimpleNameExpression. /// public class SimpleNameExpression : Expression { public Identifier Identifier { get; set; } + public AstNodeCollection TypeArguments { + get { return GetChildrenByRole(Roles.TypeArgument); } + } + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { var node = other as SimpleNameExpression; return node != null - && Identifier.DoMatch(node.Identifier, match); + && Identifier.DoMatch(node.Identifier, match) + && TypeArguments.DoMatch(node.TypeArguments, match); } public override S AcceptVisitor(IAstVisitor visitor, T data) diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs new file mode 100644 index 000000000..54ef20f94 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeOfIsExpression.cs @@ -0,0 +1,37 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class TypeOfIsExpression : Expression + { + public TypeOfIsExpression() + { + } + + public Expression TypeOfExpression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as TypeOfIsExpression; + return expr != null && + TypeOfExpression.DoMatch(expr.TypeOfExpression, match) && + Type.DoMatch(expr.Type, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitTypeOfIsExpression(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeReferenceExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeReferenceExpression.cs similarity index 76% rename from ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeReferenceExpression.cs rename to ICSharpCode.NRefactory.VB/Ast/Expressions/TypeReferenceExpression.cs index 9104235f8..d163fcd77 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Expressions/TypeReferenceExpression.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/TypeReferenceExpression.cs @@ -1,13 +1,13 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) // This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; -namespace ICSharpCode.NRefactory.CSharp +namespace ICSharpCode.NRefactory.VB.Ast { /// /// Represents an AstType as an expression. - /// This is used when calling a method on a primitive type: "int.Parse()" + /// This is used when calling a method on a primitive type: "Integer.Parse()" /// public class TypeReferenceExpression : Expression { @@ -27,7 +27,7 @@ namespace ICSharpCode.NRefactory.CSharp public TypeReferenceExpression (AstType type) { - AddChild (type, Roles.Type); + SetChildByRole(Roles.Type, type); } protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/UnaryOperatorExpression.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/UnaryOperatorExpression.cs new file mode 100644 index 000000000..787698484 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/UnaryOperatorExpression.cs @@ -0,0 +1,80 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Operator Expression + /// + public class UnaryOperatorExpression : Expression + { + public readonly static Role OperatorRole = BinaryOperatorExpression.OperatorRole; + + public UnaryOperatorExpression() + { + } + + public UnaryOperatorExpression(UnaryOperatorType op, Expression expression) + { + this.Operator = op; + this.Expression = expression; + } + + public UnaryOperatorType Operator { + get; + set; + } + + public VBTokenNode OperatorToken { + get { return GetChildByRole (OperatorRole); } + } + + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitUnaryOperatorExpression(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + UnaryOperatorExpression o = other as UnaryOperatorExpression; + return o != null && this.Operator == o.Operator && this.Expression.DoMatch(o.Expression, match); + } + + public static string GetOperatorSymbol(UnaryOperatorType op) + { + switch (op) { + case UnaryOperatorType.Not: + return "Not"; + case UnaryOperatorType.Minus: + return "-"; + case UnaryOperatorType.Plus: + return "+"; + default: + throw new NotSupportedException("Invalid value for UnaryOperatorType"); + } + } + } + + public enum UnaryOperatorType + { + /// Logical/Bitwise not (Not a) + Not, + /// Unary minus (-a) + Minus, + /// Unary plus (+a) + Plus, + /// AddressOf + AddressOf, + /// Await + Await + } + +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/VariableInitializer.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/VariableInitializer.cs new file mode 100644 index 000000000..7d1cb87e7 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/VariableInitializer.cs @@ -0,0 +1,46 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Identifier As Type = Expression + /// + public class VariableInitializer : AstNode + { + public static readonly Role VariableInitializerRole = new Role("VariableInitializer"); + + public VariableIdentifier Identifier { + get { return GetChildByRole(VariableIdentifier.VariableIdentifierRole); } + set { SetChildByRole(VariableIdentifier.VariableIdentifierRole, value); } + } + + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public VBTokenNode 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.VisitVariableInitializer(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + VariableInitializer o = other as VariableInitializer; + return o != null && this.Identifier.DoMatch(o.Identifier, match) && this.Type.DoMatch(o.Type, match) && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlIdentifier.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlIdentifier.cs index 7d3a6ca0b..3b45d5a60 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlIdentifier.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlIdentifier.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -33,13 +33,13 @@ namespace ICSharpCode.NRefactory.VB.Ast public string Name { get; set; } - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } } - AstLocation endLocation; - public override AstLocation EndLocation { + TextLocation endLocation; + public override TextLocation EndLocation { get { return endLocation; } } @@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory.VB.Ast this.Name = string.Empty; } - public XmlIdentifier(string name, AstLocation startLocation, AstLocation endLocation) + public XmlIdentifier(string name, TextLocation startLocation, TextLocation endLocation) { this.Name = name; this.startLocation = startLocation; diff --git a/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlLiteralString.cs b/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlLiteralString.cs index 3195bcd69..d2f89e805 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlLiteralString.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Expressions/XmlLiteralString.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -30,13 +30,13 @@ namespace ICSharpCode.NRefactory.VB.Ast public string Value { get; set; } - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } } - AstLocation endLocation; - public override AstLocation EndLocation { + TextLocation endLocation; + public override TextLocation EndLocation { get { return endLocation; } } @@ -45,7 +45,7 @@ namespace ICSharpCode.NRefactory.VB.Ast this.Value = string.Empty; } - public XmlLiteralString(string value, AstLocation startLocation, AstLocation endLocation) + public XmlLiteralString(string value, TextLocation startLocation, TextLocation endLocation) { this.Value = value; this.startLocation = startLocation; diff --git a/ICSharpCode.NRefactory.VB/Ast/General/Attribute.cs b/ICSharpCode.NRefactory.VB/Ast/General/Attribute.cs index 22261575e..3ad468609 100644 --- a/ICSharpCode.NRefactory.VB/Ast/General/Attribute.cs +++ b/ICSharpCode.NRefactory.VB/Ast/General/Attribute.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -42,7 +42,9 @@ namespace ICSharpCode.NRefactory.VB.Ast public static readonly Role AttributeRole = new Role("Attribute"); public static readonly Role TargetRole = new Role("Target", VBTokenNode.Null); - public VBTokenNode Target { + public AttributeTarget Target { get; set; } + + public VBTokenNode TargetKeyword { get { return GetChildByRole(TargetRole); } set { SetChildByRole(TargetRole, value); } } @@ -81,12 +83,13 @@ namespace ICSharpCode.NRefactory.VB.Ast protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { var node = other as Attribute; - return node != null && node.Target.DoMatch(this.Target, match) && node.Type.DoMatch(this.Type, match) && node.Arguments.DoMatch(this.Arguments, match); + return node != null && node.Target == Target && node.TargetKeyword.DoMatch(this.TargetKeyword, match) && node.Type.DoMatch(this.Type, match) && node.Arguments.DoMatch(this.Arguments, match); } } public enum AttributeTarget { + None, Assembly, Module } diff --git a/ICSharpCode.NRefactory.VB/Ast/General/AttributeBlock.cs b/ICSharpCode.NRefactory.VB/Ast/General/AttributeBlock.cs index 2e06d3917..57d69db33 100644 --- a/ICSharpCode.NRefactory.VB/Ast/General/AttributeBlock.cs +++ b/ICSharpCode.NRefactory.VB/Ast/General/AttributeBlock.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs b/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs index 37e364ee6..de1ccd254 100644 --- a/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs +++ b/ICSharpCode.NRefactory.VB/Ast/General/AttributedNode.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -20,7 +20,7 @@ namespace ICSharpCode.NRefactory.VB.Ast set { SetModifiers(this, value); } } - public IEnumerable ModifierTokens { + public AstNodeCollection ModifierTokens { get { return GetChildrenByRole (ModifierRole); } } @@ -41,7 +41,7 @@ namespace ICSharpCode.NRefactory.VB.Ast if ((m & newValue) != 0) { if ((m & oldValue) == 0) { // Modifier was added - var newToken = new VBModifierToken(AstLocation.Empty, m); + var newToken = new VBModifierToken(TextLocation.Empty, m); node.InsertChildAfter(insertionPos, newToken, ModifierRole); insertionPos = newToken; } else { diff --git a/ICSharpCode.NRefactory.VB/Ast/General/CompilationUnit.cs b/ICSharpCode.NRefactory.VB/Ast/General/CompilationUnit.cs index 6dbe78427..558872c7d 100644 --- a/ICSharpCode.NRefactory.VB/Ast/General/CompilationUnit.cs +++ b/ICSharpCode.NRefactory.VB/Ast/General/CompilationUnit.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -22,10 +22,10 @@ namespace ICSharpCode.NRefactory.VB.Ast public AstNode GetNodeAt (int line, int column) { - return GetNodeAt (new AstLocation (line, column)); + return GetNodeAt (new TextLocation (line, column)); } - public AstNode GetNodeAt (AstLocation location) + public AstNode GetNodeAt (TextLocation location) { AstNode node = this; while (node.FirstChild != null) { @@ -46,10 +46,10 @@ namespace ICSharpCode.NRefactory.VB.Ast public IEnumerable GetNodesBetween (int startLine, int startColumn, int endLine, int endColumn) { - return GetNodesBetween (new AstLocation (startLine, startColumn), new AstLocation (endLine, endColumn)); + return GetNodesBetween (new TextLocation (startLine, startColumn), new TextLocation (endLine, endColumn)); } - public IEnumerable GetNodesBetween (AstLocation start, AstLocation end) + public IEnumerable GetNodesBetween (TextLocation start, TextLocation end) { AstNode node = this; while (node != null) { diff --git a/ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs b/ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs new file mode 100644 index 000000000..da1e14cf4 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/General/EventMemberSpecifier.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class EventMemberSpecifier : AstNode + { + public static readonly Role EventMemberSpecifierRole = new Role("EventMemberSpecifier"); + + public EventMemberSpecifier() + { + } + + public Expression Target { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public Identifier Member { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as EventMemberSpecifier; + return expr != null && + Target.DoMatch(expr.Target, match) && + Member.DoMatch(expr.Member, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitEventMemberSpecifier(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs b/ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs new file mode 100644 index 000000000..d4e0090f2 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/General/InterfaceMemberSpecifier.cs @@ -0,0 +1,47 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class InterfaceMemberSpecifier : AstNode + { + public static readonly Role InterfaceMemberSpecifierRole = new Role("InterfaceMemberSpecifier"); + + public InterfaceMemberSpecifier(Expression target, Identifier member) + { + Target = target; + Member = member; + } + + public InterfaceMemberSpecifier(AstType target, string member) + { + Target = new TypeReferenceExpression(target); + Member = new Identifier(member, TextLocation.Empty); + } + + public Expression Target { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public Identifier Member { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var expr = other as InterfaceMemberSpecifier; + return expr != null && + Target.DoMatch(expr.Target, match) && + Member.DoMatch(expr.Member, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitInterfaceMemberSpecifier(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/General/ParameterDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/General/ParameterDeclaration.cs index 87b4162b4..61b4f2ae3 100644 --- a/ICSharpCode.NRefactory.VB/Ast/General/ParameterDeclaration.cs +++ b/ICSharpCode.NRefactory.VB/Ast/General/ParameterDeclaration.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -17,7 +17,7 @@ namespace ICSharpCode.NRefactory.VB.Ast set { SetChildByRole(Roles.Expression, value); } } - public AstType ReturnType { + public AstType Type { get { return GetChildByRole(Roles.Type); } set { SetChildByRole(Roles.Type, value); } } @@ -29,7 +29,7 @@ namespace ICSharpCode.NRefactory.VB.Ast MatchAttributesAndModifiers(param, match) && Name.DoMatch(param.Name, match) && OptionalValue.DoMatch(param.OptionalValue, match) && - ReturnType.DoMatch(param.ReturnType, match); + Type.DoMatch(param.Type, match); } public override S AcceptVisitor(IAstVisitor visitor, T data) diff --git a/ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs index 90be4263a..29396a9d9 100644 --- a/ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs +++ b/ICSharpCode.NRefactory.VB/Ast/General/TypeParameterDeclaration.cs @@ -1,10 +1,12 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + namespace ICSharpCode.NRefactory.VB.Ast { /// @@ -21,7 +23,7 @@ namespace ICSharpCode.NRefactory.VB.Ast public string Name { get { return GetChildByRole (Roles.Identifier).Name; } - set { SetChildByRole(Roles.Identifier, new Identifier (value, AstLocation.Empty)); } + set { SetChildByRole(Roles.Identifier, new Identifier (value, TextLocation.Empty)); } } public AstNodeCollection Constraints { diff --git a/ICSharpCode.NRefactory.VB/Ast/Generated.cs b/ICSharpCode.NRefactory.VB/Ast/Generated.cs index bd973a0d7..dee6e4d96 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Generated.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Generated.cs @@ -1,5 +1,5 @@ //// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -//// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +//// This code is distributed under MIT X11 license (for details please see \doc\license.txt) //using System; //using System.Collections.Generic; // diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/DelegateDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/DelegateDeclaration.cs index bc2d06ca0..8a88c9135 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/DelegateDeclaration.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/DelegateDeclaration.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumDeclaration.cs index 49fe3f239..736d579ff 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumDeclaration.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumDeclaration.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.VB.Ast set { SetChildByRole(UnderlyingTypeRole, value); } } - public AstNodeCollection Member { + public AstNodeCollection Members { get { return GetChildrenByRole(MemberRole); } } @@ -33,7 +33,7 @@ namespace ICSharpCode.NRefactory.VB.Ast MatchAttributesAndModifiers(decl, match) && Name.DoMatch(decl.Name, match) && UnderlyingType.DoMatch(decl.UnderlyingType, match) && - Member.DoMatch(decl.Member, match); + Members.DoMatch(decl.Members, match); } public override S AcceptVisitor(IAstVisitor visitor, T data) diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumMemberDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumMemberDeclaration.cs index 476ec5636..72e757c60 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumMemberDeclaration.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/EnumMemberDeclaration.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsClause.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsClause.cs index 15730eab0..a9d7f45bf 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsClause.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsClause.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -73,7 +73,7 @@ namespace ICSharpCode.NRefactory.VB.Ast public override S AcceptVisitor(IAstVisitor visitor, T data) { - return visitor.VisitMembersImportsClause(this, data); + return visitor.VisitMemberImportsClause(this, data); } public override string ToString() diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsStatement.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsStatement.cs index 6691b852b..24ea944d6 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsStatement.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/ImportsStatement.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; using ICSharpCode.NRefactory.PatternMatching; diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs index 5c392a73a..84016b45a 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/NamespaceDeclaration.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -30,7 +30,7 @@ namespace ICSharpCode.NRefactory.VB.Ast return builder.ToString (); } set { - GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => new Identifier (ident, AstLocation.Empty))); + GetChildrenByRole(Roles.Identifier).ReplaceWith(value.Split('.').Select(ident => new Identifier (ident, TextLocation.Empty))); } } diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/OptionStatement.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/OptionStatement.cs index 903439c89..299cc5b01 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/OptionStatement.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/OptionStatement.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; using ICSharpCode.NRefactory.PatternMatching; diff --git a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs index eadd4f031..13ccf5563 100644 --- a/ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs +++ b/ICSharpCode.NRefactory.VB/Ast/GlobalScope/TypeDeclaration.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -8,6 +8,14 @@ using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.VB.Ast { + public enum ClassType + { + Class, + Struct, + Interface, + Module + } + public class TypeDeclaration : AttributedNode { public readonly static Role MemberRole = new Role("Member"); @@ -20,11 +28,9 @@ namespace ICSharpCode.NRefactory.VB.Ast public ClassType ClassType { get; set; } - public string Name { - get { return GetChildByRole(Roles.Identifier).Name; } - set { - SetChildByRole(Roles.Identifier, new Identifier (value, AstLocation.Empty)); - } + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } } public AstNodeCollection TypeParameters { @@ -33,6 +39,7 @@ namespace ICSharpCode.NRefactory.VB.Ast public AstType InheritsType { get { return GetChildByRole(InheritsTypeRole); } + set { SetChildByRole(InheritsTypeRole, value); } } public AstNodeCollection ImplementsTypes { @@ -46,7 +53,7 @@ namespace ICSharpCode.NRefactory.VB.Ast MatchAttributesAndModifiers(t, match) && Members.DoMatch(t.Members, match) && ClassType == t.ClassType && - MatchString(Name, t.Name) && + Name.DoMatch(t.Name, match) && TypeParameters.DoMatch(t.TypeParameters, match) && InheritsType.DoMatch(t.InheritsType, match) && ImplementsTypes.DoMatch(t.ImplementsTypes, match); diff --git a/ICSharpCode.NRefactory.VB/Ast/INullable.cs b/ICSharpCode.NRefactory.VB/Ast/INullable.cs index 14a65a444..1ce646f6b 100644 --- a/ICSharpCode.NRefactory.VB/Ast/INullable.cs +++ b/ICSharpCode.NRefactory.VB/Ast/INullable.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) namespace ICSharpCode.NRefactory.VB.Ast { diff --git a/ICSharpCode.NRefactory.VB/Ast/Identifier.cs b/ICSharpCode.NRefactory.VB/Ast/Identifier.cs index ea308b7f9..e7cd4424a 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Identifier.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Identifier.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -43,16 +43,16 @@ namespace ICSharpCode.NRefactory.VB.Ast public TypeCode TypeCharacter { get; set; } - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (StartLocation.Line, StartLocation.Column + Name.Length); + return new TextLocation (StartLocation.Line, StartLocation.Column + Name.Length); } } @@ -61,7 +61,7 @@ namespace ICSharpCode.NRefactory.VB.Ast this.name = string.Empty; } - public Identifier (string name, AstLocation location) + public Identifier (string name, TextLocation location) { if (name == null) throw new ArgumentNullException("name"); @@ -69,6 +69,11 @@ namespace ICSharpCode.NRefactory.VB.Ast this.startLocation = location; } + public static implicit operator Identifier(string name) + { + return new Identifier(name, TextLocation.Empty); + } + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) { var node = other as Identifier; @@ -84,8 +89,8 @@ namespace ICSharpCode.NRefactory.VB.Ast public override string ToString() { - return string.Format("[Identifier Name={0}, StartLocation={1}, TypeCharacter{4}]", - name, startLocation, TypeCharacter); + return string.Format("{0}", + name); } } } diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/BlockStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/BlockStatement.cs index 73610fe70..1cce01649 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Statements/BlockStatement.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/BlockStatement.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -79,7 +79,7 @@ namespace ICSharpCode.NRefactory.VB.Ast protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) { BlockStatement o = other as BlockStatement; - return o != null && !o.IsNull && this.Statements.DoMatch(o.Statements, match); + return o != null && !(o is CatchBlock) && !o.IsNull && this.Statements.DoMatch(o.Statements, match); } #region Builder methods @@ -88,28 +88,26 @@ namespace ICSharpCode.NRefactory.VB.Ast AddChild(statement, StatementRole); } - // TODO : uncomment + public void Add(Expression expression) + { + AddChild(new ExpressionStatement { Expression = expression }, StatementRole); + } -// public void Add(Expression expression) -// { -// AddChild(new ExpressionStatement { Expression = expression }, StatementRole); -// } -// public void AddRange(IEnumerable statements) { foreach (Statement st in statements) AddChild(st, StatementRole); } -// public void AddAssignment(Expression left, Expression right) -// { -// Add(new AssignmentExpression { Left = left, Operator = AssignmentOperatorType.Assign, Right = right }); -// } -// -// public void AddReturnStatement(Expression expression) -// { -// Add(new ReturnStatement { Expression = expression }); -// } + public void AddAssignment(Expression left, Expression right) + { + Add(new AssignmentExpression(left, AssignmentOperatorType.Assign, right)); + } + + public void AddReturnStatement(Expression expression) + { + Add(new ReturnStatement { Expression = expression }); + } #endregion IEnumerator IEnumerable.GetEnumerator() diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/ContinueStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/ContinueStatement.cs new file mode 100644 index 000000000..4ec41f628 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/ContinueStatement.cs @@ -0,0 +1,50 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Continue ( Do | For | While ) + /// + public class ContinueStatement : Statement + { + public static readonly Role ContinueKindTokenRole = new Role("ContinueKindToken"); + + public ContinueKind ContinueKind { get; set; } + + public VBTokenNode ContinueToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public VBTokenNode ContinueKindToken { + get { return GetChildByRole (ContinueKindTokenRole); } + } + + public ContinueStatement(ContinueKind kind) + { + this.ContinueKind = kind; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitContinueStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ContinueStatement o = other as ContinueStatement; + return o != null && this.ContinueKind == o.ContinueKind; + } + } + + public enum ContinueKind + { + None, + Do, + For, + While + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/DoLoopStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/DoLoopStatement.cs new file mode 100644 index 000000000..9335926f8 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/DoLoopStatement.cs @@ -0,0 +1,33 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class DoLoopStatement : Statement + { + public ConditionType ConditionType { get; set; } + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitDoLoopStatement(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/ExitStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/ExitStatement.cs new file mode 100644 index 000000000..b5f7c0ff3 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/ExitStatement.cs @@ -0,0 +1,55 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Exit ( Do | For | While | Select | Sub | Function | Property | Try ) + /// + public class ExitStatement : Statement + { + public static readonly Role ExitKindTokenRole = new Role("ExitKindToken"); + + public ExitKind ExitKind { get; set; } + + public VBTokenNode ExitToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public VBTokenNode ExitKindToken { + get { return GetChildByRole (ExitKindTokenRole); } + } + + public ExitStatement(ExitKind kind) + { + this.ExitKind = kind; + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitExitStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ExitStatement o = other as ExitStatement; + return o != null && this.ExitKind == o.ExitKind; + } + } + + public enum ExitKind + { + None, + Sub, + Function, + Property, + Do, + For, + While, + Select, + Try + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/ExpressionStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/ExpressionStatement.cs new file mode 100644 index 000000000..67e8952d6 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/ExpressionStatement.cs @@ -0,0 +1,40 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Expression + /// + // TODO this does not directly reflect the VB grammar! + public class ExpressionStatement : Statement + { + public Expression Expression { + get { return GetChildByRole (Roles.Expression); } + set { SetChildByRole (Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitExpressionStatement(this, data); + } + + public ExpressionStatement() + { + } + + public ExpressionStatement(Expression expression) + { + this.Expression = expression; + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ExpressionStatement o = other as ExpressionStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/ForEachStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/ForEachStatement.cs new file mode 100644 index 000000000..7c0cd90b1 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/ForEachStatement.cs @@ -0,0 +1,38 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class ForEachStatement : Statement + { + public static readonly Role VariableRole = new Role("Variable", AstNode.Null); + + public AstNode Variable { + get { return GetChildByRole(VariableRole); } + set { SetChildByRole(VariableRole, value); } + } + + public Expression InExpression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitForEachStatement(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/ForStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/ForStatement.cs new file mode 100644 index 000000000..c28ea0fd5 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/ForStatement.cs @@ -0,0 +1,45 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class ForStatement : Statement + { + public static readonly Role VariableRole = new Role("Variable", AstNode.Null); + public static readonly Role ToExpressionRole = new Role("ToExpression", Expression.Null); + public static readonly Role StepExpressionRole = new Role("StepExpression", Expression.Null); + + public AstNode Variable { + get { return GetChildByRole(VariableRole); } + set { SetChildByRole(VariableRole, value); } + } + + public Expression ToExpression { + get { return GetChildByRole(ToExpressionRole); } + set { SetChildByRole(ToExpressionRole, value); } + } + + public Expression StepExpression { + get { return GetChildByRole(StepExpressionRole); } + set { SetChildByRole(StepExpressionRole, value); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitForStatement(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/GoToStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/GoToStatement.cs new file mode 100644 index 000000000..32dc7d745 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/GoToStatement.cs @@ -0,0 +1,27 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class GoToStatement : Statement + { + /// either PrimitiveExpression or IdentifierExpression + public Expression Label { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitGoToStatement(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/IfElseStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/IfElseStatement.cs new file mode 100644 index 000000000..08738789a --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/IfElseStatement.cs @@ -0,0 +1,39 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class IfElseStatement : Statement + { + public static readonly Role FalseStatementRole = new Role("False", Ast.Statement.Null); + public static readonly Role TrueStatementRole = new Role("True", Ast.Statement.Null); + + public Expression Condition { + get { return GetChildByRole(Roles.Condition); } + set { SetChildByRole(Roles.Condition, value); } + } + + public Statement Body { + get { return GetChildByRole(TrueStatementRole); } + set { SetChildByRole(TrueStatementRole, value); } + } + + public Statement ElseBlock { + get { return GetChildByRole(FalseStatementRole); } + set { SetChildByRole(FalseStatementRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitIfElseStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/LabelDeclarationStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/LabelDeclarationStatement.cs new file mode 100644 index 000000000..589fea5a6 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/LabelDeclarationStatement.cs @@ -0,0 +1,35 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Label: + /// + public class LabelDeclarationStatement : Statement + { + /// either PrimitiveExpression or IdentifierExpression + public Expression Label { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public VBTokenNode Colon { + get { return GetChildByRole(Roles.Colon); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitLabelDeclarationStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + LabelDeclarationStatement o = other as LabelDeclarationStatement; + return o != null && this.Label.DoMatch(o.Label, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/LocalDeclarationStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/LocalDeclarationStatement.cs new file mode 100644 index 000000000..40c19b2ab --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/LocalDeclarationStatement.cs @@ -0,0 +1,37 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// ( Dim | Static | Const ) VariableDeclarator { , VariableDeclarator } + /// + public class LocalDeclarationStatement : Statement + { + public AstNodeCollection Variables { + get { return GetChildrenByRole(VariableDeclarator.VariableDeclaratorRole); } + } + + public Modifiers Modifiers { + get { return AttributedNode.GetModifiers(this); } + set { AttributedNode.SetModifiers(this, value); } + } + + public VBModifierToken ModifierToken { + get { return GetChildByRole(AttributedNode.ModifierRole); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitLocalDeclarationStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/ReturnStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/ReturnStatement.cs new file mode 100644 index 000000000..26deb1ab2 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/ReturnStatement.cs @@ -0,0 +1,43 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Return Expression + /// + public class ReturnStatement : Statement + { + public VBTokenNode ReturnToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public ReturnStatement() + { + } + + public ReturnStatement(Expression expression) + { + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitReturnStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ReturnStatement o = other as ReturnStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs new file mode 100644 index 000000000..70f2dd720 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/SelectStatement.cs @@ -0,0 +1,147 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class SelectStatement : Statement + { + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public AstNodeCollection Cases { + get { return GetChildrenByRole(CaseStatement.CaseStatementRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSelectStatement(this, data); + } + } + + public class CaseStatement : Statement + { + public static readonly Role CaseStatementRole = new Role("CaseStatement"); + + public AstNodeCollection Clauses { + get { return GetChildrenByRole(CaseClause.CaseClauseRole); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitCaseStatement(this, data); + } + } + + public abstract class CaseClause : AstNode + { + #region Null + public new static readonly CaseClause Null = new NullCaseClause(); + + sealed class NullCaseClause : CaseClause + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public static readonly Role CaseClauseRole = new Role("CaseClause", CaseClause.Null); + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + } + + public class SimpleCaseClause : CaseClause + { + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitSimpleCaseClause(this, data); + } + } + + public class RangeCaseClause : CaseClause + { + public static readonly Role ToExpressionRole = ForStatement.ToExpressionRole; + + public Expression ToExpression { + get { return GetChildByRole(ToExpressionRole); } + set { SetChildByRole(ToExpressionRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitRangeCaseClause(this, data); + } + } + + public class ComparisonCaseClause : CaseClause + { + public static readonly Role OperatorRole = BinaryOperatorExpression.OperatorRole; + + public ComparisonOperator Operator { get; set; } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitComparisonCaseClause(this, data); + } + } + + public enum ComparisonOperator + { + Equality = BinaryOperatorType.Equality, + InEquality = BinaryOperatorType.InEquality, + LessThan = BinaryOperatorType.LessThan, + GreaterThan = BinaryOperatorType.GreaterThan, + LessThanOrEqual = BinaryOperatorType.LessThanOrEqual, + GreaterThanOrEqual = BinaryOperatorType.GreaterThanOrEqual + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs index c20407051..5b2a55bbb 100644 --- a/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/Statement.cs @@ -115,18 +115,18 @@ namespace ICSharpCode.NRefactory.VB.Ast } // Make debugging easier by giving Statements a ToString() implementation - public override string ToString() - { -// if (IsNull) -// return "Null"; -// StringWriter w = new StringWriter(); -// AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); -// string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); -// if (text.Length > 100) -// return text.Substring(0, 97) + "..."; -// else -// return text; - throw new NotImplementedException(); - } +// public override string ToString() +// { +//// if (IsNull) +//// return "Null"; +//// StringWriter w = new StringWriter(); +//// AcceptVisitor(new OutputVisitor(w, new CSharpFormattingOptions()), null); +//// string text = w.ToString().TrimEnd().Replace("\t", "").Replace(w.NewLine, " "); +//// if (text.Length > 100) +//// return text.Substring(0, 97) + "..."; +//// else +//// return text; +// throw new NotImplementedException(); +// } } } diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/SyncLockStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/SyncLockStatement.cs new file mode 100644 index 000000000..7fd317eb0 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/SyncLockStatement.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// SyncLock Expression
+ /// Block
+ /// End SyncLock + ///
+ public class SyncLockStatement : Statement + { + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitSyncLockStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/ThrowStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/ThrowStatement.cs new file mode 100644 index 000000000..c4c1634b5 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/ThrowStatement.cs @@ -0,0 +1,43 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Throw Expression + /// + public class ThrowStatement : Statement + { + public VBTokenNode ThrowToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public ThrowStatement() + { + } + + public ThrowStatement(Expression expression) + { + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitThrowStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + ThrowStatement o = other as ThrowStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/TryStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/TryStatement.cs new file mode 100644 index 000000000..7e5eb94da --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/TryStatement.cs @@ -0,0 +1,67 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class TryStatement : Statement + { + public static readonly Role FinallyBlockRole = new Role("FinallyBlock", Ast.BlockStatement.Null); + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + public AstNodeCollection CatchBlocks { + get { return GetChildrenByRole(CatchBlock.CatchBlockRole); } + } + + public BlockStatement FinallyBlock { + get { return GetChildByRole(FinallyBlockRole); } + set { SetChildByRole(FinallyBlockRole, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitTryStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + throw new NotImplementedException(); + } + } + + public class CatchBlock : BlockStatement + { + public static readonly Role CatchBlockRole = new Role("CatchBlockRole"); + + public Identifier ExceptionVariable { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstType ExceptionType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public Expression WhenExpression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitCatchBlock(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/UsingStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/UsingStatement.cs new file mode 100644 index 000000000..c2147e447 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/UsingStatement.cs @@ -0,0 +1,33 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class UsingStatement : Statement + { + public static readonly Role ResourceRole = new Role("Resource", AstNode.Null); + + /// either multiple VariableInitializers or one Expression + public AstNodeCollection Resources { + get { return GetChildrenByRole(ResourceRole); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitUsingStatement(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/WhileStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/WhileStatement.cs new file mode 100644 index 000000000..e5c9ec24c --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/WhileStatement.cs @@ -0,0 +1,31 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class WhileStatement : Statement + { + public Expression Condition { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitWhileStatement(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/WithStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/WithStatement.cs new file mode 100644 index 000000000..b915a9081 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/WithStatement.cs @@ -0,0 +1,36 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// With Expression
+ /// Block
+ /// End With + ///
+ public class WithStatement : Statement + { + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return visitor.VisitWithStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + throw new NotImplementedException(); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/Statements/YieldStatement.cs b/ICSharpCode.NRefactory.VB/Ast/Statements/YieldStatement.cs new file mode 100644 index 000000000..895382aa1 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/Statements/YieldStatement.cs @@ -0,0 +1,44 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.IO; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Yield Expression + /// + /// VB 11 + public class YieldStatement : Statement + { + public VBTokenNode YieldToken { + get { return GetChildByRole (Roles.Keyword); } + } + + public Expression Expression { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + public YieldStatement() + { + } + + public YieldStatement(Expression expression) + { + AddChild (expression, Roles.Expression); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitYieldStatement(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + YieldStatement o = other as YieldStatement; + return o != null && this.Expression.DoMatch(o.Expression, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/Accessor.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/Accessor.cs new file mode 100644 index 000000000..7eb287c26 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/Accessor.cs @@ -0,0 +1,49 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Get/Set/AddHandler/RemoveHandler/RaiseEvent + /// + public class Accessor : AttributedNode + { + public static readonly new Accessor Null = new NullAccessor (); + sealed class NullAccessor : Accessor + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitAccessor(this, data); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + Accessor o = other as Accessor; + return o != null && !o.IsNull && this.MatchAttributesAndModifiers(o, match) && + this.Body.DoMatch(o.Body, match) && Parameters.DoMatch(o.Parameters, match); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs new file mode 100644 index 000000000..9e57fc572 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ConstructorDeclaration.cs @@ -0,0 +1,45 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public abstract class MemberDeclaration : AttributedNode + { + + } + + /// + /// Description of ConstructorDeclaration. + /// + public class ConstructorDeclaration : MemberDeclaration + { + public ConstructorDeclaration() + { + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var ctor = other as ConstructorDeclaration; + return ctor != null && + MatchAttributesAndModifiers(ctor, match) && + Parameters.DoMatch(ctor.Parameters, match) && + Body.DoMatch(ctor.Body, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitConstructorDeclaration(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/EventDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/EventDeclaration.cs new file mode 100644 index 000000000..ce0181964 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/EventDeclaration.cs @@ -0,0 +1,59 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class EventDeclaration : MemberDeclaration + { + public bool IsCustom { get; set; } + + public static readonly Role AddHandlerRole = new Role("AddHandler", Accessor.Null); + public static readonly Role RemoveHandlerRole = new Role("RemoveHandler", Accessor.Null); + public static readonly Role RaiseEventRole = new Role("RaiseEvent", Accessor.Null); + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection ImplementsClause { + get { return GetChildrenByRole(InterfaceMemberSpecifier.InterfaceMemberSpecifierRole); } + } + + public Accessor AddHandlerBlock { + get { return GetChildByRole(AddHandlerRole); } + set { SetChildByRole(AddHandlerRole, value); } + } + + public Accessor RemoveHandlerBlock { + get { return GetChildByRole(RemoveHandlerRole); } + set { SetChildByRole(RemoveHandlerRole, value); } + } + + public Accessor RaiseEventBlock { + get { return GetChildByRole(RaiseEventRole); } + set { SetChildByRole(RaiseEventRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitEventDeclaration(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ExternalMethodDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ExternalMethodDeclaration.cs new file mode 100644 index 000000000..d5d975447 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/ExternalMethodDeclaration.cs @@ -0,0 +1,71 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Runtime.InteropServices; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class ExternalMethodDeclaration : MemberDeclaration + { + public ExternalMethodDeclaration() + { + } + + public CharsetModifier CharsetModifier { get; set; } + + public bool IsSub { get; set; } + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public string Library { get; set; } + + public string Alias { get; set; } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection ReturnTypeAttributes { + get { return GetChildrenByRole(AttributeBlock.ReturnTypeAttributeBlockRole); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + // TODO : finish + var method = other as ExternalMethodDeclaration; + return method != null && + MatchAttributesAndModifiers(method, match) && + IsSub == method.IsSub && + Name.DoMatch(method.Name, match) && + Parameters.DoMatch(method.Parameters, match) && + ReturnTypeAttributes.DoMatch(method.ReturnTypeAttributes, match) && + ReturnType.DoMatch(method.ReturnType, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitExternalMethodDeclaration(this, data); + } + } + + /// + /// Charset types, used in external methods + /// declarations (VB only). + /// + public enum CharsetModifier + { + None, + Auto, + Unicode, + Ansi + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs new file mode 100644 index 000000000..528d632cb --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/FieldDeclaration.cs @@ -0,0 +1,81 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// Attributes? VariableModifier+ VariableDeclarators StatementTerminator + /// + public class FieldDeclaration : MemberDeclaration + { + public AstNodeCollection Variables { + get { return GetChildrenByRole(VariableDeclarator.VariableDeclaratorRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitFieldDeclaration(this, data); + } + } + + + + /// + /// Identifier IdentifierModifiers + /// + public class VariableIdentifier : AstNode + { + #region Null + public new static readonly VariableIdentifier Null = new NullVariableIdentifier(); + + sealed class NullVariableIdentifier : VariableIdentifier + { + public override bool IsNull { + get { + return true; + } + } + + public override S AcceptVisitor (IAstVisitor visitor, T data) + { + return default (S); + } + + protected internal override bool DoMatch(AstNode other, PatternMatching.Match match) + { + return other == null || other.IsNull; + } + } + #endregion + + public static readonly Role VariableIdentifierRole = new Role("VariableIdentifier", VariableIdentifier.Null); + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public bool HasNullableSpecifier { get; set; } + + public AstNodeCollection ArraySpecifiers { + get { return GetChildrenByRole(ComposedType.ArraySpecifierRole); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitVariableIdentifier(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs new file mode 100644 index 000000000..a6dd87159 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/MethodDeclaration.cs @@ -0,0 +1,72 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class MethodDeclaration : MemberDeclaration + { + public MethodDeclaration() + { + } + + public bool IsSub { get; set; } + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstNodeCollection TypeParameters { + get { return GetChildrenByRole(Roles.TypeParameter); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection ReturnTypeAttributes { + get { return GetChildrenByRole(AttributeBlock.ReturnTypeAttributeBlockRole); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AstNodeCollection HandlesClause { + get { return GetChildrenByRole(EventMemberSpecifier.EventMemberSpecifierRole); } + } + + public AstNodeCollection ImplementsClause { + get { return GetChildrenByRole(InterfaceMemberSpecifier.InterfaceMemberSpecifierRole); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + var method = other as MethodDeclaration; + return method != null && + MatchAttributesAndModifiers(method, match) && + IsSub == method.IsSub && + Name.DoMatch(method.Name, match) && + TypeParameters.DoMatch(method.TypeParameters, match) && + Parameters.DoMatch(method.Parameters, match) && + ReturnTypeAttributes.DoMatch(method.ReturnTypeAttributes, match) && + ReturnType.DoMatch(method.ReturnType, match) && + HandlesClause.DoMatch(method.HandlesClause, match) && + ImplementsClause.DoMatch(method.ImplementsClause, match) && + Body.DoMatch(method.Body, match); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitMethodDeclaration(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/OperatorDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/OperatorDeclaration.cs new file mode 100644 index 000000000..f6591e4a4 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/OperatorDeclaration.cs @@ -0,0 +1,83 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class OperatorDeclaration : MemberDeclaration + { + public OperatorDeclaration() + { + } + + public OverloadableOperatorType Operator { get; set; } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection ReturnTypeAttributes { + get { return GetChildrenByRole(AttributeBlock.ReturnTypeAttributeBlockRole); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public BlockStatement Body { + get { return GetChildByRole(Roles.Body); } + set { SetChildByRole(Roles.Body, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitOperatorDeclaration(this, data); + } + } + + public enum OverloadableOperatorType + { + None, + + Add, + Subtract, + Multiply, + Divide, + Modulus, + Concat, + + UnaryPlus, + UnaryMinus, + + Not, + + BitwiseAnd, + BitwiseOr, + ExclusiveOr, + + ShiftLeft, + ShiftRight, + + GreaterThan, + GreaterThanOrEqual, + Equality, + InEquality, + LessThan, + LessThanOrEqual, + + IsTrue, + IsFalse, + + Like, + Power, + CType, + DivideInteger + }// +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/PropertyDeclaration.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/PropertyDeclaration.cs new file mode 100644 index 000000000..6fdab3842 --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/PropertyDeclaration.cs @@ -0,0 +1,57 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + public class PropertyDeclaration : MemberDeclaration + { + // TODO : support automatic properties + + public static readonly Role GetterRole = new Role("Getter", Accessor.Null); + public static readonly Role SetterRole = new Role("Setter", Accessor.Null); + + public Identifier Name { + get { return GetChildByRole(Roles.Identifier); } + set { SetChildByRole(Roles.Identifier, value); } + } + + public AstNodeCollection Parameters { + get { return GetChildrenByRole(Roles.Parameter); } + } + + public AstNodeCollection ReturnTypeAttributes { + get { return GetChildrenByRole(AttributeBlock.ReturnTypeAttributeBlockRole); } + } + + public AstType ReturnType { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public AstNodeCollection ImplementsClause { + get { return GetChildrenByRole(InterfaceMemberSpecifier.InterfaceMemberSpecifierRole); } + } + + public Accessor Getter { + get { return GetChildByRole(GetterRole); } + set { SetChildByRole(GetterRole, value); } + } + + public Accessor Setter { + get { return GetChildByRole(SetterRole); } + set { SetChildByRole(SetterRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitPropertyDeclaration(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeMembers/VariableDeclarator.cs b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/VariableDeclarator.cs new file mode 100644 index 000000000..a3ad2892a --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Ast/TypeMembers/VariableDeclarator.cs @@ -0,0 +1,63 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; + +namespace ICSharpCode.NRefactory.VB.Ast +{ + /// + /// VariableIdentifiers As ObjectCreationExpression
+ /// VariableIdentifiers ( As TypeName )? ( Equals Expression )? + ///
+ public abstract class VariableDeclarator : AstNode + { + public static readonly Role VariableDeclaratorRole = new Role("VariableDeclarator"); + + public AstNodeCollection Identifiers { + get { return GetChildrenByRole(VariableIdentifier.VariableIdentifierRole); } + } + } + + public class VariableDeclaratorWithTypeAndInitializer : VariableDeclarator + { + public AstType Type { + get { return GetChildByRole(Roles.Type); } + set { SetChildByRole(Roles.Type, value); } + } + + public Expression Initializer { + get { return GetChildByRole(Roles.Expression); } + set { SetChildByRole(Roles.Expression, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitVariableDeclaratorWithTypeAndInitializer(this, data); + } + } + + public class VariableDeclaratorWithObjectCreation : VariableDeclarator + { + public static readonly Role InitializerRole = new Role("InitializerRole"); + + public ObjectCreationExpression Initializer { + get { return GetChildByRole(InitializerRole); } + set { SetChildByRole(InitializerRole, value); } + } + + protected internal override bool DoMatch(AstNode other, ICSharpCode.NRefactory.PatternMatching.Match match) + { + throw new NotImplementedException(); + } + + public override S AcceptVisitor(IAstVisitor visitor, T data) + { + return visitor.VisitVariableDeclaratorWithObjectCreation(this, data); + } + } +} diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs b/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs index 13ba3ee97..ca39bd369 100644 --- a/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs +++ b/ICSharpCode.NRefactory.VB/Ast/TypeName/AstType.cs @@ -1,7 +1,8 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; +using System.Linq; namespace ICSharpCode.NRefactory.VB.Ast { @@ -70,38 +71,55 @@ namespace ICSharpCode.NRefactory.VB.Ast return new ComposedType { BaseType = this }.MakeArrayType(rank); } - // TODO : reimplement this -// /// -// /// Builds an expression that can be used to access a static member on this type. -// /// -// public MemberReferenceExpression Member(string memberName) -// { -// return new TypeReferenceExpression { Type = this }.Member(memberName); -// } -// -// /// -// /// Builds an invocation expression using this type as target. -// /// -// public InvocationExpression Invoke(string methodName, IEnumerable arguments) -// { -// return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); -// } -// -// /// -// /// Builds an invocation expression using this type as target. -// /// -// public InvocationExpression Invoke(string methodName, params Expression[] arguments) -// { -// return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); -// } -// -// /// -// /// Builds an invocation expression using this type as target. -// /// -// public InvocationExpression Invoke(string methodName, IEnumerable typeArguments, IEnumerable arguments) -// { -// return new TypeReferenceExpression { Type = this }.Invoke(methodName, typeArguments, arguments); -// } + public static AstType FromName(string fullName) + { + if (string.IsNullOrEmpty(fullName)) + throw new ArgumentNullException("fullName"); + fullName = fullName.Trim(); + if (!fullName.Contains(".")) + return new SimpleType(fullName); + string[] parts = fullName.Split('.'); + + AstType type = new SimpleType(parts.First()); + + foreach (var part in parts.Skip(1)) { + type = new QualifiedType(type, part); + } + + return type; + } + + /// + /// Builds an expression that can be used to access a static member on this type. + /// + public MemberAccessExpression Member(string memberName) + { + return new TypeReferenceExpression { Type = this }.Member(memberName); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, params Expression[] arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, arguments); + } + + /// + /// Builds an invocation expression using this type as target. + /// + public InvocationExpression Invoke(string methodName, IEnumerable typeArguments, IEnumerable arguments) + { + return new TypeReferenceExpression { Type = this }.Invoke(methodName, typeArguments, arguments); + } public static AstType Create(Type type) { diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeName/ComposedType.cs b/ICSharpCode.NRefactory.VB/Ast/TypeName/ComposedType.cs index e214a7e4b..3f23d791c 100644 --- a/ICSharpCode.NRefactory.VB/Ast/TypeName/ComposedType.cs +++ b/ICSharpCode.NRefactory.VB/Ast/TypeName/ComposedType.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.Linq; @@ -22,7 +22,7 @@ namespace ICSharpCode.NRefactory.VB.Ast return !GetChildByRole(NullableRole).IsNull; } set { - SetChildByRole(NullableRole, value ? new VBTokenNode(AstLocation.Empty, 1) : null); + SetChildByRole(NullableRole, value ? new VBTokenNode(TextLocation.Empty, 1) : null); } } @@ -89,7 +89,7 @@ namespace ICSharpCode.NRefactory.VB.Ast d--; } while (d < value) { - InsertChildBefore(GetChildByRole(Roles.Comma), new VBTokenNode(AstLocation.Empty, 1), Roles.Comma); + InsertChildBefore(GetChildByRole(Roles.Comma), new VBTokenNode(TextLocation.Empty, 1), Roles.Comma); d++; } } diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeName/PrimitiveType.cs b/ICSharpCode.NRefactory.VB/Ast/TypeName/PrimitiveType.cs index 8d6badc8f..092705d53 100644 --- a/ICSharpCode.NRefactory.VB/Ast/TypeName/PrimitiveType.cs +++ b/ICSharpCode.NRefactory.VB/Ast/TypeName/PrimitiveType.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; using System.Linq; @@ -9,7 +9,7 @@ namespace ICSharpCode.NRefactory.VB.Ast public class PrimitiveType : AstType { public string Keyword { get; set; } - public AstLocation Location { get; set; } + public TextLocation Location { get; set; } public PrimitiveType() { @@ -20,20 +20,20 @@ namespace ICSharpCode.NRefactory.VB.Ast this.Keyword = keyword; } - public PrimitiveType(string keyword, AstLocation location) + public PrimitiveType(string keyword, TextLocation location) { this.Keyword = keyword; this.Location = location; } - public override AstLocation StartLocation { + public override TextLocation StartLocation { get { return Location; } } - public override AstLocation EndLocation { + public override TextLocation EndLocation { get { - return new AstLocation (Location.Line, Location.Column + (Keyword != null ? Keyword.Length : 0)); + return new TextLocation (Location.Line, Location.Column + (Keyword != null ? Keyword.Length : 0)); } } diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs b/ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs index 116f9918c..3ee783d63 100644 --- a/ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs +++ b/ICSharpCode.NRefactory.VB/Ast/TypeName/QualifiedType.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Linq; @@ -24,7 +24,7 @@ namespace ICSharpCode.NRefactory.VB.Ast return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, new Identifier (value, TextLocation.Empty)); } } diff --git a/ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs b/ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs index 590671b9c..5f86fa871 100644 --- a/ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs +++ b/ICSharpCode.NRefactory.VB/Ast/TypeName/SimpleType.cs @@ -42,7 +42,7 @@ namespace ICSharpCode.NRefactory.VB.Ast this.Identifier = identifier; } - public SimpleType(string identifier, AstLocation location) + public SimpleType(string identifier, TextLocation location) { SetChildByRole (Roles.Identifier, new Identifier (identifier, location)); } @@ -52,7 +52,7 @@ namespace ICSharpCode.NRefactory.VB.Ast return GetChildByRole (Roles.Identifier).Name; } set { - SetChildByRole (Roles.Identifier, new Identifier (value, AstLocation.Empty)); + SetChildByRole (Roles.Identifier, new Identifier (value, TextLocation.Empty)); } } diff --git a/ICSharpCode.NRefactory.VB/Ast/VBModifierToken.cs b/ICSharpCode.NRefactory.VB/Ast/VBModifierToken.cs index 05a22acc4..d6a23ebcd 100644 --- a/ICSharpCode.NRefactory.VB/Ast/VBModifierToken.cs +++ b/ICSharpCode.NRefactory.VB/Ast/VBModifierToken.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -46,6 +46,7 @@ namespace ICSharpCode.NRefactory.VB.Ast new KeyValuePair(Modifiers.Overridable, "Overridable".Length), new KeyValuePair(Modifiers.NotInheritable, "NotInheritable".Length), new KeyValuePair(Modifiers.NotOverridable, "NotOverridable".Length), + new KeyValuePair(Modifiers.Dim, "Dim".Length), new KeyValuePair(Modifiers.Const, "Const".Length), new KeyValuePair(Modifiers.Shared, "Shared".Length), new KeyValuePair(Modifiers.Static, "Static".Length), @@ -57,8 +58,17 @@ namespace ICSharpCode.NRefactory.VB.Ast new KeyValuePair(Modifiers.Overloads, "Overloads".Length), new KeyValuePair(Modifiers.WithEvents, "WithEvents".Length), new KeyValuePair(Modifiers.Default, "Default".Length), - new KeyValuePair(Modifiers.Dim, "Dim".Length), - + // parameter modifiers + new KeyValuePair(Modifiers.Optional, "Optional".Length), + new KeyValuePair(Modifiers.ByVal, "ByVal".Length), + new KeyValuePair(Modifiers.ByRef, "ByRef".Length), + new KeyValuePair(Modifiers.ParamArray, "ParamArray".Length), + // operator modifiers + new KeyValuePair(Modifiers.Narrowing, "Narrowing".Length), + new KeyValuePair(Modifiers.Widening, "Widening".Length), + // VB 11 modifiers + new KeyValuePair(Modifiers.Async, "Async".Length), + new KeyValuePair(Modifiers.Iterator, "Iterator".Length), // even though it's used for patterns only, it needs to be in this table to be usable in the AST new KeyValuePair(Modifiers.Any, "Any".Length) }; @@ -67,7 +77,7 @@ namespace ICSharpCode.NRefactory.VB.Ast get { return lengthTable.Select(p => p.Key); } } - public VBModifierToken(AstLocation location, Modifiers modifier) : base (location, 0) + public VBModifierToken(TextLocation location, Modifiers modifier) : base (location, 0) { this.Modifier = modifier; } @@ -117,8 +127,24 @@ namespace ICSharpCode.NRefactory.VB.Ast return "Dim"; case Modifiers.WriteOnly: return "WriteOnly"; + case Modifiers.Optional: + return "Optional"; + case Modifiers.ByVal: + return "ByVal"; + case Modifiers.ByRef: + return "ByRef"; + case Modifiers.ParamArray: + return "ParamArray"; + case Modifiers.Widening: + return "Widening"; + case Modifiers.Narrowing: + return "Narrowing"; + case Modifiers.Async: + return "Async"; + case Modifiers.Iterator: + return "Iterator"; default: - throw new NotSupportedException("Invalid value for Modifiers"); + throw new NotSupportedException("Invalid value for Modifiers: " + modifier); } } } diff --git a/ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs b/ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs index 225484e67..d98a820af 100644 --- a/ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs +++ b/ICSharpCode.NRefactory.VB/Ast/VBTokenNode.cs @@ -25,7 +25,7 @@ namespace ICSharpCode.NRefactory.VB.Ast } } - public NullVBTokenNode() : base (AstLocation.Empty, 0) + public NullVBTokenNode() : base (TextLocation.Empty, 0) { } @@ -40,8 +40,8 @@ namespace ICSharpCode.NRefactory.VB.Ast } } - AstLocation startLocation; - public override AstLocation StartLocation { + TextLocation startLocation; + public override TextLocation StartLocation { get { return startLocation; } @@ -49,20 +49,20 @@ namespace ICSharpCode.NRefactory.VB.Ast protected int tokenLength = -1; - AstLocation endLocation; - public override AstLocation EndLocation { + TextLocation endLocation; + public override TextLocation EndLocation { get { - return tokenLength < 0 ? endLocation : new AstLocation(startLocation.Line, startLocation.Column + tokenLength); + return tokenLength < 0 ? endLocation : new TextLocation(startLocation.Line, startLocation.Column + tokenLength); } } - public VBTokenNode(AstLocation location, int tokenLength) + public VBTokenNode(TextLocation location, int tokenLength) { this.startLocation = location; this.tokenLength = tokenLength; } - public VBTokenNode(AstLocation startLocation, AstLocation endLocation) + public VBTokenNode(TextLocation startLocation, TextLocation endLocation) { this.startLocation = startLocation; this.endLocation = endLocation; diff --git a/ICSharpCode.NRefactory.VB/AstBuilder/ExpressionBuilder.cs b/ICSharpCode.NRefactory.VB/AstBuilder/ExpressionBuilder.cs index 402dc449f..7ac2ef32c 100644 --- a/ICSharpCode.NRefactory.VB/AstBuilder/ExpressionBuilder.cs +++ b/ICSharpCode.NRefactory.VB/AstBuilder/ExpressionBuilder.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/AstBuilder/StatementBuilder.cs b/ICSharpCode.NRefactory.VB/AstBuilder/StatementBuilder.cs index 1f3541f15..eb227171f 100644 --- a/ICSharpCode.NRefactory.VB/AstBuilder/StatementBuilder.cs +++ b/ICSharpCode.NRefactory.VB/AstBuilder/StatementBuilder.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/IAstVisitor.cs b/ICSharpCode.NRefactory.VB/IAstVisitor.cs index a2f8ac6c7..c24e2b617 100644 --- a/ICSharpCode.NRefactory.VB/IAstVisitor.cs +++ b/ICSharpCode.NRefactory.VB/IAstVisitor.cs @@ -9,18 +9,21 @@ namespace ICSharpCode.NRefactory.VB { public interface IAstVisitor { S VisitBlockStatement(BlockStatement blockStatement, T data); + S VisitComment(Comment comment, T data); S VisitCompilationUnit(CompilationUnit compilationUnit, T data); S VisitPatternPlaceholder(AstNode placeholder, PatternMatching.Pattern pattern, T data); S VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, T data); S VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, T data); S VisitVBTokenNode(VBTokenNode vBTokenNode, T data); + S VisitEventMemberSpecifier(EventMemberSpecifier eventMemberSpecifier, T data); + S VisitInterfaceMemberSpecifier(InterfaceMemberSpecifier interfaceMemberSpecifier, T data); // Global scope S VisitAliasImportsClause(AliasImportsClause aliasImportsClause, T data); S VisitAttribute(Attribute attribute, T data); S VisitAttributeBlock(AttributeBlock attributeBlock, T data); S VisitImportsStatement(ImportsStatement importsStatement, T data); - S VisitMembersImportsClause(MemberImportsClause membersImportsClause, T data); + S VisitMemberImportsClause(MemberImportsClause memberImportsClause, T data); S VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, T data); S VisitOptionStatement(OptionStatement optionStatement, T data); S VisitTypeDeclaration(TypeDeclaration typeDeclaration, T data); @@ -29,12 +32,70 @@ namespace ICSharpCode.NRefactory.VB { S VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, T data); S VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, T data); + // TypeMember scope + S VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, T data); + S VisitMethodDeclaration(MethodDeclaration methodDeclaration, T data); + S VisitExternalMethodDeclaration(ExternalMethodDeclaration externalMethodDeclaration, T data); + S VisitFieldDeclaration(FieldDeclaration fieldDeclaration, T data); + S VisitVariableDeclaratorWithTypeAndInitializer(VariableDeclaratorWithTypeAndInitializer variableDeclaratorWithTypeAndInitializer, T data); + S VisitVariableDeclaratorWithObjectCreation(VariableDeclaratorWithObjectCreation variableDeclaratorWithObjectCreation, T data); + S VisitVariableIdentifier(VariableIdentifier variableIdentifier, T data); + S VisitAccessor(Accessor accessor, T data); + S VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, T data); + S VisitEventDeclaration(EventDeclaration eventDeclaration, T data); + S VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, T data); + // Expression scope S VisitIdentifier(Identifier identifier, T data); S VisitXmlIdentifier(XmlIdentifier xmlIdentifier, T data); S VisitXmlLiteralString(XmlLiteralString xmlLiteralString, T data); S VisitSimpleNameExpression(SimpleNameExpression identifierExpression, T data); S VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, T data); + S VisitInstanceExpression(InstanceExpression instanceExpression, T data); + S VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, T data); + S VisitGetTypeExpression(GetTypeExpression getTypeExpression, T data); + S VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, T data); + S VisitGetXmlNamespaceExpression(GetXmlNamespaceExpression getXmlNamespaceExpression, T data); + S VisitMemberAccessExpression(MemberAccessExpression memberAccessExpression, T data); + S VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, T data); + S VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, T data); + S VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, T data); + S VisitAssignmentExpression(AssignmentExpression assignmentExpression, T data); + S VisitIdentifierExpression(IdentifierExpression identifierExpression, T data); + S VisitInvocationExpression(InvocationExpression invocationExpression, T data); + S VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, T data); + S VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, T data); + S VisitObjectCreationExpression(ObjectCreationExpression objectCreationExpression, T data); + S VisitCastExpression(CastExpression castExpression, T data); + S VisitFieldInitializerExpression(FieldInitializerExpression fieldInitializerExpression, T data); + S VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, T data); + S VisitConditionalExpression(ConditionalExpression conditionalExpression, T data); + + // Statement scope + S VisitLabelDeclarationStatement(LabelDeclarationStatement labelDeclarationStatement, T data); + S VisitLocalDeclarationStatement(LocalDeclarationStatement localDeclarationStatement, T data); + S VisitExpressionStatement(ExpressionStatement expressionStatement, T data); + S VisitWithStatement(WithStatement withStatement, T data); + S VisitSyncLockStatement(SyncLockStatement syncLockStatement, T data); + S VisitIfElseStatement(IfElseStatement ifElseStatement, T data); + S VisitTryStatement(TryStatement tryStatement, T data); + S VisitThrowStatement(ThrowStatement throwStatement, T data); + S VisitCatchBlock(CatchBlock catchBlock, T data); + S VisitReturnStatement(ReturnStatement returnStatement, T data); + S VisitWhileStatement(WhileStatement whileStatement, T data); + S VisitForStatement(ForStatement forStatement, T data); + S VisitForEachStatement(ForEachStatement forEachStatement, T data); + S VisitExitStatement(ExitStatement exitStatement, T data); + S VisitContinueStatement(ContinueStatement continueStatement, T data); + S VisitSelectStatement(SelectStatement selectStatement, T data); + S VisitYieldStatement(YieldStatement yieldStatement, T data); + S VisitVariableInitializer(VariableInitializer variableInitializer, T data); + S VisitRangeCaseClause(RangeCaseClause rangeCaseClause, T data); + S VisitComparisonCaseClause(ComparisonCaseClause comparisonCaseClause, T data); + S VisitSimpleCaseClause(SimpleCaseClause simpleCaseClause, T data); + S VisitCaseStatement(CaseStatement caseStatement, T data); + S VisitDoLoopStatement(DoLoopStatement doLoopStatement, T data); + S VisitUsingStatement(UsingStatement usingStatement, T data); // TypeName S VisitPrimitiveType(PrimitiveType primitiveType, T data); @@ -42,5 +103,33 @@ namespace ICSharpCode.NRefactory.VB { S VisitComposedType(ComposedType composedType, T data); S VisitArraySpecifier(ArraySpecifier arraySpecifier, T data); S VisitSimpleType(SimpleType simpleType, T data); + + S VisitGoToStatement(GoToStatement goToStatement, T data); + + S VisitSingleLineSubLambdaExpression(SingleLineSubLambdaExpression singleLineSubLambdaExpression, T data); + S VisitMultiLineLambdaExpression(MultiLineLambdaExpression multiLineLambdaExpression, T data); + S VisitSingleLineFunctionLambdaExpression(SingleLineFunctionLambdaExpression singleLineFunctionLambdaExpression, T data); + + S VisitQueryExpression(QueryExpression queryExpression, T data); + + S VisitEmptyExpression(EmptyExpression emptyExpression, T data); + + S VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpression anonymousObjectCreationExpression, T data); + + S VisitCollectionRangeVariableDeclaration(CollectionRangeVariableDeclaration collectionRangeVariableDeclaration, T data); + + S VisitFromQueryOperator(FromQueryOperator fromQueryOperator, T data); + S VisitAggregateQueryOperator(AggregateQueryOperator aggregateQueryOperator, T data); + S VisitSelectQueryOperator(SelectQueryOperator selectQueryOperator, T data); + S VisitDistinctQueryOperator(DistinctQueryOperator distinctQueryOperator, T data); + S VisitWhereQueryOperator(WhereQueryOperator whereQueryOperator, T data); + S VisitOrderExpression(OrderExpression orderExpression, T data); + S VisitOrderByQueryOperator(OrderByQueryOperator orderByQueryOperator, T data); + S VisitPartitionQueryOperator(PartitionQueryOperator partitionQueryOperator, T data); + S VisitLetQueryOperator(LetQueryOperator letQueryOperator, T data); + S VisitGroupByQueryOperator(GroupByQueryOperator groupByQueryOperator, T data); + S VisitJoinQueryOperator(JoinQueryOperator joinQueryOperator, T data); + S VisitJoinCondition(JoinCondition joinCondition, T data); + S VisitGroupJoinQueryOperator(GroupJoinQueryOperator groupJoinQueryOperator, T data); } } diff --git a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj index 1dac9e1d9..f6de8470b 100644 --- a/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj +++ b/ICSharpCode.NRefactory.VB/ICSharpCode.NRefactory.VB.csproj @@ -3,16 +3,19 @@ {7B82B671-419F-45F4-B778-D9286F996EFA} Debug - x86 + AnyCPU Library ICSharpCode.NRefactory.VB ICSharpCode.NRefactory.VB v4.0 Properties - Client + False + False + 4 + false - - x86 + + AnyCPU bin\Debug\ @@ -43,19 +46,46 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -70,7 +100,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -122,6 +180,7 @@ + @@ -130,6 +189,7 @@ + @@ -160,6 +220,10 @@ + + {53DCA265-3C3C-42F9-B647-F72BA678122B} + ICSharpCode.NRefactory.CSharp + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371} ICSharpCode.NRefactory diff --git a/ICSharpCode.NRefactory.VB/Lexer/Block.cs b/ICSharpCode.NRefactory.VB/Lexer/Block.cs index c9ffba0d2..6b4218e7c 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Block.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Block.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -33,11 +33,11 @@ namespace ICSharpCode.NRefactory.VB.Parser { public static readonly Block Default = new Block() { context = Context.Global, - lastExpressionStart = AstLocation.Empty + lastExpressionStart = TextLocation.Empty }; public Context context; - public AstLocation lastExpressionStart; + public TextLocation lastExpressionStart; public bool isClosed; public override string ToString() diff --git a/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.cs b/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.cs index 15b9bdd6d..42b6e05c4 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinder.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -28,7 +28,7 @@ namespace ICSharpCode.NRefactory.VB.Parser void PushContext(Context context, Token la, Token t) { string indent = new string('\t', stack.Count); - AstLocation l = la == null ? (t == null ? AstLocation.Empty : t.EndLocation) : la.Location; + TextLocation l = la == null ? (t == null ? TextLocation.Empty : t.EndLocation) : la.Location; stack.Push(new Block() { context = context, lastExpressionStart = l }); Print(indent + "enter " + context); diff --git a/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinderState.cs b/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinderState.cs index 485ed3d23..0feda1f93 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinderState.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/ExpressionFinderState.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Extensions.cs b/ICSharpCode.NRefactory.VB/Lexer/Extensions.cs index 7b5d4163a..0107d3f08 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Extensions.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Extensions.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Lexer/LATextReader.cs b/ICSharpCode.NRefactory.VB/Lexer/LATextReader.cs index f11043307..eff8b821e 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/LATextReader.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/LATextReader.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Lexer/LookupTable.cs b/ICSharpCode.NRefactory.VB/Lexer/LookupTable.cs index 2ec80b687..eb2c94dfc 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/LookupTable.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/LookupTable.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Globalization; diff --git a/ICSharpCode.NRefactory.VB/Lexer/SavepointEventArgs.cs b/ICSharpCode.NRefactory.VB/Lexer/SavepointEventArgs.cs index f3ee77a93..c599ca7f5 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/SavepointEventArgs.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/SavepointEventArgs.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; @@ -8,10 +8,10 @@ namespace ICSharpCode.NRefactory.VB.Parser { public class SavepointEventArgs : EventArgs { - public AstLocation SavepointLocation { get; private set; } + public TextLocation SavepointLocation { get; private set; } public VBLexerMemento State { get; private set; } - public SavepointEventArgs(AstLocation savepointLocation, VBLexerMemento state) + public SavepointEventArgs(TextLocation savepointLocation, VBLexerMemento state) { this.SavepointLocation = savepointLocation; this.State = state; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Special/BlankLine.cs b/ICSharpCode.NRefactory.VB/Lexer/Special/BlankLine.cs index 5120bd765..5821ca6a9 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Special/BlankLine.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Special/BlankLine.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Special/Comment.cs b/ICSharpCode.NRefactory.VB/Lexer/Special/Comment.cs index 82772f2d4..ecfc393fa 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Special/Comment.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Special/Comment.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Special/CommentType.cs b/ICSharpCode.NRefactory.VB/Lexer/Special/CommentType.cs index 1c9bb63e9..7eac974d5 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Special/CommentType.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Special/CommentType.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Special/ISpecial.cs b/ICSharpCode.NRefactory.VB/Lexer/Special/ISpecial.cs index a58964211..52c1abb37 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Special/ISpecial.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Special/ISpecial.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Special/PreProcessingDirective.cs b/ICSharpCode.NRefactory.VB/Lexer/Special/PreProcessingDirective.cs index 97c0a7481..4b9222190 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Special/PreProcessingDirective.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Special/PreProcessingDirective.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Special/SpecialTracker.cs b/ICSharpCode.NRefactory.VB/Lexer/Special/SpecialTracker.cs index 2107163e4..6ae334b2f 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Special/SpecialTracker.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Special/SpecialTracker.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Special/TagComment.cs b/ICSharpCode.NRefactory.VB/Lexer/Special/TagComment.cs index 3209cf162..39863d125 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Special/TagComment.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Special/TagComment.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Lexer/Token.cs b/ICSharpCode.NRefactory.VB/Lexer/Token.cs index ae4ed7d63..423c56a93 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/Token.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/Token.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; @@ -15,7 +15,7 @@ namespace ICSharpCode.NRefactory.VB.Parser internal readonly object literalValue; internal readonly string val; internal Token next; - readonly AstLocation endLocation; + readonly TextLocation endLocation; public int Kind { get { return kind; } @@ -29,13 +29,13 @@ namespace ICSharpCode.NRefactory.VB.Parser get { return val; } } - public AstLocation EndLocation { + public TextLocation EndLocation { get { return endLocation; } } - public AstLocation Location { + public TextLocation Location { get { - return new AstLocation(line, col); + return new TextLocation(line, col); } } @@ -48,7 +48,7 @@ namespace ICSharpCode.NRefactory.VB.Parser { } - public Token(int kind, AstLocation startLocation, AstLocation endLocation) : this(kind, startLocation, endLocation, "", null) + public Token(int kind, TextLocation startLocation, TextLocation endLocation) : this(kind, startLocation, endLocation, "", null) { } @@ -58,15 +58,15 @@ namespace ICSharpCode.NRefactory.VB.Parser this.col = col; this.line = line; this.val = val; - this.endLocation = new AstLocation(line, col + (val == null ? 1 : val.Length)); + this.endLocation = new TextLocation(line, col + (val == null ? 1 : val.Length)); } internal Token(int kind, int x, int y, string val, object literalValue) - : this(kind, new AstLocation(y, x), new AstLocation(y, x + val.Length), val, literalValue) + : this(kind, new TextLocation(y, x), new TextLocation(y, x + val.Length), val, literalValue) { } - public Token(int kind, AstLocation startLocation, AstLocation endLocation, string val, object literalValue) + public Token(int kind, TextLocation startLocation, TextLocation endLocation, string val, object literalValue) { this.kind = kind; this.col = startLocation.Column; diff --git a/ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs b/ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs index 6aac502c2..a8e316309 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/VBLexer.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections; @@ -34,7 +34,7 @@ namespace ICSharpCode.NRefactory.VB.Parser public VBLexer(TextReader reader, VBLexerMemento state) : this(reader) { - SetInitialLocation(new AstLocation(state.Line, state.Column)); + SetInitialLocation(new TextLocation(state.Line, state.Column)); lastToken = new Token(state.PrevTokenKind, 0, 0); ef = new ExpressionFinder(state.ExpressionFinder); lineEnd = state.LineEnd; @@ -54,7 +54,7 @@ namespace ICSharpCode.NRefactory.VB.Parser unchecked { while (true) { - AstLocation startLocation = new AstLocation(Line, Col); + TextLocation startLocation = new TextLocation(Line, Col); int nextChar = ReaderRead(); if (nextChar == -1) return new Token(Tokens.EOF, Col, Line, string.Empty); @@ -96,12 +96,12 @@ namespace ICSharpCode.NRefactory.VB.Parser if (ReaderPeek() == '/') { ReaderRead(); info.inXmlCloseTag = true; - return new Token(Tokens.XmlOpenEndTag, new AstLocation(y, x), new AstLocation(Line, Col)); + return new Token(Tokens.XmlOpenEndTag, new TextLocation(y, x), new TextLocation(Line, Col)); } if (ReaderPeek() == '%' && ReaderPeek(1) == '=') { inXmlMode = false; ReaderRead(); ReaderRead(); - return new Token(Tokens.XmlStartInlineVB, new AstLocation(y, x), new AstLocation(Line, Col)); + return new Token(Tokens.XmlStartInlineVB, new TextLocation(y, x), new TextLocation(Line, Col)); } if (ReaderPeek() == '?') { ReaderRead(); @@ -122,7 +122,7 @@ namespace ICSharpCode.NRefactory.VB.Parser ReaderRead(); info.inXmlTag = false; info.level--; - return new Token(Tokens.XmlCloseTagEmptyElement, new AstLocation(y, x), new AstLocation(Line, Col)); + return new Token(Tokens.XmlCloseTagEmptyElement, new TextLocation(y, x), new TextLocation(Line, Col)); } break; case '>': @@ -143,7 +143,7 @@ namespace ICSharpCode.NRefactory.VB.Parser return new Token(Tokens.Identifier, x, y, ReadXmlIdent(ch)); } else { string content = ReadXmlContent(ch); - return new Token(Tokens.XmlContent, startLocation, new AstLocation(Line, Col), content, null); + return new Token(Tokens.XmlContent, startLocation, new TextLocation(Line, Col), content, null); } } #endregion @@ -157,7 +157,7 @@ namespace ICSharpCode.NRefactory.VB.Parser // specialTracker.AddEndOfLine(startLocation); } else { lineEnd = true; - return new Token(Tokens.EOL, startLocation, new AstLocation(Line, Col), null, null); + return new Token(Tokens.EOL, startLocation, new TextLocation(Line, Col), null, null); } } continue; @@ -314,7 +314,7 @@ namespace ICSharpCode.NRefactory.VB.Parser int y = Line; inXmlMode = true; ReaderRead(); - return new Token(Tokens.XmlEndInlineVB, new AstLocation(y, x), new AstLocation(Line, Col)); + return new Token(Tokens.XmlEndInlineVB, new TextLocation(y, x), new TextLocation(Line, Col)); } #endregion if (ch == '<' && (ef.NextTokenIsPotentialStartOfExpression || ef.NextTokenIsStartOfImportsOrAccessExpression)) { @@ -326,13 +326,13 @@ namespace ICSharpCode.NRefactory.VB.Parser if (ReaderPeek() == '/') { ReaderRead(); info.inXmlCloseTag = true; - return new Token(Tokens.XmlOpenEndTag, new AstLocation(y, x), new AstLocation(Line, Col)); + return new Token(Tokens.XmlOpenEndTag, new TextLocation(y, x), new TextLocation(Line, Col)); } // should we allow <%= at start of an expression? not valid with vbc ... if (ReaderPeek() == '%' && ReaderPeek(1) == '=') { inXmlMode = false; ReaderRead(); ReaderRead(); - return new Token(Tokens.XmlStartInlineVB, new AstLocation(y, x), new AstLocation(Line, Col)); + return new Token(Tokens.XmlStartInlineVB, new TextLocation(y, x), new TextLocation(Line, Col)); } if (ReaderPeek() == '!') { ReaderRead(); @@ -361,7 +361,7 @@ namespace ICSharpCode.NRefactory.VB.Parser } } - void CheckXMLState(AstLocation startLocation) + void CheckXMLState(TextLocation startLocation) { if (inXmlMode && !xmlModeStack.Any()) throw new InvalidOperationException("invalid XML stack state at " + startLocation); @@ -776,7 +776,7 @@ namespace ICSharpCode.NRefactory.VB.Parser void ReadPreprocessorDirective() { - AstLocation start = new AstLocation(Line, Col - 1); + TextLocation start = new TextLocation(Line, Col - 1); string directive = ReadIdent('#'); // TODO : expression parser for PP directives // needed for proper conversion to e. g. C# @@ -833,7 +833,7 @@ namespace ICSharpCode.NRefactory.VB.Parser void ReadComment() { - AstLocation startPos = new AstLocation(Line, Col); + TextLocation startPos = new TextLocation(Line, Col); sb.Length = 0; StringBuilder curWord = specialCommentHash != null ? new StringBuilder() : null; int missingApostrophes = 2; // no. of ' missing until it is a documentation comment @@ -866,7 +866,7 @@ namespace ICSharpCode.NRefactory.VB.Parser string tag = curWord.ToString(); curWord.Length = 0; if (specialCommentHash.ContainsKey(tag)) { - AstLocation p = new AstLocation(Line, Col); + TextLocation p = new TextLocation(Line, Col); string comment = ch + ReadToEndOfLine(); // this.TagComments.Add(new TagComment(tag, comment, isAtLineBegin, p, new Location(Col, Line))); sb.Append(comment); @@ -1046,7 +1046,7 @@ namespace ICSharpCode.NRefactory.VB.Parser ReaderSkip("?>".Length); - return new Token(Tokens.XmlProcessingInstruction, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + return new Token(Tokens.XmlProcessingInstruction, new TextLocation(y, x), new TextLocation(Line, Col), sb.ToString(), null); } Token ReadXmlCommentOrCData(int x, int y) @@ -1060,7 +1060,7 @@ namespace ICSharpCode.NRefactory.VB.Parser sb.Append((char)nextChar); if (string.CompareOrdinal(ReaderPeekString("-->".Length), "-->") == 0) { ReaderSkip("-->".Length); - return new Token(Tokens.XmlComment, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + return new Token(Tokens.XmlComment, new TextLocation(y, x), new TextLocation(Line, Col), sb.ToString(), null); } } } @@ -1071,12 +1071,12 @@ namespace ICSharpCode.NRefactory.VB.Parser sb.Append((char)nextChar); if (string.CompareOrdinal(ReaderPeekString("]]>".Length), "]]>") == 0) { ReaderSkip("]]>".Length); - return new Token(Tokens.XmlCData, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + return new Token(Tokens.XmlCData, new TextLocation(y, x), new TextLocation(Line, Col), sb.ToString(), null); } } } - return new Token(Tokens.XmlComment, new AstLocation(y, x), new AstLocation(Line, Col), sb.ToString(), null); + return new Token(Tokens.XmlComment, new TextLocation(y, x), new TextLocation(Line, Col), sb.ToString(), null); } string ReadXmlContent(char ch) @@ -1276,7 +1276,7 @@ namespace ICSharpCode.NRefactory.VB.Parser return builder.ToString(); } - public void SetInitialLocation(AstLocation location) + public void SetInitialLocation(TextLocation location) { if (lastToken != null || curToken != null || peekToken != null) throw new InvalidOperationException(); @@ -1404,12 +1404,12 @@ namespace ICSharpCode.NRefactory.VB.Parser errors.Error(line, col, String.Format("Invalid hex number '" + digit + "'")); return 0; } - protected AstLocation lastLineEnd = new AstLocation(1, 1); - protected AstLocation curLineEnd = new AstLocation(1, 1); + protected TextLocation lastLineEnd = new TextLocation(1, 1); + protected TextLocation curLineEnd = new TextLocation(1, 1); protected void LineBreak () { lastLineEnd = curLineEnd; - curLineEnd = new AstLocation (line, col - 1); + curLineEnd = new TextLocation (line, col - 1); } protected bool HandleLineEnd(char ch) { diff --git a/ICSharpCode.NRefactory.VB/Lexer/VBLexerMemento.cs b/ICSharpCode.NRefactory.VB/Lexer/VBLexerMemento.cs index 148475ccd..30e9d0f8c 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/VBLexerMemento.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/VBLexerMemento.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Lexer/XmlModeInfo.cs b/ICSharpCode.NRefactory.VB/Lexer/XmlModeInfo.cs index 4f3ef71e9..2141ac353 100644 --- a/ICSharpCode.NRefactory.VB/Lexer/XmlModeInfo.cs +++ b/ICSharpCode.NRefactory.VB/Lexer/XmlModeInfo.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/IOutputFormatter.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/IOutputFormatter.cs index a544eb0d0..056b0d1cd 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/IOutputFormatter.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/IOutputFormatter.cs @@ -16,7 +16,7 @@ namespace ICSharpCode.NRefactory.VB /// /// Writes an identifier. /// If the identifier conflicts with a keyword, the output visitor will - /// call WriteToken("@") before calling WriteIdentifier(). + /// call WriteToken("[") before and WriteToken("]") after calling WriteIdentifier(). /// void WriteIdentifier(string identifier); @@ -35,5 +35,10 @@ namespace ICSharpCode.NRefactory.VB void Unindent(); void NewLine(); + + void WriteComment(bool isDocumentation, string content); + + void MarkFoldStart(); + void MarkFoldEnd(); } } diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs index f4085b6bc..eacb30db4 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/OutputVisitor.cs @@ -1,9 +1,13 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Globalization; using System.IO; +using System.Linq; +using System.Text; using ICSharpCode.NRefactory.PatternMatching; using ICSharpCode.NRefactory.VB.Ast; @@ -13,7 +17,7 @@ namespace ICSharpCode.NRefactory.VB /// /// Description of OutputVisitor. /// - public class OutputVisitor : IAstVisitor, IPatternAstVisitor + public class OutputVisitor : IAstVisitor { readonly IOutputFormatter formatter; readonly VBFormattingOptions policy; @@ -21,6 +25,18 @@ namespace ICSharpCode.NRefactory.VB readonly Stack containerStack = new Stack(); readonly Stack positionStack = new Stack(); + /// + /// Used to insert the minimal amount of spaces so that the lexer recognizes the tokens that were written. + /// + LastWritten lastWritten; + + enum LastWritten + { + Whitespace, + Other, + KeywordOrIdentifier + } + public OutputVisitor(TextWriter textWriter, VBFormattingOptions formattingPolicy) { if (textWriter == null) @@ -41,7 +57,7 @@ namespace ICSharpCode.NRefactory.VB this.policy = formattingPolicy; } - public object VisitCompilationUnit(ICSharpCode.NRefactory.VB.Ast.CompilationUnit compilationUnit, object data) + public object VisitCompilationUnit(CompilationUnit compilationUnit, object data) { // don't do node tracking as we visit all children directly foreach (AstNode node in compilationUnit.Children) @@ -51,7 +67,12 @@ namespace ICSharpCode.NRefactory.VB public object VisitBlockStatement(BlockStatement blockStatement, object data) { - throw new NotImplementedException(); + StartNode(blockStatement); + foreach (var stmt in blockStatement) { + stmt.AcceptVisitor(this, data); + NewLine(); + } + return EndNode(blockStatement); } public object VisitPatternPlaceholder(AstNode placeholder, Pattern pattern, object data) @@ -61,17 +82,61 @@ namespace ICSharpCode.NRefactory.VB public object VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) { - throw new NotImplementedException(); + StartNode(typeParameterDeclaration); + + switch (typeParameterDeclaration.Variance) { + case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Invariant: + break; + case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Covariant: + WriteKeyword("Out"); + break; + case ICSharpCode.NRefactory.TypeSystem.VarianceModifier.Contravariant: + WriteKeyword("In"); + break; + default: + throw new Exception("Invalid value for VarianceModifier"); + } + + WriteIdentifier(typeParameterDeclaration.Name); + if (typeParameterDeclaration.Constraints.Any()) { + WriteKeyword("As"); + if (typeParameterDeclaration.Constraints.Count > 1) + WriteToken("{", TypeParameterDeclaration.Roles.LBrace); + WriteCommaSeparatedList(typeParameterDeclaration.Constraints); + if (typeParameterDeclaration.Constraints.Count > 1) + WriteToken("}", TypeParameterDeclaration.Roles.RBrace); + } + + return EndNode(typeParameterDeclaration); } public object VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data) { - throw new NotImplementedException(); + StartNode(parameterDeclaration); + WriteAttributes(parameterDeclaration.Attributes); + WriteModifiers(parameterDeclaration.ModifierTokens); + WriteIdentifier(parameterDeclaration.Name.Name); + if (!parameterDeclaration.Type.IsNull) { + WriteKeyword("As"); + parameterDeclaration.Type.AcceptVisitor(this, data); + } + if (!parameterDeclaration.OptionalValue.IsNull) { + WriteToken("=", ParameterDeclaration.Roles.Assign); + parameterDeclaration.OptionalValue.AcceptVisitor(this, data); + } + return EndNode(parameterDeclaration); } public object VisitVBTokenNode(VBTokenNode vBTokenNode, object data) { - throw new NotImplementedException(); + var mod = vBTokenNode as VBModifierToken; + if (mod != null) { + StartNode(vBTokenNode); + WriteKeyword(VBModifierToken.GetModifierName(mod.Modifier)); + return EndNode(vBTokenNode); + } else { + throw new NotSupportedException("Should never visit individual tokens"); + } } public object VisitAliasImportsClause(AliasImportsClause aliasImportsClause, object data) @@ -81,27 +146,84 @@ namespace ICSharpCode.NRefactory.VB public object VisitAttribute(ICSharpCode.NRefactory.VB.Ast.Attribute attribute, object data) { - throw new NotImplementedException(); + StartNode(attribute); + + if (attribute.Target != AttributeTarget.None) { + switch (attribute.Target) { + case AttributeTarget.None: + break; + case AttributeTarget.Assembly: + WriteKeyword("Assembly"); + break; + case AttributeTarget.Module: + WriteKeyword("Module"); + break; + default: + throw new Exception("Invalid value for AttributeTarget"); + } + WriteToken(":", Ast.Attribute.Roles.Colon); + Space(); + } + attribute.Type.AcceptVisitor(this, data); + WriteCommaSeparatedListInParenthesis(attribute.Arguments, false); + + return EndNode(attribute); } public object VisitAttributeBlock(AttributeBlock attributeBlock, object data) { - throw new NotImplementedException(); + StartNode(attributeBlock); + + WriteToken("<", AttributeBlock.Roles.LChevron); + WriteCommaSeparatedList(attributeBlock.Attributes); + WriteToken(">", AttributeBlock.Roles.RChevron); + if (attributeBlock.Parent is ParameterDeclaration) + Space(); + else + NewLine(); + + return EndNode(attributeBlock); } public object VisitImportsStatement(ImportsStatement importsStatement, object data) { - throw new NotImplementedException(); + StartNode(importsStatement); + + WriteKeyword("Imports", AstNode.Roles.Keyword); + Space(); + WriteCommaSeparatedList(importsStatement.ImportsClauses); + NewLine(); + + return EndNode(importsStatement); } - public object VisitMembersImportsClause(MemberImportsClause membersImportsClause, object data) + public object VisitMemberImportsClause(MemberImportsClause memberImportsClause, object data) { - throw new NotImplementedException(); + StartNode(memberImportsClause); + memberImportsClause.Member.AcceptVisitor(this, data); + return EndNode(memberImportsClause); } public object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) { - throw new NotImplementedException(); + StartNode(namespaceDeclaration); + NewLine(); + WriteKeyword("Namespace"); + bool isFirst = true; + foreach (Identifier node in namespaceDeclaration.Identifiers) { + if (isFirst) { + isFirst = false; + } else { + WriteToken(".", NamespaceDeclaration.Roles.Dot); + } + node.AcceptVisitor(this, null); + } + NewLine(); + WriteMembers(namespaceDeclaration.Members); + WriteKeyword("End"); + WriteKeyword("Namespace"); + NewLine(); + return EndNode(namespaceDeclaration); } public object VisitOptionStatement(OptionStatement optionStatement, object data) @@ -111,7 +233,58 @@ namespace ICSharpCode.NRefactory.VB public object VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) { - throw new NotImplementedException(); + StartNode(typeDeclaration); + WriteAttributes(typeDeclaration.Attributes); + WriteModifiers(typeDeclaration.ModifierTokens); + WriteClassTypeKeyword(typeDeclaration); + WriteIdentifier(typeDeclaration.Name.Name); + MarkFoldStart(); + NewLine(); + + if (!typeDeclaration.InheritsType.IsNull) { + Indent(); + WriteKeyword("Inherits"); + typeDeclaration.InheritsType.AcceptVisitor(this, data); + Unindent(); + NewLine(); + } + if (typeDeclaration.ImplementsTypes.Any()) { + Indent(); + WriteImplementsClause(typeDeclaration.ImplementsTypes); + Unindent(); + NewLine(); + } + + if (!typeDeclaration.InheritsType.IsNull || typeDeclaration.ImplementsTypes.Any()) + NewLine(); + + WriteMembers(typeDeclaration.Members); + + WriteKeyword("End"); + WriteClassTypeKeyword(typeDeclaration); + MarkFoldEnd(); + NewLine(); + return EndNode(typeDeclaration); + } + + void WriteClassTypeKeyword(TypeDeclaration typeDeclaration) + { + switch (typeDeclaration.ClassType) { + case ClassType.Class: + WriteKeyword("Class"); + break; + case ClassType.Interface: + WriteKeyword("Interface"); + break; + case ClassType.Struct: + WriteKeyword("Structure"); + break; + case ClassType.Module: + WriteKeyword("Module"); + break; + default: + throw new Exception("Invalid value for ClassType"); + } } public object VisitXmlNamespaceImportsClause(XmlNamespaceImportsClause xmlNamespaceImportsClause, object data) @@ -121,22 +294,83 @@ namespace ICSharpCode.NRefactory.VB public object VisitEnumDeclaration(EnumDeclaration enumDeclaration, object data) { - throw new NotImplementedException(); + StartNode(enumDeclaration); + + WriteAttributes(enumDeclaration.Attributes); + WriteModifiers(enumDeclaration.ModifierTokens); + WriteKeyword("Enum"); + WriteIdentifier(enumDeclaration.Name.Name); + if (!enumDeclaration.UnderlyingType.IsNull) { + Space(); + WriteKeyword("As"); + enumDeclaration.UnderlyingType.AcceptVisitor(this, data); + } + MarkFoldStart(); + NewLine(); + + Indent(); + foreach (var member in enumDeclaration.Members) { + member.AcceptVisitor(this, null); + } + Unindent(); + + WriteKeyword("End"); + WriteKeyword("Enum"); + MarkFoldEnd(); + NewLine(); + + return EndNode(enumDeclaration); } public object VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) { - throw new NotImplementedException(); + StartNode(enumMemberDeclaration); + + WriteAttributes(enumMemberDeclaration.Attributes); + WriteIdentifier(enumMemberDeclaration.Name.Name); + + if (!enumMemberDeclaration.Value.IsNull) { + Space(); + WriteToken("=", EnumMemberDeclaration.Roles.Assign); + Space(); + enumMemberDeclaration.Value.AcceptVisitor(this, data); + } + NewLine(); + + return EndNode(enumMemberDeclaration); } public object VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) { - throw new NotImplementedException(); + StartNode(delegateDeclaration); + + WriteAttributes(delegateDeclaration.Attributes); + WriteModifiers(delegateDeclaration.ModifierTokens); + WriteKeyword("Delegate"); + if (delegateDeclaration.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + WriteIdentifier(delegateDeclaration.Name.Name); + WriteTypeParameters(delegateDeclaration.TypeParameters); + WriteCommaSeparatedListInParenthesis(delegateDeclaration.Parameters, false); + if (!delegateDeclaration.IsSub) { + Space(); + WriteKeyword("As"); + WriteAttributes(delegateDeclaration.ReturnTypeAttributes); + delegateDeclaration.ReturnType.AcceptVisitor(this, data); + } + NewLine(); + + return EndNode(delegateDeclaration); } public object VisitIdentifier(Identifier identifier, object data) { - throw new NotImplementedException(); + StartNode(identifier); + WriteIdentifier(identifier.Name); + WriteTypeCharacter(identifier.TypeCharacter); + return EndNode(identifier); } public object VisitXmlIdentifier(XmlIdentifier xmlIdentifier, object data) @@ -149,74 +383,2269 @@ namespace ICSharpCode.NRefactory.VB throw new NotImplementedException(); } - public object VisitSimpleNameExpression(SimpleNameExpression identifierExpression, object data) + public object VisitSimpleNameExpression(SimpleNameExpression simpleNameExpression, object data) { - throw new NotImplementedException(); + StartNode(simpleNameExpression); + + simpleNameExpression.Identifier.AcceptVisitor(this, data); + WriteTypeArguments(simpleNameExpression.TypeArguments); + + return EndNode(simpleNameExpression); } public object VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) + { + StartNode(primitiveExpression); + + WritePrimitiveValue(primitiveExpression.Value); + + return EndNode(primitiveExpression); + } + + public object VisitInstanceExpression(InstanceExpression instanceExpression, object data) + { + StartNode(instanceExpression); + + switch (instanceExpression.Type) { + case InstanceExpressionType.Me: + WriteKeyword("Me"); + break; + case InstanceExpressionType.MyBase: + WriteKeyword("MyBase"); + break; + case InstanceExpressionType.MyClass: + WriteKeyword("MyClass"); + break; + default: + throw new Exception("Invalid value for InstanceExpressionType"); + } + + return EndNode(instanceExpression); + } + + public object VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) + { + StartNode(parenthesizedExpression); + + LPar(); + parenthesizedExpression.Expression.AcceptVisitor(this, data); + RPar(); + + return EndNode(parenthesizedExpression); + } + + public object VisitGetTypeExpression(GetTypeExpression getTypeExpression, object data) + { + StartNode(getTypeExpression); + + WriteKeyword("GetType"); + LPar(); + getTypeExpression.Type.AcceptVisitor(this, data); + RPar(); + + return EndNode(getTypeExpression); + } + + public object VisitTypeOfIsExpression(TypeOfIsExpression typeOfIsExpression, object data) + { + StartNode(typeOfIsExpression); + + WriteKeyword("TypeOf"); + typeOfIsExpression.TypeOfExpression.AcceptVisitor(this, data); + WriteKeyword("Is"); + typeOfIsExpression.Type.AcceptVisitor(this, data); + + return EndNode(typeOfIsExpression); + } + + public object VisitGetXmlNamespaceExpression(GetXmlNamespaceExpression getXmlNamespaceExpression, object data) { throw new NotImplementedException(); } + public object VisitMemberAccessExpression(MemberAccessExpression memberAccessExpression, object data) + { + StartNode(memberAccessExpression); + + memberAccessExpression.Target.AcceptVisitor(this, data); + WriteToken(".", MemberAccessExpression.Roles.Dot); + memberAccessExpression.MemberName.AcceptVisitor(this, data); + WriteTypeArguments(memberAccessExpression.TypeArguments); + + return EndNode(memberAccessExpression); + } + + public object VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) + { + StartNode(typeReferenceExpression); + + typeReferenceExpression.Type.AcceptVisitor(this, data); + + return EndNode(typeReferenceExpression); + } + + public object VisitEventMemberSpecifier(EventMemberSpecifier eventMemberSpecifier, object data) + { + StartNode(eventMemberSpecifier); + + eventMemberSpecifier.Target.AcceptVisitor(this, data); + WriteToken(".", EventMemberSpecifier.Roles.Dot); + eventMemberSpecifier.Member.AcceptVisitor(this, data); + + return EndNode(eventMemberSpecifier); + } + + public object VisitInterfaceMemberSpecifier(InterfaceMemberSpecifier interfaceMemberSpecifier, object data) + { + StartNode(interfaceMemberSpecifier); + + interfaceMemberSpecifier.Target.AcceptVisitor(this, data); + WriteToken(".", EventMemberSpecifier.Roles.Dot); + interfaceMemberSpecifier.Member.AcceptVisitor(this, data); + + return EndNode(interfaceMemberSpecifier); + } + + #region TypeMembers + public object VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) + { + StartNode(constructorDeclaration); + + WriteAttributes(constructorDeclaration.Attributes); + WriteModifiers(constructorDeclaration.ModifierTokens); + WriteKeyword("Sub"); + WriteKeyword("New"); + WriteCommaSeparatedListInParenthesis(constructorDeclaration.Parameters, false); + MarkFoldStart(); + NewLine(); + + Indent(); + WriteBlock(constructorDeclaration.Body); + Unindent(); + + WriteKeyword("End"); + WriteKeyword("Sub"); + MarkFoldEnd(); + NewLine(); + + return EndNode(constructorDeclaration); + } + + public object VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) + { + StartNode(methodDeclaration); + + WriteAttributes(methodDeclaration.Attributes); + WriteModifiers(methodDeclaration.ModifierTokens); + if (methodDeclaration.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + methodDeclaration.Name.AcceptVisitor(this, data); + WriteTypeParameters(methodDeclaration.TypeParameters); + WriteCommaSeparatedListInParenthesis(methodDeclaration.Parameters, false); + if (!methodDeclaration.IsSub && !methodDeclaration.ReturnType.IsNull) { + Space(); + WriteKeyword("As"); + WriteAttributes(methodDeclaration.ReturnTypeAttributes); + methodDeclaration.ReturnType.AcceptVisitor(this, data); + } + WriteHandlesClause(methodDeclaration.HandlesClause); + WriteImplementsClause(methodDeclaration.ImplementsClause); + if (!methodDeclaration.Body.IsNull) { + MarkFoldStart(); + NewLine(); + Indent(); + WriteBlock(methodDeclaration.Body); + Unindent(); + WriteKeyword("End"); + if (methodDeclaration.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + MarkFoldEnd(); + } + NewLine(); + + return EndNode(methodDeclaration); + } + + public object VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) + { + StartNode(fieldDeclaration); + + WriteAttributes(fieldDeclaration.Attributes); + WriteModifiers(fieldDeclaration.ModifierTokens); + WriteCommaSeparatedList(fieldDeclaration.Variables); + NewLine(); + + return EndNode(fieldDeclaration); + } + + public object VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) + { + StartNode(propertyDeclaration); + + WriteAttributes(propertyDeclaration.Attributes); + WriteModifiers(propertyDeclaration.ModifierTokens); + WriteKeyword("Property"); + WriteIdentifier(propertyDeclaration.Name.Name); + WriteCommaSeparatedListInParenthesis(propertyDeclaration.Parameters, false); + if (!propertyDeclaration.ReturnType.IsNull) { + Space(); + WriteKeyword("As"); + WriteAttributes(propertyDeclaration.ReturnTypeAttributes); + propertyDeclaration.ReturnType.AcceptVisitor(this, data); + } + + bool needsBody = !propertyDeclaration.Getter.Body.IsNull || !propertyDeclaration.Setter.Body.IsNull; + + if (needsBody) { + MarkFoldStart(); + NewLine(); + Indent(); + + if (!propertyDeclaration.Getter.Body.IsNull) { + propertyDeclaration.Getter.AcceptVisitor(this, data); + } + + if (!propertyDeclaration.Setter.Body.IsNull) { + propertyDeclaration.Setter.AcceptVisitor(this, data); + } + Unindent(); + + WriteKeyword("End"); + WriteKeyword("Property"); + MarkFoldEnd(); + } + NewLine(); + + return EndNode(propertyDeclaration); + } + #endregion + + #region TypeName public object VisitPrimitiveType(PrimitiveType primitiveType, object data) { - throw new NotImplementedException(); + StartNode(primitiveType); + + WriteKeyword(primitiveType.Keyword); + + return EndNode(primitiveType); } public object VisitQualifiedType(QualifiedType qualifiedType, object data) { - throw new NotImplementedException(); + StartNode(qualifiedType); + + qualifiedType.Target.AcceptVisitor(this, data); + WriteToken(".", AstNode.Roles.Dot); + WriteIdentifier(qualifiedType.Name); + WriteTypeArguments(qualifiedType.TypeArguments); + + return EndNode(qualifiedType); } public object VisitComposedType(ComposedType composedType, object data) { - throw new NotImplementedException(); + StartNode(composedType); + + composedType.BaseType.AcceptVisitor(this, data); + if (composedType.HasNullableSpecifier) + WriteToken("?", ComposedType.Roles.QuestionMark); + WriteArraySpecifiers(composedType.ArraySpecifiers); + + return EndNode(composedType); } public object VisitArraySpecifier(ArraySpecifier arraySpecifier, object data) { - throw new NotImplementedException(); + StartNode(arraySpecifier); + + LPar(); + for (int i = 0; i < arraySpecifier.Dimensions - 1; i++) { + WriteToken(",", ArraySpecifier.Roles.Comma); + } + RPar(); + + return EndNode(arraySpecifier); } public object VisitSimpleType(SimpleType simpleType, object data) { - throw new NotImplementedException(); + StartNode(simpleType); + + WriteIdentifier(simpleType.Identifier); + WriteTypeArguments(simpleType.TypeArguments); + + return EndNode(simpleType); } + #endregion - public object VisitAnyNode(AnyNode anyNode, object data) + #region StartNode/EndNode + void StartNode(AstNode node) { - throw new NotImplementedException(); + // Ensure that nodes are visited in the proper nested order. + // Jumps to different subtrees are allowed only for the child of a placeholder node. + Debug.Assert(containerStack.Count == 0 || node.Parent == containerStack.Peek()); + if (positionStack.Count > 0) + WriteSpecialsUpToNode(node); + containerStack.Push(node); + positionStack.Push(node.FirstChild); + formatter.StartNode(node); } - public object VisitBackreference(Backreference backreference, object data) + object EndNode(AstNode node) { - throw new NotImplementedException(); + Debug.Assert(node == containerStack.Peek()); + AstNode pos = positionStack.Pop(); + Debug.Assert(pos == null || pos.Parent == node); + WriteSpecials(pos, null); + containerStack.Pop(); + formatter.EndNode(node); + return null; } + #endregion - public object VisitChoice(Choice choice, object data) + #region WriteSpecials + /// + /// Writes all specials from start to end (exclusive). Does not touch the positionStack. + /// + void WriteSpecials(AstNode start, AstNode end) { - throw new NotImplementedException(); + for (AstNode pos = start; pos != end; pos = pos.NextSibling) { + if (pos.Role == AstNode.Roles.Comment) { + pos.AcceptVisitor(this, null); + } + } } - public object VisitNamedNode(NamedNode namedNode, object data) + /// + /// Writes all specials between the current position (in the positionStack) and the next + /// node with the specified role. Advances the current position. + /// + void WriteSpecialsUpToRole(Role role) { - throw new NotImplementedException(); + for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { + if (pos.Role == role) { + WriteSpecials(positionStack.Pop(), pos); + positionStack.Push(pos); + break; + } + } } - public object VisitRepeat(Repeat repeat, object data) + /// + /// Writes all specials between the current position (in the positionStack) and the specified node. + /// Advances the current position. + /// + void WriteSpecialsUpToNode(AstNode node) { - throw new NotImplementedException(); + for (AstNode pos = positionStack.Peek(); pos != null; pos = pos.NextSibling) { + if (pos == node) { + WriteSpecials(positionStack.Pop(), pos); + positionStack.Push(pos); + break; + } + } } - public object VisitOptionalNode(OptionalNode optionalNode, object data) + void WriteSpecialsUpToRole(Role role, AstNode nextNode) { - throw new NotImplementedException(); + // Look for the role between the current position and the nextNode. + for (AstNode pos = positionStack.Peek(); pos != null && pos != nextNode; pos = pos.NextSibling) { + if (pos.Role == AstNode.Roles.Comma) { + WriteSpecials(positionStack.Pop(), pos); + positionStack.Push(pos); + break; + } + } } + #endregion - public object VisitIdentifierExpressionBackreference(IdentifierExpressionBackreference identifierExpressionBackreference, object data) + #region Comma + /// + /// Writes a comma. + /// + /// The next node after the comma. + /// When set prevents printing a space after comma. + void Comma(AstNode nextNode, bool noSpaceAfterComma = false) + { + WriteSpecialsUpToRole(AstNode.Roles.Comma, nextNode); + formatter.WriteToken(","); + lastWritten = LastWritten.Other; + Space(!noSpaceAfterComma); // TODO: Comma policy has changed. + } + + void WriteCommaSeparatedList(IEnumerable list) + { + bool isFirst = true; + foreach (AstNode node in list) { + if (isFirst) { + isFirst = false; + } else { + Comma(node); + } + node.AcceptVisitor(this, null); + } + } + + void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + { + LPar(); + if (list.Any()) { + Space(spaceWithin); + WriteCommaSeparatedList(list); + Space(spaceWithin); + } + RPar(); + } + + #if DOTNET35 + void WriteCommaSeparatedList(IEnumerable list) + { + WriteCommaSeparatedList(list); + } + + void WriteCommaSeparatedList(IEnumerable list) + { + WriteCommaSeparatedList(list); + } + + void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + { + WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); + } + + void WriteCommaSeparatedListInParenthesis(IEnumerable list, bool spaceWithin) + { + WriteCommaSeparatedListInParenthesis(list.SafeCast(), spaceWithin); + } + + #endif + + void WriteCommaSeparatedListInBrackets(IEnumerable list, bool spaceWithin) + { + WriteToken("[", AstNode.Roles.LBracket); + if (list.Any()) { + Space(spaceWithin); + WriteCommaSeparatedList(list); + Space(spaceWithin); + } + WriteToken("]", AstNode.Roles.RBracket); + } + + void WriteCommaSeparatedListInBrackets(IEnumerable list) + { + WriteToken ("[", AstNode.Roles.LBracket); + if (list.Any ()) { + Space(); + WriteCommaSeparatedList(list); + Space(); + } + WriteToken ("]", AstNode.Roles.RBracket); + } + #endregion + + #region Write tokens + /// + /// Writes a keyword, and all specials up to + /// + void WriteKeyword(string keyword, Role tokenRole = null) + { + WriteSpecialsUpToRole(tokenRole ?? AstNode.Roles.Keyword); + if (lastWritten == LastWritten.KeywordOrIdentifier) + formatter.Space(); + formatter.WriteKeyword(keyword); + lastWritten = LastWritten.KeywordOrIdentifier; + } + + void WriteIdentifier(string identifier, Role identifierRole = null) + { + WriteSpecialsUpToRole(identifierRole ?? AstNode.Roles.Identifier); + if (IsKeyword(identifier, containerStack.Peek())) { + if (lastWritten == LastWritten.KeywordOrIdentifier) + Space(); // this space is not strictly required, so we call Space() + formatter.WriteToken("["); + } else if (lastWritten == LastWritten.KeywordOrIdentifier) { + formatter.Space(); // this space is strictly required, so we directly call the formatter + } + formatter.WriteIdentifier(identifier); + if (IsKeyword(identifier, containerStack.Peek())) { + formatter.WriteToken("]"); + } + lastWritten = LastWritten.KeywordOrIdentifier; + } + + void WriteToken(string token, Role tokenRole) + { + WriteSpecialsUpToRole(tokenRole); + // Avoid that two +, - or ? tokens are combined into a ++, -- or ?? token. + // Note that we don't need to handle tokens like = because there's no valid + // C# program that contains the single token twice in a row. + // (for +, - and &, this can happen with unary operators; + // for ?, this can happen in "a is int? ? b : c" or "a as int? ?? 0"; + // and for /, this can happen with "1/ *ptr" or "1/ //comment".) +// if (lastWritten == LastWritten.Plus && token[0] == '+' +// || lastWritten == LastWritten.Minus && token[0] == '-' +// || lastWritten == LastWritten.Ampersand && token[0] == '&' +// || lastWritten == LastWritten.QuestionMark && token[0] == '?' +// || lastWritten == LastWritten.Division && token[0] == '*') +// { +// formatter.Space(); +// } + formatter.WriteToken(token); +// if (token == "+") +// lastWritten = LastWritten.Plus; +// else if (token == "-") +// lastWritten = LastWritten.Minus; +// else if (token == "&") +// lastWritten = LastWritten.Ampersand; +// else if (token == "?") +// lastWritten = LastWritten.QuestionMark; +// else if (token == "/") +// lastWritten = LastWritten.Division; +// else + lastWritten = LastWritten.Other; + } + + void WriteTypeCharacter(TypeCode typeCharacter) + { + switch (typeCharacter) { + case TypeCode.Empty: + case TypeCode.Object: + case TypeCode.DBNull: + case TypeCode.Boolean: + case TypeCode.Char: + + break; + case TypeCode.SByte: + + break; + case TypeCode.Byte: + + break; + case TypeCode.Int16: + + break; + case TypeCode.UInt16: + + break; + case TypeCode.Int32: + WriteToken("%", null); + break; + case TypeCode.UInt32: + + break; + case TypeCode.Int64: + WriteToken("&", null); + break; + case TypeCode.UInt64: + + break; + case TypeCode.Single: + WriteToken("!", null); + break; + case TypeCode.Double: + WriteToken("#", null); + break; + case TypeCode.Decimal: + WriteToken("@", null); + break; + case TypeCode.DateTime: + + break; + case TypeCode.String: + WriteToken("$", null); + break; + default: + throw new Exception("Invalid value for TypeCode"); + } + } + + void LPar() + { + WriteToken("(", AstNode.Roles.LPar); + } + + void RPar() + { + WriteToken(")", AstNode.Roles.LPar); + } + + /// + /// Writes a space depending on policy. + /// + void Space(bool addSpace = true) + { + if (addSpace) { + formatter.Space(); + lastWritten = LastWritten.Whitespace; + } + } + + void NewLine() + { + formatter.NewLine(); + lastWritten = LastWritten.Whitespace; + } + + void Indent() + { + formatter.Indent(); + } + + void Unindent() + { + formatter.Unindent(); + } + + void MarkFoldStart() + { + formatter.MarkFoldStart(); + } + + void MarkFoldEnd() + { + formatter.MarkFoldEnd(); + } + #endregion + + #region IsKeyword Test + static readonly HashSet unconditionalKeywords = new HashSet { + "AddHandler", "AddressOf", "Alias", "And", "AndAlso", "As", "Boolean", "ByRef", "Byte", + "ByVal", "Call", "Case", "Catch", "CBool", "CByte", "CChar", "CInt", "Class", "CLng", + "CObj", "Const", "Continue", "CSByte", "CShort", "CSng", "CStr", "CType", "CUInt", + "CULng", "CUShort", "Date", "Decimal", "Declare", "Default", "Delegate", "Dim", + "DirectCast", "Do", "Double", "Each", "Else", "ElseIf", "End", "EndIf", "Enum", "Erase", + "Error", "Event", "Exit", "False", "Finally", "For", "Friend", "Function", "Get", + "GetType", "GetXmlNamespace", "Global", "GoSub", "GoTo", "Handles", "If", "Implements", + "Imports", "In", "Inherits", "Integer", "Interface", "Is", "IsNot", "Let", "Lib", "Like", + "Long", "Loop", "Me", "Mod", "Module", "MustInherit", "MustOverride", "MyBase", "MyClass", + "Namespace", "Narrowing", "New", "Next", "Not", "Nothing", "NotInheritable", "NotOverridable", + "Object", "Of", "On", "Operator", "Option", "Optional", "Or", "OrElse", "Overloads", + "Overridable", "Overrides", "ParamArray", "Partial", "Private", "Property", "Protected", + "Public", "RaiseEvent", "ReadOnly", "ReDim", "REM", "RemoveHandler", "Resume", "Return", + "SByte", "Select", "Set", "Shadows", "Shared", "Short", "Single", "Static", "Step", "Stop", + "String", "Structure", "Sub", "SyncLock", "Then", "Throw", "To", "True", "Try", "TryCast", + "TypeOf", "UInteger", "ULong", "UShort", "Using", "Variant", "Wend", "When", "While", + "Widening", "With", "WithEvents", "WriteOnly", "Xor" + }; + + static readonly HashSet queryKeywords = new HashSet { + + }; + + /// + /// Determines whether the specified identifier is a keyword in the given context. + /// + public static bool IsKeyword(string identifier, AstNode context) + { + if (unconditionalKeywords.Contains(identifier)) + return true; +// if (context.Ancestors.Any(a => a is QueryExpression)) { +// if (queryKeywords.Contains(identifier)) +// return true; +// } + return false; + } + #endregion + + #region Write constructs + void WriteTypeArguments(IEnumerable typeArguments) + { + if (typeArguments.Any()) { + LPar(); + WriteKeyword("Of"); + WriteCommaSeparatedList(typeArguments); + RPar(); + } + } + + void WriteTypeParameters(IEnumerable typeParameters) + { + if (typeParameters.Any()) { + LPar(); + WriteKeyword("Of"); + WriteCommaSeparatedList(typeParameters); + RPar(); + } + } + + void WriteModifiers(IEnumerable modifierTokens) + { + foreach (VBModifierToken modifier in modifierTokens) { + modifier.AcceptVisitor(this, null); + } + } + + void WriteArraySpecifiers(IEnumerable arraySpecifiers) + { + foreach (ArraySpecifier specifier in arraySpecifiers) { + specifier.AcceptVisitor(this, null); + } + } + + void WriteQualifiedIdentifier(IEnumerable identifiers) + { + bool first = true; + foreach (Identifier ident in identifiers) { + if (first) { + first = false; + if (lastWritten == LastWritten.KeywordOrIdentifier) + formatter.Space(); + } else { + WriteSpecialsUpToRole(AstNode.Roles.Dot, ident); + formatter.WriteToken("."); + lastWritten = LastWritten.Other; + } + WriteSpecialsUpToNode(ident); + formatter.WriteIdentifier(ident.Name); + lastWritten = LastWritten.KeywordOrIdentifier; + } + } + + void WriteEmbeddedStatement(Statement embeddedStatement) + { + if (embeddedStatement.IsNull) + return; + BlockStatement block = embeddedStatement as BlockStatement; + if (block != null) + VisitBlockStatement(block, null); + else + embeddedStatement.AcceptVisitor(this, null); + } + + void WriteBlock(BlockStatement body) + { + if (body.IsNull) + NewLine(); + else + VisitBlockStatement(body, null); + } + + void WriteMembers(IEnumerable members) + { + Indent(); + bool isFirst = true; + foreach (var member in members) { + if (isFirst) { + isFirst = false; + } else { + NewLine(); + } + member.AcceptVisitor(this, null); + } + Unindent(); + } + + void WriteAttributes(IEnumerable attributes) + { + foreach (AttributeBlock attr in attributes) { + attr.AcceptVisitor(this, null); + } + } + + void WritePrivateImplementationType(AstType privateImplementationType) + { + if (!privateImplementationType.IsNull) { + privateImplementationType.AcceptVisitor(this, null); + WriteToken(".", AstNode.Roles.Dot); + } + } + + void WriteImplementsClause(AstNodeCollection implementsClause) + { + if (implementsClause.Any()) { + Space(); + WriteKeyword("Implements"); + WriteCommaSeparatedList(implementsClause); + } + } + + void WriteImplementsClause(AstNodeCollection implementsClause) + { + if (implementsClause.Any()) { + WriteKeyword("Implements"); + WriteCommaSeparatedList(implementsClause); + } + } + + void WriteHandlesClause(AstNodeCollection handlesClause) + { + if (handlesClause.Any()) { + Space(); + WriteKeyword("Handles"); + WriteCommaSeparatedList(handlesClause); + } + } + + void WritePrimitiveValue(object val) + { + if (val == null) { + WriteKeyword("Nothing"); + return; + } + + if (val is bool) { + if ((bool)val) { + WriteKeyword("True"); + } else { + WriteKeyword("False"); + } + return; + } + + if (val is string) { + formatter.WriteToken("\"" + ConvertString(val.ToString()) + "\""); + lastWritten = LastWritten.Other; + } else if (val is char) { + formatter.WriteToken("\"" + ConvertCharLiteral((char)val) + "\"c"); + lastWritten = LastWritten.Other; + } else if (val is decimal) { + formatter.WriteToken(((decimal)val).ToString(NumberFormatInfo.InvariantInfo) + "D"); + lastWritten = LastWritten.Other; + } else if (val is float) { + float f = (float)val; + if (float.IsInfinity(f) || float.IsNaN(f)) { + // Strictly speaking, these aren't PrimitiveExpressions; + // but we still support writing these to make life easier for code generators. + WriteKeyword("Single"); + WriteToken(".", AstNode.Roles.Dot); + if (float.IsPositiveInfinity(f)) + WriteIdentifier("PositiveInfinity"); + else if (float.IsNegativeInfinity(f)) + WriteIdentifier("NegativeInfinity"); + else + WriteIdentifier("NaN"); + return; + } + formatter.WriteToken(f.ToString("R", NumberFormatInfo.InvariantInfo) + "F"); + lastWritten = LastWritten.Other; + } else if (val is double) { + double f = (double)val; + if (double.IsInfinity(f) || double.IsNaN(f)) { + // Strictly speaking, these aren't PrimitiveExpressions; + // but we still support writing these to make life easier for code generators. + WriteKeyword("Double"); + WriteToken(".", AstNode.Roles.Dot); + if (double.IsPositiveInfinity(f)) + WriteIdentifier("PositiveInfinity"); + else if (double.IsNegativeInfinity(f)) + WriteIdentifier("NegativeInfinity"); + else + WriteIdentifier("NaN"); + return; + } + string number = f.ToString("R", NumberFormatInfo.InvariantInfo); + if (number.IndexOf('.') < 0 && number.IndexOf('E') < 0) + number += ".0"; + formatter.WriteToken(number); + // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix + lastWritten = LastWritten.KeywordOrIdentifier; + } else if (val is IFormattable) { + StringBuilder b = new StringBuilder(); +// if (primitiveExpression.LiteralFormat == LiteralFormat.HexadecimalNumber) { +// b.Append("0x"); +// b.Append(((IFormattable)val).ToString("x", NumberFormatInfo.InvariantInfo)); +// } else { + b.Append(((IFormattable)val).ToString(null, NumberFormatInfo.InvariantInfo)); +// } + if (val is uint || val is ulong) { + b.Append("U"); + } + if (val is long || val is ulong) { + b.Append("L"); + } + formatter.WriteToken(b.ToString()); + // needs space if identifier follows number; this avoids mistaking the following identifier as type suffix + lastWritten = LastWritten.KeywordOrIdentifier; + } else { + formatter.WriteToken(val.ToString()); + lastWritten = LastWritten.Other; + } + } + #endregion + + #region ConvertLiteral + static string ConvertCharLiteral(char ch) + { + if (ch == '"') return "\"\""; + return ch.ToString(); + } + + static string ConvertString(string str) + { + StringBuilder sb = new StringBuilder(); + foreach (char ch in str) { + sb.Append(ConvertCharLiteral(ch)); + } + return sb.ToString(); + } + #endregion + + public object VisitVariableIdentifier(VariableIdentifier variableIdentifier, object data) + { + StartNode(variableIdentifier); + + WriteIdentifier(variableIdentifier.Name.Name); + if (variableIdentifier.HasNullableSpecifier) + WriteToken("?", VariableIdentifier.Roles.QuestionMark); + WriteArraySpecifiers(variableIdentifier.ArraySpecifiers); + + return EndNode(variableIdentifier); + } + + public object VisitAccessor(Accessor accessor, object data) + { + StartNode(accessor); + WriteAttributes(accessor.Attributes); + WriteModifiers(accessor.ModifierTokens); + if (accessor.Role == PropertyDeclaration.GetterRole) { + WriteKeyword("Get"); + } else if (accessor.Role == PropertyDeclaration.SetterRole) { + WriteKeyword("Set"); + } else if (accessor.Role == EventDeclaration.AddHandlerRole) { + WriteKeyword("AddHandler"); + } else if (accessor.Role == EventDeclaration.RemoveHandlerRole) { + WriteKeyword("RemoveHandler"); + } else if (accessor.Role == EventDeclaration.RaiseEventRole) { + WriteKeyword("RaiseEvent"); + } + if (accessor.Parameters.Any()) + WriteCommaSeparatedListInParenthesis(accessor.Parameters, false); + NewLine(); + Indent(); + WriteBlock(accessor.Body); + Unindent(); + WriteKeyword("End"); + + if (accessor.Role == PropertyDeclaration.GetterRole) { + WriteKeyword("Get"); + } else if (accessor.Role == PropertyDeclaration.SetterRole) { + WriteKeyword("Set"); + } else if (accessor.Role == EventDeclaration.AddHandlerRole) { + WriteKeyword("AddHandler"); + } else if (accessor.Role == EventDeclaration.RemoveHandlerRole) { + WriteKeyword("RemoveHandler"); + } else if (accessor.Role == EventDeclaration.RaiseEventRole) { + WriteKeyword("RaiseEvent"); + } + NewLine(); + + return EndNode(accessor); + } + + + public object VisitLabelDeclarationStatement(LabelDeclarationStatement labelDeclarationStatement, object data) + { + StartNode(labelDeclarationStatement); + + labelDeclarationStatement.Label.AcceptVisitor(this, data); + WriteToken(":", LabelDeclarationStatement.Roles.Colon); + + return EndNode(labelDeclarationStatement); + } + + public object VisitLocalDeclarationStatement(LocalDeclarationStatement localDeclarationStatement, object data) + { + StartNode(localDeclarationStatement); + + if (localDeclarationStatement.ModifierToken != null && !localDeclarationStatement.ModifierToken.IsNull) + WriteModifiers(new [] { localDeclarationStatement.ModifierToken }); + WriteCommaSeparatedList(localDeclarationStatement.Variables); + + return EndNode(localDeclarationStatement); + } + + public object VisitWithStatement(WithStatement withStatement, object data) + { + StartNode(withStatement); + WriteKeyword("With"); + withStatement.Expression.AcceptVisitor(this, data); + NewLine(); + Indent(); + withStatement.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("End"); + WriteKeyword("With"); + return EndNode(withStatement); + } + + public object VisitSyncLockStatement(SyncLockStatement syncLockStatement, object data) + { + StartNode(syncLockStatement); + WriteKeyword("SyncLock"); + syncLockStatement.Expression.AcceptVisitor(this, data); + NewLine(); + Indent(); + syncLockStatement.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("End"); + WriteKeyword("SyncLock"); + return EndNode(syncLockStatement); + } + + public object VisitTryStatement(TryStatement tryStatement, object data) + { + StartNode(tryStatement); + WriteKeyword("Try"); + NewLine(); + Indent(); + tryStatement.Body.AcceptVisitor(this, data); + Unindent(); + foreach (var clause in tryStatement.CatchBlocks) { + clause.AcceptVisitor(this, data); + } + if (!tryStatement.FinallyBlock.IsNull) { + WriteKeyword("Finally"); + NewLine(); + Indent(); + tryStatement.FinallyBlock.AcceptVisitor(this, data); + Unindent(); + } + WriteKeyword("End"); + WriteKeyword("Try"); + return EndNode(tryStatement); + } + + public object VisitCatchBlock(CatchBlock catchBlock, object data) + { + StartNode(catchBlock); + WriteKeyword("Catch"); + catchBlock.ExceptionVariable.AcceptVisitor(this, data); + if (!catchBlock.ExceptionType.IsNull) { + WriteKeyword("As"); + catchBlock.ExceptionType.AcceptVisitor(this, data); + } + NewLine(); + Indent(); + foreach (var stmt in catchBlock) { + stmt.AcceptVisitor(this, data); + NewLine(); + } + Unindent(); + return EndNode(catchBlock); + } + + public object VisitExpressionStatement(ExpressionStatement expressionStatement, object data) + { + StartNode(expressionStatement); + expressionStatement.Expression.AcceptVisitor(this, data); + return EndNode(expressionStatement); + } + + public object VisitThrowStatement(ThrowStatement throwStatement, object data) + { + StartNode(throwStatement); + + WriteKeyword("Throw"); + throwStatement.Expression.AcceptVisitor(this, data); + + return EndNode(throwStatement); + } + + public object VisitIfElseStatement(IfElseStatement ifElseStatement, object data) + { + StartNode(ifElseStatement); + WriteKeyword("If"); + ifElseStatement.Condition.AcceptVisitor(this, data); + Space(); + WriteKeyword("Then"); + NewLine(); + Indent(); + ifElseStatement.Body.AcceptVisitor(this, data); + Unindent(); + if (!ifElseStatement.ElseBlock.IsNull) { + WriteKeyword("Else"); + NewLine(); + Indent(); + ifElseStatement.ElseBlock.AcceptVisitor(this, data); + Unindent(); + } + WriteKeyword("End"); + WriteKeyword("If"); + return EndNode(ifElseStatement); + } + + public object VisitReturnStatement(ReturnStatement returnStatement, object data) + { + StartNode(returnStatement); + WriteKeyword("Return"); + returnStatement.Expression.AcceptVisitor(this, data); + return EndNode(returnStatement); + } + + public object VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) + { + StartNode(binaryOperatorExpression); + binaryOperatorExpression.Left.AcceptVisitor(this, data); + Space(); + switch (binaryOperatorExpression.Operator) { + case BinaryOperatorType.BitwiseAnd: + WriteKeyword("And"); + break; + case BinaryOperatorType.BitwiseOr: + WriteKeyword("Or"); + break; + case BinaryOperatorType.LogicalAnd: + WriteKeyword("AndAlso"); + break; + case BinaryOperatorType.LogicalOr: + WriteKeyword("OrElse"); + break; + case BinaryOperatorType.ExclusiveOr: + WriteKeyword("Xor"); + break; + case BinaryOperatorType.GreaterThan: + WriteToken(">", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.GreaterThanOrEqual: + WriteToken(">=", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Equality: + WriteToken("=", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.InEquality: + WriteToken("<>", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.LessThan: + WriteToken("<", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.LessThanOrEqual: + WriteToken("<=", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Add: + WriteToken("+", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Subtract: + WriteToken("-", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Multiply: + WriteToken("*", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Divide: + WriteToken("/", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Modulus: + WriteKeyword("Mod"); + break; + case BinaryOperatorType.DivideInteger: + WriteToken("\\", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Power: + WriteToken("*", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.Concat: + WriteToken("&", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.ShiftLeft: + WriteToken("<<", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.ShiftRight: + WriteToken(">>", BinaryOperatorExpression.OperatorRole); + break; + case BinaryOperatorType.ReferenceEquality: + WriteKeyword("Is"); + break; + case BinaryOperatorType.ReferenceInequality: + WriteKeyword("IsNot"); + break; + case BinaryOperatorType.Like: + WriteKeyword("Like"); + break; + case BinaryOperatorType.DictionaryAccess: + WriteToken("!", BinaryOperatorExpression.OperatorRole); + break; + default: + throw new Exception("Invalid value for BinaryOperatorType: " + binaryOperatorExpression.Operator); + } + Space(); + binaryOperatorExpression.Right.AcceptVisitor(this, data); + return EndNode(binaryOperatorExpression); + } + + public object VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) + { + StartNode(identifierExpression); + identifierExpression.Identifier.AcceptVisitor(this, data); + WriteTypeArguments(identifierExpression.TypeArguments); + return EndNode(identifierExpression); + } + + public object VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) + { + StartNode(assignmentExpression); + assignmentExpression.Left.AcceptVisitor(this, data); + Space(); + switch (assignmentExpression.Operator) { + case AssignmentOperatorType.Assign: + WriteToken("=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.Add: + WriteToken("+=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.Subtract: + WriteToken("-=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.Multiply: + WriteToken("*=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.Divide: + WriteToken("/=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.Power: + WriteToken("^=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.DivideInteger: + WriteToken("\\=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.ConcatString: + WriteToken("&=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.ShiftLeft: + WriteToken("<<=", AssignmentExpression.OperatorRole); + break; + case AssignmentOperatorType.ShiftRight: + WriteToken(">>=", AssignmentExpression.OperatorRole); + break; + default: + throw new Exception("Invalid value for AssignmentOperatorType: " + assignmentExpression.Operator); + } + Space(); + assignmentExpression.Right.AcceptVisitor(this, data); + return EndNode(assignmentExpression); + } + + public object VisitInvocationExpression(InvocationExpression invocationExpression, object data) + { + StartNode(invocationExpression); + invocationExpression.Target.AcceptVisitor(this, data); + WriteCommaSeparatedListInParenthesis(invocationExpression.Arguments, false); + return EndNode(invocationExpression); + } + + public object VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data) + { + StartNode(arrayInitializerExpression); + WriteToken("{", ArrayInitializerExpression.Roles.LBrace); + Space(); + WriteCommaSeparatedList(arrayInitializerExpression.Elements); + Space(); + WriteToken("}", ArrayInitializerExpression.Roles.RBrace); + return EndNode(arrayInitializerExpression); + } + + public object VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) + { + StartNode(arrayCreateExpression); + WriteKeyword("New"); + Space(); + arrayCreateExpression.Type.AcceptVisitor(this, data); + WriteCommaSeparatedListInParenthesis(arrayCreateExpression.Arguments, false); + foreach (var specifier in arrayCreateExpression.AdditionalArraySpecifiers) { + specifier.AcceptVisitor(this, data); + } + if (!arrayCreateExpression.Initializer.IsNull) { + Space(); + WriteToken("=", ArrayCreateExpression.Roles.Assign); + Space(); + arrayCreateExpression.Initializer.AcceptVisitor(this, data); + } + return EndNode(arrayCreateExpression); + } + + public object VisitObjectCreationExpression(ObjectCreationExpression objectCreationExpression, object data) + { + StartNode(objectCreationExpression); + + WriteKeyword("New"); + objectCreationExpression.Type.AcceptVisitor(this, data); + WriteCommaSeparatedListInParenthesis(objectCreationExpression.Arguments, false); + if (!objectCreationExpression.Initializer.IsNull) { + Space(); + objectCreationExpression.Initializer.AcceptVisitor(this, data); + } + + return EndNode(objectCreationExpression); + } + + public object VisitCastExpression(CastExpression castExpression, object data) + { + StartNode(castExpression); + + switch (castExpression.CastType) { + case CastType.DirectCast: + WriteKeyword("DirectCast"); + break; + case CastType.TryCast: + WriteKeyword("TryCast"); + break; + case CastType.CType: + WriteKeyword("CType"); + break; + case CastType.CBool: + WriteKeyword("CBool"); + break; + case CastType.CByte: + WriteKeyword("CByte"); + break; + case CastType.CChar: + WriteKeyword("CChar"); + break; + case CastType.CDate: + WriteKeyword("CDate"); + break; + case CastType.CDec: + WriteKeyword("CType"); + break; + case CastType.CDbl: + WriteKeyword("CDec"); + break; + case CastType.CInt: + WriteKeyword("CInt"); + break; + case CastType.CLng: + WriteKeyword("CLng"); + break; + case CastType.CObj: + WriteKeyword("CObj"); + break; + case CastType.CSByte: + WriteKeyword("CSByte"); + break; + case CastType.CShort: + WriteKeyword("CShort"); + break; + case CastType.CSng: + WriteKeyword("CSng"); + break; + case CastType.CStr: + WriteKeyword("CStr"); + break; + case CastType.CUInt: + WriteKeyword("CUInt"); + break; + case CastType.CULng: + WriteKeyword("CULng"); + break; + case CastType.CUShort: + WriteKeyword("CUShort"); + break; + default: + throw new Exception("Invalid value for CastType"); + } + + WriteToken("(", CastExpression.Roles.LPar); + castExpression.Expression.AcceptVisitor(this, data); + + if (castExpression.CastType == CastType.CType || + castExpression.CastType == CastType.DirectCast || + castExpression.CastType == CastType.TryCast) { + WriteToken(",", CastExpression.Roles.Comma); + Space(); + castExpression.Type.AcceptVisitor(this, data); + } + + WriteToken(")", CastExpression.Roles.RPar); + + return EndNode(castExpression); + } + + public object VisitComment(Comment comment, object data) + { + formatter.WriteComment(comment.IsDocumentationComment, comment.Content); + return null; + } + + public object VisitEventDeclaration(EventDeclaration eventDeclaration, object data) + { + StartNode(eventDeclaration); + + WriteAttributes(eventDeclaration.Attributes); + WriteModifiers(eventDeclaration.ModifierTokens); + if (eventDeclaration.IsCustom) + WriteKeyword("Custom"); + WriteKeyword("Event"); + WriteIdentifier(eventDeclaration.Name.Name); + if (!eventDeclaration.IsCustom && eventDeclaration.ReturnType.IsNull) + WriteCommaSeparatedListInParenthesis(eventDeclaration.Parameters, false); + if (!eventDeclaration.ReturnType.IsNull) { + Space(); + WriteKeyword("As"); + eventDeclaration.ReturnType.AcceptVisitor(this, data); + } + WriteImplementsClause(eventDeclaration.ImplementsClause); + + if (eventDeclaration.IsCustom) { + MarkFoldStart(); + NewLine(); + Indent(); + + eventDeclaration.AddHandlerBlock.AcceptVisitor(this, data); + eventDeclaration.RemoveHandlerBlock.AcceptVisitor(this, data); + eventDeclaration.RaiseEventBlock.AcceptVisitor(this, data); + + Unindent(); + WriteKeyword("End"); + WriteKeyword("Event"); + MarkFoldEnd(); + } + NewLine(); + + return EndNode(eventDeclaration); + } + + public object VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) + { + StartNode(unaryOperatorExpression); + + switch (unaryOperatorExpression.Operator) { + case UnaryOperatorType.Not: + WriteKeyword("Not"); + break; + case UnaryOperatorType.Minus: + WriteToken("-", UnaryOperatorExpression.OperatorRole); + break; + case UnaryOperatorType.Plus: + WriteToken("+", UnaryOperatorExpression.OperatorRole); + break; + case UnaryOperatorType.AddressOf: + WriteKeyword("AddressOf"); + break; + case UnaryOperatorType.Await: + WriteKeyword("Await"); + break; + default: + throw new Exception("Invalid value for UnaryOperatorType"); + } + + unaryOperatorExpression.Expression.AcceptVisitor(this, data); + + return EndNode(unaryOperatorExpression); + } + + public object VisitFieldInitializerExpression(FieldInitializerExpression fieldInitializerExpression, object data) + { + StartNode(fieldInitializerExpression); + + if (fieldInitializerExpression.IsKey) { + WriteKeyword("Key"); + Space(); + } + + WriteToken(".", FieldInitializerExpression.Roles.Dot); + fieldInitializerExpression.Identifier.AcceptVisitor(this, data); + + Space(); + WriteToken("=", FieldInitializerExpression.Roles.Assign); + Space(); + fieldInitializerExpression.Expression.AcceptVisitor(this, data); + + return EndNode(fieldInitializerExpression); + } + + public object VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) { throw new NotImplementedException(); } + + public object VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) + { + StartNode(conditionalExpression); + + WriteKeyword("If"); + WriteToken("(", ConditionalExpression.Roles.LPar); + + conditionalExpression.ConditionExpression.AcceptVisitor(this, data); + WriteToken(",", ConditionalExpression.Roles.Comma); + Space(); + + if (!conditionalExpression.TrueExpression.IsNull) { + conditionalExpression.TrueExpression.AcceptVisitor(this, data); + WriteToken(",", ConditionalExpression.Roles.Comma); + Space(); + } + + conditionalExpression.FalseExpression.AcceptVisitor(this, data); + + WriteToken(")", ConditionalExpression.Roles.RPar); + + return EndNode(conditionalExpression); + } + + public object VisitWhileStatement(WhileStatement whileStatement, object data) + { + StartNode(whileStatement); + + WriteKeyword("While"); + Space(); + whileStatement.Condition.AcceptVisitor(this, data); + NewLine(); + Indent(); + whileStatement.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("End"); + WriteKeyword("While"); + + return EndNode(whileStatement); + } + + public object VisitExitStatement(ExitStatement exitStatement, object data) + { + StartNode(exitStatement); + + WriteKeyword("Exit"); + + switch (exitStatement.ExitKind) { + case ExitKind.Sub: + WriteKeyword("Sub"); + break; + case ExitKind.Function: + WriteKeyword("Function"); + break; + case ExitKind.Property: + WriteKeyword("Property"); + break; + case ExitKind.Do: + WriteKeyword("Do"); + break; + case ExitKind.For: + WriteKeyword("For"); + break; + case ExitKind.While: + WriteKeyword("While"); + break; + case ExitKind.Select: + WriteKeyword("Select"); + break; + case ExitKind.Try: + WriteKeyword("Try"); + break; + default: + throw new Exception("Invalid value for ExitKind"); + } + + return EndNode(exitStatement); + } + + public object VisitForStatement(ForStatement forStatement, object data) + { + StartNode(forStatement); + + WriteKeyword("For"); + forStatement.Variable.AcceptVisitor(this, data); + WriteKeyword("To"); + forStatement.ToExpression.AcceptVisitor(this, data); + if (!forStatement.StepExpression.IsNull) { + WriteKeyword("Step"); + Space(); + forStatement.StepExpression.AcceptVisitor(this, data); + } + NewLine(); + Indent(); + forStatement.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("Next"); + + return EndNode(forStatement); + } + + public object VisitForEachStatement(ForEachStatement forEachStatement, object data) + { + StartNode(forEachStatement); + + WriteKeyword("For"); + WriteKeyword("Each"); + forEachStatement.Variable.AcceptVisitor(this, data); + WriteKeyword("In"); + forEachStatement.InExpression.AcceptVisitor(this, data); + NewLine(); + Indent(); + forEachStatement.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("Next"); + + return EndNode(forEachStatement); + } + + public object VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) + { + StartNode(operatorDeclaration); + + WriteAttributes(operatorDeclaration.Attributes); + WriteModifiers(operatorDeclaration.ModifierTokens); + WriteKeyword("Operator"); + switch (operatorDeclaration.Operator) { + case OverloadableOperatorType.Add: + case OverloadableOperatorType.UnaryPlus: + WriteToken("+", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.Subtract: + case OverloadableOperatorType.UnaryMinus: + WriteToken("-", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.Multiply: + WriteToken("*", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.Divide: + WriteToken("/", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.Modulus: + WriteKeyword("Mod"); + break; + case OverloadableOperatorType.Concat: + WriteToken("&", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.Not: + WriteKeyword("Not"); + break; + case OverloadableOperatorType.BitwiseAnd: + WriteKeyword("And"); + break; + case OverloadableOperatorType.BitwiseOr: + WriteKeyword("Or"); + break; + case OverloadableOperatorType.ExclusiveOr: + WriteKeyword("Xor"); + break; + case OverloadableOperatorType.ShiftLeft: + WriteToken("<<", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.ShiftRight: + WriteToken(">>", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.GreaterThan: + WriteToken(">", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.GreaterThanOrEqual: + WriteToken(">=", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.Equality: + WriteToken("=", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.InEquality: + WriteToken("<>", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.LessThan: + WriteToken("<", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.LessThanOrEqual: + WriteToken("<=", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.IsTrue: + WriteKeyword("IsTrue"); + break; + case OverloadableOperatorType.IsFalse: + WriteKeyword("IsFalse"); + break; + case OverloadableOperatorType.Like: + WriteKeyword("Like"); + break; + case OverloadableOperatorType.Power: + WriteToken("^", OperatorDeclaration.Roles.Keyword); + break; + case OverloadableOperatorType.CType: + WriteKeyword("CType"); + break; + case OverloadableOperatorType.DivideInteger: + WriteToken("\\", OperatorDeclaration.Roles.Keyword); + break; + default: + throw new Exception("Invalid value for OverloadableOperatorType"); + } + WriteCommaSeparatedListInParenthesis(operatorDeclaration.Parameters, false); + if (!operatorDeclaration.ReturnType.IsNull) { + Space(); + WriteKeyword("As"); + WriteAttributes(operatorDeclaration.ReturnTypeAttributes); + operatorDeclaration.ReturnType.AcceptVisitor(this, data); + } + if (!operatorDeclaration.Body.IsNull) { + MarkFoldStart(); + NewLine(); + Indent(); + WriteBlock(operatorDeclaration.Body); + Unindent(); + WriteKeyword("End"); + WriteKeyword("Operator"); + MarkFoldEnd(); + } + NewLine(); + + return EndNode(operatorDeclaration); + } + + public object VisitSelectStatement(SelectStatement selectStatement, object data) + { + StartNode(selectStatement); + + WriteKeyword("Select"); + WriteKeyword("Case"); + selectStatement.Expression.AcceptVisitor(this, data); + NewLine(); + Indent(); + + foreach (CaseStatement stmt in selectStatement.Cases) { + stmt.AcceptVisitor(this, data); + } + + Unindent(); + WriteKeyword("End"); + WriteKeyword("Select"); + + return EndNode(selectStatement); + } + + public object VisitCaseStatement(CaseStatement caseStatement, object data) + { + StartNode(caseStatement); + + WriteKeyword("Case"); + if (caseStatement.Clauses.Count == 1 && caseStatement.Clauses.First().Expression.IsNull) + WriteKeyword("Else"); + else + WriteCommaSeparatedList(caseStatement.Clauses); + NewLine(); + Indent(); + caseStatement.Body.AcceptVisitor(this, data); + Unindent(); + + return EndNode(caseStatement); + } + + public object VisitSimpleCaseClause(SimpleCaseClause simpleCaseClause, object data) + { + StartNode(simpleCaseClause); + simpleCaseClause.Expression.AcceptVisitor(this, data); + return EndNode(simpleCaseClause); + } + + public object VisitRangeCaseClause(RangeCaseClause rangeCaseClause, object data) + { + StartNode(rangeCaseClause); + rangeCaseClause.Expression.AcceptVisitor(this, data); + WriteKeyword("To"); + rangeCaseClause.ToExpression.AcceptVisitor(this, data); + return EndNode(rangeCaseClause); + } + + public object VisitComparisonCaseClause(ComparisonCaseClause comparisonCaseClause, object data) + { + StartNode(comparisonCaseClause); + switch (comparisonCaseClause.Operator) { + case ComparisonOperator.Equality: + WriteToken("=", ComparisonCaseClause.OperatorRole); + break; + case ComparisonOperator.InEquality: + WriteToken("<>", ComparisonCaseClause.OperatorRole); + break; + case ComparisonOperator.LessThan: + WriteToken("<", ComparisonCaseClause.OperatorRole); + break; + case ComparisonOperator.GreaterThan: + WriteToken(">", ComparisonCaseClause.OperatorRole); + break; + case ComparisonOperator.LessThanOrEqual: + WriteToken("<=", ComparisonCaseClause.OperatorRole); + break; + case ComparisonOperator.GreaterThanOrEqual: + WriteToken(">=", ComparisonCaseClause.OperatorRole); + break; + default: + throw new Exception("Invalid value for ComparisonOperator"); + } + Space(); + comparisonCaseClause.Expression.AcceptVisitor(this, data); + return EndNode(comparisonCaseClause); + } + + + public object VisitYieldStatement(YieldStatement yieldStatement, object data) + { + StartNode(yieldStatement); + WriteKeyword("Yield"); + yieldStatement.Expression.AcceptVisitor(this, data); + return EndNode(yieldStatement); + } + + public object VisitVariableInitializer(VariableInitializer variableInitializer, object data) + { + StartNode(variableInitializer); + + variableInitializer.Identifier.AcceptVisitor(this, data); + if (!variableInitializer.Type.IsNull) { + WriteKeyword("As"); + variableInitializer.Type.AcceptVisitor(this, data); + } + if (!variableInitializer.Expression.IsNull) { + Space(); + WriteToken("=", VariableInitializer.Roles.Assign); + Space(); + variableInitializer.Expression.AcceptVisitor(this, data); + } + + return EndNode(variableInitializer); + } + + public object VisitVariableDeclaratorWithTypeAndInitializer(VariableDeclaratorWithTypeAndInitializer variableDeclaratorWithTypeAndInitializer, object data) + { + StartNode(variableDeclaratorWithTypeAndInitializer); + + WriteCommaSeparatedList(variableDeclaratorWithTypeAndInitializer.Identifiers); + WriteKeyword("As"); + variableDeclaratorWithTypeAndInitializer.Type.AcceptVisitor(this, data); + if (!variableDeclaratorWithTypeAndInitializer.Initializer.IsNull) { + Space(); + WriteToken("=", VariableDeclarator.Roles.Assign); + Space(); + variableDeclaratorWithTypeAndInitializer.Initializer.AcceptVisitor(this, data); + } + + return EndNode(variableDeclaratorWithTypeAndInitializer); + } + + public object VisitVariableDeclaratorWithObjectCreation(VariableDeclaratorWithObjectCreation variableDeclaratorWithObjectCreation, object data) + { + StartNode(variableDeclaratorWithObjectCreation); + + WriteCommaSeparatedList(variableDeclaratorWithObjectCreation.Identifiers); + WriteKeyword("As"); + variableDeclaratorWithObjectCreation.Initializer.AcceptVisitor(this, data); + + return EndNode(variableDeclaratorWithObjectCreation); + } + + public object VisitDoLoopStatement(DoLoopStatement doLoopStatement, object data) + { + StartNode(doLoopStatement); + + WriteKeyword("Do"); + if (doLoopStatement.ConditionType == ConditionType.DoUntil) { + WriteKeyword("Until"); + doLoopStatement.Expression.AcceptVisitor(this, data); + } + if (doLoopStatement.ConditionType == ConditionType.DoWhile) { + WriteKeyword("While"); + doLoopStatement.Expression.AcceptVisitor(this, data); + } + NewLine(); + Indent(); + doLoopStatement.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("Loop"); + if (doLoopStatement.ConditionType == ConditionType.LoopUntil) { + WriteKeyword("Until"); + doLoopStatement.Expression.AcceptVisitor(this, data); + } + if (doLoopStatement.ConditionType == ConditionType.LoopWhile) { + WriteKeyword("While"); + doLoopStatement.Expression.AcceptVisitor(this, data); + } + + return EndNode(doLoopStatement); + } + + public object VisitUsingStatement(UsingStatement usingStatement, object data) + { + StartNode(usingStatement); + + WriteKeyword("Using"); + WriteCommaSeparatedList(usingStatement.Resources); + NewLine(); + Indent(); + usingStatement.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("End"); + WriteKeyword("Using"); + + return EndNode(usingStatement); + } + + public object VisitGoToStatement(GoToStatement goToStatement, object data) + { + StartNode(goToStatement); + + WriteKeyword("GoTo"); + goToStatement.Label.AcceptVisitor(this, data); + + return EndNode(goToStatement); + } + + public object VisitSingleLineSubLambdaExpression(SingleLineSubLambdaExpression singleLineSubLambdaExpression, object data) + { + StartNode(singleLineSubLambdaExpression); + + WriteModifiers(singleLineSubLambdaExpression.ModifierTokens); + WriteKeyword("Sub"); + WriteCommaSeparatedListInParenthesis(singleLineSubLambdaExpression.Parameters, false); + Space(); + singleLineSubLambdaExpression.EmbeddedStatement.AcceptVisitor(this, data); + + return EndNode(singleLineSubLambdaExpression); + } + + public object VisitSingleLineFunctionLambdaExpression(SingleLineFunctionLambdaExpression singleLineFunctionLambdaExpression, object data) + { + StartNode(singleLineFunctionLambdaExpression); + + WriteModifiers(singleLineFunctionLambdaExpression.ModifierTokens); + WriteKeyword("Function"); + WriteCommaSeparatedListInParenthesis(singleLineFunctionLambdaExpression.Parameters, false); + Space(); + singleLineFunctionLambdaExpression.EmbeddedExpression.AcceptVisitor(this, data); + + return EndNode(singleLineFunctionLambdaExpression); + } + + public object VisitMultiLineLambdaExpression(MultiLineLambdaExpression multiLineLambdaExpression, object data) + { + StartNode(multiLineLambdaExpression); + + WriteModifiers(multiLineLambdaExpression.ModifierTokens); + if (multiLineLambdaExpression.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + WriteCommaSeparatedListInParenthesis(multiLineLambdaExpression.Parameters, false); + NewLine(); + Indent(); + multiLineLambdaExpression.Body.AcceptVisitor(this, data); + Unindent(); + WriteKeyword("End"); + if (multiLineLambdaExpression.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + + return EndNode(multiLineLambdaExpression); + } + + public object VisitQueryExpression(QueryExpression queryExpression, object data) + { + StartNode(queryExpression); + + foreach (var op in queryExpression.QueryOperators) { + op.AcceptVisitor(this, data); + } + + return EndNode(queryExpression); + } + + public object VisitContinueStatement(ContinueStatement continueStatement, object data) + { + StartNode(continueStatement); + + WriteKeyword("Continue"); + + switch (continueStatement.ContinueKind) { + case ContinueKind.Do: + WriteKeyword("Do"); + break; + case ContinueKind.For: + WriteKeyword("For"); + break; + case ContinueKind.While: + WriteKeyword("While"); + break; + default: + throw new Exception("Invalid value for ContinueKind"); + } + + return EndNode(continueStatement); + } + + public object VisitExternalMethodDeclaration(ExternalMethodDeclaration externalMethodDeclaration, object data) + { + StartNode(externalMethodDeclaration); + + WriteAttributes(externalMethodDeclaration.Attributes); + WriteModifiers(externalMethodDeclaration.ModifierTokens); + WriteKeyword("Declare"); + switch (externalMethodDeclaration.CharsetModifier) { + case CharsetModifier.None: + break; + case CharsetModifier.Auto: + WriteKeyword("Auto"); + break; + case CharsetModifier.Unicode: + WriteKeyword("Unicode"); + break; + case CharsetModifier.Ansi: + WriteKeyword("Ansi"); + break; + default: + throw new Exception("Invalid value for CharsetModifier"); + } + if (externalMethodDeclaration.IsSub) + WriteKeyword("Sub"); + else + WriteKeyword("Function"); + externalMethodDeclaration.Name.AcceptVisitor(this, data); + WriteKeyword("Lib"); + Space(); + WritePrimitiveValue(externalMethodDeclaration.Library); + Space(); + if (externalMethodDeclaration.Alias != null) { + WriteKeyword("Alias"); + Space(); + WritePrimitiveValue(externalMethodDeclaration.Alias); + Space(); + } + WriteCommaSeparatedListInParenthesis(externalMethodDeclaration.Parameters, false); + if (!externalMethodDeclaration.IsSub && !externalMethodDeclaration.ReturnType.IsNull) { + Space(); + WriteKeyword("As"); + WriteAttributes(externalMethodDeclaration.ReturnTypeAttributes); + externalMethodDeclaration.ReturnType.AcceptVisitor(this, data); + } + NewLine(); + + return EndNode(externalMethodDeclaration); + } + + public static string ToVBNetString(PrimitiveExpression primitiveExpression) + { + var writer = new StringWriter(); + new OutputVisitor(writer, new VBFormattingOptions()).WritePrimitiveValue(primitiveExpression.Value); + return writer.ToString(); + } + + public object VisitEmptyExpression(EmptyExpression emptyExpression, object data) + { + StartNode(emptyExpression); + + return EndNode(emptyExpression); + } + + public object VisitAnonymousObjectCreationExpression(AnonymousObjectCreationExpression anonymousObjectCreationExpression, object data) + { + StartNode(anonymousObjectCreationExpression); + + WriteKeyword("New"); + WriteKeyword("With"); + + WriteToken("{", AnonymousObjectCreationExpression.Roles.LBrace); + Space(); + WriteCommaSeparatedList(anonymousObjectCreationExpression.Initializer); + Space(); + WriteToken("}", AnonymousObjectCreationExpression.Roles.RBrace); + + return EndNode(anonymousObjectCreationExpression); + } + + public object VisitCollectionRangeVariableDeclaration(CollectionRangeVariableDeclaration collectionRangeVariableDeclaration, object data) + { + StartNode(collectionRangeVariableDeclaration); + + collectionRangeVariableDeclaration.Identifier.AcceptVisitor(this, data); + if (!collectionRangeVariableDeclaration.Type.IsNull) { + WriteKeyword("As"); + collectionRangeVariableDeclaration.Type.AcceptVisitor(this, data); + } + WriteKeyword("In"); + collectionRangeVariableDeclaration.Expression.AcceptVisitor(this, data); + + return EndNode(collectionRangeVariableDeclaration); + } + + public object VisitFromQueryOperator(FromQueryOperator fromQueryOperator, object data) + { + StartNode(fromQueryOperator); + + WriteKeyword("From"); + WriteCommaSeparatedList(fromQueryOperator.Variables); + + return EndNode(fromQueryOperator); + } + + public object VisitAggregateQueryOperator(AggregateQueryOperator aggregateQueryOperator, object data) + { + StartNode(aggregateQueryOperator); + + WriteKeyword("Aggregate"); + aggregateQueryOperator.Variable.AcceptVisitor(this, data); + + foreach (var operators in aggregateQueryOperator.SubQueryOperators) { + operators.AcceptVisitor(this, data); + } + + WriteKeyword("Into"); + WriteCommaSeparatedList(aggregateQueryOperator.IntoExpressions); + + return EndNode(aggregateQueryOperator); + } + + public object VisitSelectQueryOperator(SelectQueryOperator selectQueryOperator, object data) + { + StartNode(selectQueryOperator); + + WriteKeyword("Select"); + WriteCommaSeparatedList(selectQueryOperator.Variables); + + return EndNode(selectQueryOperator); + } + + public object VisitDistinctQueryOperator(DistinctQueryOperator distinctQueryOperator, object data) + { + StartNode(distinctQueryOperator); + + WriteKeyword("Distinct"); + + return EndNode(distinctQueryOperator); + } + + public object VisitWhereQueryOperator(WhereQueryOperator whereQueryOperator, object data) + { + StartNode(whereQueryOperator); + + WriteKeyword("Where"); + whereQueryOperator.Condition.AcceptVisitor(this, data); + + return EndNode(whereQueryOperator); + } + + public object VisitPartitionQueryOperator(PartitionQueryOperator partitionQueryOperator, object data) + { + StartNode(partitionQueryOperator); + + switch (partitionQueryOperator.Kind) { + case PartitionKind.Take: + WriteKeyword("Take"); + break; + case PartitionKind.TakeWhile: + WriteKeyword("Take"); + WriteKeyword("While"); + break; + case PartitionKind.Skip: + WriteKeyword("Skip"); + break; + case PartitionKind.SkipWhile: + WriteKeyword("Skip"); + WriteKeyword("While"); + break; + default: + throw new Exception("Invalid value for PartitionKind"); + } + + partitionQueryOperator.Expression.AcceptVisitor(this, data); + + return EndNode(partitionQueryOperator); + } + + public object VisitOrderExpression(OrderExpression orderExpression, object data) + { + StartNode(orderExpression); + + orderExpression.Expression.AcceptVisitor(this, data); + + switch (orderExpression.Direction) { + case QueryOrderingDirection.None: + break; + case QueryOrderingDirection.Ascending: + WriteKeyword("Ascending"); + break; + case QueryOrderingDirection.Descending: + WriteKeyword("Descending"); + break; + default: + throw new Exception("Invalid value for QueryExpressionOrderingDirection"); + } + + return EndNode(orderExpression); + } + + public object VisitOrderByQueryOperator(OrderByQueryOperator orderByQueryOperator, object data) + { + StartNode(orderByQueryOperator); + + WriteKeyword("Order"); + WriteKeyword("By"); + WriteCommaSeparatedList(orderByQueryOperator.Expressions); + + return EndNode(orderByQueryOperator); + } + + public object VisitLetQueryOperator(LetQueryOperator letQueryOperator, object data) + { + StartNode(letQueryOperator); + + WriteKeyword("Let"); + WriteCommaSeparatedList(letQueryOperator.Variables); + + return EndNode(letQueryOperator); + } + + public object VisitGroupByQueryOperator(GroupByQueryOperator groupByQueryOperator, object data) + { + StartNode(groupByQueryOperator); + + WriteKeyword("Group"); + WriteCommaSeparatedList(groupByQueryOperator.GroupExpressions); + WriteKeyword("By"); + WriteCommaSeparatedList(groupByQueryOperator.ByExpressions); + WriteKeyword("Into"); + WriteCommaSeparatedList(groupByQueryOperator.IntoExpressions); + + return EndNode(groupByQueryOperator); + } + + public object VisitJoinQueryOperator(JoinQueryOperator joinQueryOperator, object data) + { + StartNode(joinQueryOperator); + + WriteKeyword("Join"); + joinQueryOperator.JoinVariable.AcceptVisitor(this, data); + if (!joinQueryOperator.SubJoinQuery.IsNull) { + joinQueryOperator.SubJoinQuery.AcceptVisitor(this, data); + } + WriteKeyword("On"); + bool first = true; + foreach (var cond in joinQueryOperator.JoinConditions) { + if (first) + first = false; + else + WriteKeyword("And"); + cond.AcceptVisitor(this, data); + } + + return EndNode(joinQueryOperator); + } + + public object VisitJoinCondition(JoinCondition joinCondition, object data) + { + StartNode(joinCondition); + + joinCondition.Left.AcceptVisitor(this, data); + WriteKeyword("Equals"); + joinCondition.Right.AcceptVisitor(this, data); + + return EndNode(joinCondition); + } + + public object VisitGroupJoinQueryOperator(GroupJoinQueryOperator groupJoinQueryOperator, object data) + { + StartNode(groupJoinQueryOperator); + + WriteKeyword("Group"); + WriteKeyword("Join"); + groupJoinQueryOperator.JoinVariable.AcceptVisitor(this, data); + if (!groupJoinQueryOperator.SubJoinQuery.IsNull) { + groupJoinQueryOperator.SubJoinQuery.AcceptVisitor(this, data); + } + WriteKeyword("On"); + bool first = true; + foreach (var cond in groupJoinQueryOperator.JoinConditions) { + if (first) + first = false; + else + WriteKeyword("And"); + cond.AcceptVisitor(this, data); + } + WriteKeyword("Into"); + WriteCommaSeparatedList(groupJoinQueryOperator.IntoExpressions); + + return EndNode(groupJoinQueryOperator); + } } } diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/TextWriterOutputFormatter.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/TextWriterOutputFormatter.cs index cc2df64ed..f5b610d16 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/TextWriterOutputFormatter.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/TextWriterOutputFormatter.cs @@ -79,5 +79,23 @@ namespace ICSharpCode.NRefactory.VB public virtual void EndNode(AstNode node) { } + + public void WriteComment(bool isDocumentation, string content) + { + WriteIndentation(); + if (isDocumentation) + textWriter.Write("'''"); + else + textWriter.Write("'"); + textWriter.WriteLine(content); + } + + public void MarkFoldStart() + { + } + + public void MarkFoldEnd() + { + } } } diff --git a/ICSharpCode.NRefactory.VB/OutputVisitor/VBFormattingOptions.cs b/ICSharpCode.NRefactory.VB/OutputVisitor/VBFormattingOptions.cs index 8888bf2ff..5dbf95054 100644 --- a/ICSharpCode.NRefactory.VB/OutputVisitor/VBFormattingOptions.cs +++ b/ICSharpCode.NRefactory.VB/OutputVisitor/VBFormattingOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/Parser/Errors.cs b/ICSharpCode.NRefactory.VB/Parser/Errors.cs index 6cd0b2e24..ab9e615bd 100644 --- a/ICSharpCode.NRefactory.VB/Parser/Errors.cs +++ b/ICSharpCode.NRefactory.VB/Parser/Errors.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Text; diff --git a/ICSharpCode.NRefactory.VB/Parser/VBParser.cs b/ICSharpCode.NRefactory.VB/Parser/VBParser.cs index c099d7981..bb3516cb2 100644 --- a/ICSharpCode.NRefactory.VB/Parser/VBParser.cs +++ b/ICSharpCode.NRefactory.VB/Parser/VBParser.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractOutputFormatter.cs b/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractOutputFormatter.cs index c69a56b12..c858d664b 100644 --- a/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractOutputFormatter.cs +++ b/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractOutputFormatter.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections; diff --git a/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractPrettyPrintOptions.cs b/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractPrettyPrintOptions.cs index 438fc54a3..7da8a578c 100644 --- a/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractPrettyPrintOptions.cs +++ b/ICSharpCode.NRefactory.VB/PrettyPrinter/AbstractPrettyPrintOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) namespace ICSharpCode.NRefactory.VB.PrettyPrinter { diff --git a/ICSharpCode.NRefactory.VB/PrettyPrinter/IOutputAstVisitor.cs b/ICSharpCode.NRefactory.VB/PrettyPrinter/IOutputAstVisitor.cs index 71ccb5d0f..049696dad 100644 --- a/ICSharpCode.NRefactory.VB/PrettyPrinter/IOutputAstVisitor.cs +++ b/ICSharpCode.NRefactory.VB/PrettyPrinter/IOutputAstVisitor.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using ICSharpCode.NRefactory.VB.Parser; diff --git a/ICSharpCode.NRefactory.VB/PrettyPrinter/SpecialNodesInserter.cs b/ICSharpCode.NRefactory.VB/PrettyPrinter/SpecialNodesInserter.cs index 95fdcf389..f44d91263 100644 --- a/ICSharpCode.NRefactory.VB/PrettyPrinter/SpecialNodesInserter.cs +++ b/ICSharpCode.NRefactory.VB/PrettyPrinter/SpecialNodesInserter.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputFormatter.cs b/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputFormatter.cs index ca2325bba..aadd790af 100644 --- a/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputFormatter.cs +++ b/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputFormatter.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using ICSharpCode.NRefactory.VB.Parser; diff --git a/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputVisitor.cs b/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputVisitor.cs index 972c09260..d4635d1d1 100644 --- a/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputVisitor.cs +++ b/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetOutputVisitor.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Linq; diff --git a/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetPrettyPrintOptions.cs b/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetPrettyPrintOptions.cs index 0b6170a07..8178afde0 100644 --- a/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetPrettyPrintOptions.cs +++ b/ICSharpCode.NRefactory.VB/PrettyPrinter/VBNet/VBNetPrettyPrintOptions.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; diff --git a/ICSharpCode.NRefactory.VB/VBParser.cs b/ICSharpCode.NRefactory.VB/VBParser.cs index 27d244be1..5f62f952a 100644 --- a/ICSharpCode.NRefactory.VB/VBParser.cs +++ b/ICSharpCode.NRefactory.VB/VBParser.cs @@ -1,5 +1,5 @@ // Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) using System; using System.Collections.Generic; diff --git a/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs new file mode 100644 index 000000000..b28f2813d --- /dev/null +++ b/ICSharpCode.NRefactory.VB/Visitors/CSharpToVBConverterVisitor.cs @@ -0,0 +1,2211 @@ +// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) +// This code is distributed under MIT X11 license (for details please see \doc\license.txt) + +using System; +using System.Collections.Generic; +using System.Linq; + +using ICSharpCode.NRefactory.PatternMatching; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.VB.Ast; + +namespace ICSharpCode.NRefactory.VB.Visitors +{ + public interface IEnvironmentProvider + { + string RootNamespace { get; } + string GetTypeNameForAttribute(CSharp.Attribute attribute); + ClassType GetClassTypeForAstType(CSharp.AstType type); + TypeCode ResolveExpression(CSharp.Expression expression); + bool? IsReferenceType(CSharp.Expression expression); + ITypeResolveContext ResolveContext { get; } + IType ResolveType(AstType type, TypeDeclaration entity = null); + } + + /// + /// Description of CSharpToVBConverterVisitor. + /// + public class CSharpToVBConverterVisitor : CSharp.IAstVisitor + { + IEnvironmentProvider provider; + Stack blocks; + Stack types; + Stack members; + + class MemberInfo + { + public bool inIterator; + } + + public CSharpToVBConverterVisitor(IEnvironmentProvider provider) + { + this.provider = provider; + this.blocks = new Stack(); + this.types = new Stack(); + this.members = new Stack(); + } + + public AstNode VisitAnonymousMethodExpression(CSharp.AnonymousMethodExpression anonymousMethodExpression, object data) + { + members.Push(new MemberInfo()); + + var expr = new MultiLineLambdaExpression() { + IsSub = true, + Body = (BlockStatement)anonymousMethodExpression.Body.AcceptVisitor(this, data) + }; + + ConvertNodes(anonymousMethodExpression.Parameters, expr.Parameters); + + if (members.Pop().inIterator) { + expr.Modifiers |= LambdaExpressionModifiers.Iterator; + } + + return EndNode(anonymousMethodExpression, expr); + } + + public AstNode VisitUndocumentedExpression(CSharp.UndocumentedExpression undocumentedExpression, object data) + { + var invocation = new InvocationExpression(); + + switch (undocumentedExpression.UndocumentedExpressionType) { + case CSharp.UndocumentedExpressionType.ArgListAccess: + case CSharp.UndocumentedExpressionType.ArgList: + invocation.Target = new IdentifierExpression { Identifier = "__ArgList" }; + break; + case CSharp.UndocumentedExpressionType.RefValue: + invocation.Target = new IdentifierExpression { Identifier = "__RefValue" }; + break; + case CSharp.UndocumentedExpressionType.RefType: + invocation.Target = new IdentifierExpression { Identifier = "__RefType" }; + break; + case CSharp.UndocumentedExpressionType.MakeRef: + invocation.Target = new IdentifierExpression { Identifier = "__MakeRef" }; + break; + default: + throw new Exception("Invalid value for UndocumentedExpressionType"); + } + + ConvertNodes(undocumentedExpression.Arguments, invocation.Arguments); + + return EndNode(undocumentedExpression, invocation); + } + + public AstNode VisitArrayCreateExpression(CSharp.ArrayCreateExpression arrayCreateExpression, object data) + { + var expr = new ArrayCreateExpression() { + Type = (AstType)arrayCreateExpression.Type.AcceptVisitor(this, data), + Initializer = (ArrayInitializerExpression)arrayCreateExpression.Initializer.AcceptVisitor(this, data) + }; + ConvertNodes(arrayCreateExpression.Arguments, expr.Arguments); + ConvertNodes(arrayCreateExpression.AdditionalArraySpecifiers, expr.AdditionalArraySpecifiers); + + return EndNode(arrayCreateExpression, expr); + } + + public AstNode VisitArrayInitializerExpression(CSharp.ArrayInitializerExpression arrayInitializerExpression, object data) + { + var expr = new ArrayInitializerExpression(); + ConvertNodes(arrayInitializerExpression.Elements, expr.Elements); + + return EndNode(arrayInitializerExpression, expr); + } + + public AstNode VisitAsExpression(CSharp.AsExpression asExpression, object data) + { + return EndNode(asExpression, new CastExpression(CastType.TryCast, (AstType)asExpression.Type.AcceptVisitor(this, data), (Expression)asExpression.Expression.AcceptVisitor(this, data))); + } + + public AstNode VisitAssignmentExpression(CSharp.AssignmentExpression assignmentExpression, object data) + { + var left = (Expression)assignmentExpression.Left.AcceptVisitor(this, data); + var op = AssignmentOperatorType.None; + var right = (Expression)assignmentExpression.Right.AcceptVisitor(this, data); + + switch (assignmentExpression.Operator) { + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Assign: + op = AssignmentOperatorType.Assign; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Add: + op = AssignmentOperatorType.Add; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Subtract: + op = AssignmentOperatorType.Subtract; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Multiply: + op = AssignmentOperatorType.Multiply; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Divide: + op = AssignmentOperatorType.Divide; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.Modulus: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.Modulus, right); + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftLeft: + op = AssignmentOperatorType.ShiftLeft; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ShiftRight: + op = AssignmentOperatorType.ShiftRight; + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseAnd: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseAnd, right); + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.BitwiseOr: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.BitwiseOr, right); + break; + case ICSharpCode.NRefactory.CSharp.AssignmentOperatorType.ExclusiveOr: + op = AssignmentOperatorType.Assign; + right = new BinaryOperatorExpression((Expression)left.Clone(), BinaryOperatorType.ExclusiveOr, right); + break; + default: + throw new Exception("Invalid value for AssignmentOperatorType: " + assignmentExpression.Operator); + } + + var expr = new AssignmentExpression(left, op, right); + return EndNode(assignmentExpression, expr); + } + + public AstNode VisitBaseReferenceExpression(CSharp.BaseReferenceExpression baseReferenceExpression, object data) + { + InstanceExpression result = new InstanceExpression(InstanceExpressionType.MyBase, baseReferenceExpression.StartLocation); + + return EndNode(baseReferenceExpression, result); + } + + public AstNode VisitBinaryOperatorExpression(CSharp.BinaryOperatorExpression binaryOperatorExpression, object data) + { + var left = (Expression)binaryOperatorExpression.Left.AcceptVisitor(this, data); + var op = BinaryOperatorType.None; + var right = (Expression)binaryOperatorExpression.Right.AcceptVisitor(this, data); + + switch (binaryOperatorExpression.Operator) { + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.BitwiseAnd: + op = BinaryOperatorType.BitwiseAnd; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.BitwiseOr: + op = BinaryOperatorType.BitwiseOr; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ConditionalAnd: + op = BinaryOperatorType.LogicalAnd; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ConditionalOr: + op = BinaryOperatorType.LogicalOr; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ExclusiveOr: + op = BinaryOperatorType.ExclusiveOr; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.GreaterThan: + op = BinaryOperatorType.GreaterThan; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.GreaterThanOrEqual: + op = BinaryOperatorType.GreaterThanOrEqual; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Equality: + if (IsReferentialEquality(binaryOperatorExpression)) + op = BinaryOperatorType.ReferenceEquality; + else + op = BinaryOperatorType.Equality; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.InEquality: + if (IsReferentialEquality(binaryOperatorExpression)) + op = BinaryOperatorType.ReferenceInequality; + else + op = BinaryOperatorType.InEquality; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.LessThan: + op = BinaryOperatorType.LessThan; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.LessThanOrEqual: + op = BinaryOperatorType.LessThanOrEqual; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Add: + // TODO might be string concatenation + op = BinaryOperatorType.Add; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Subtract: + op = BinaryOperatorType.Subtract; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Multiply: + op = BinaryOperatorType.Multiply; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Divide: + op = BinaryOperatorType.Divide; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.Modulus: + op = BinaryOperatorType.Modulus; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ShiftLeft: + op = BinaryOperatorType.ShiftLeft; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.ShiftRight: + op = BinaryOperatorType.ShiftRight; + break; + case ICSharpCode.NRefactory.CSharp.BinaryOperatorType.NullCoalescing: + var nullCoalescing = new ConditionalExpression { + ConditionExpression = left, + FalseExpression = right + }; + return EndNode(binaryOperatorExpression, nullCoalescing); + default: + throw new Exception("Invalid value for BinaryOperatorType: " + binaryOperatorExpression.Operator); + } + + return EndNode(binaryOperatorExpression, new BinaryOperatorExpression(left, op, right)); + } + + bool IsReferentialEquality(CSharp.BinaryOperatorExpression binaryOperatorExpression) + { + var left = provider.IsReferenceType(binaryOperatorExpression.Left); + var right = provider.IsReferenceType(binaryOperatorExpression.Right); + + var leftCode = provider.ResolveExpression(binaryOperatorExpression.Left); + var rightCode = provider.ResolveExpression(binaryOperatorExpression.Right); + + return (left == true || right == true) && (leftCode != TypeCode.String && rightCode != TypeCode.String); + } + + public AstNode VisitCastExpression(CSharp.CastExpression castExpression, object data) + { + var expr = new CastExpression(); + + expr.Type = (AstType)castExpression.Type.AcceptVisitor(this, data); + // TODO read additional type information from annotation + // (int)x is equivalent to CInt(Math.Truncate(x)) + expr.CastType = GetCastType(expr.Type, null); + expr.Expression = (Expression)castExpression.Expression.AcceptVisitor(this, data); + + if (expr.CastType != CastType.CType) + expr.Type = null; + + return EndNode(castExpression, expr); + } + + CastType GetCastType(AstType type, object typeInformation) + { + var primType = type as PrimitiveType; + if (primType == null) + return CastType.CType; + + switch (primType.Keyword) { + case "Boolean": + return CastType.CBool; + case "Byte": + return CastType.CByte; + case "Char": + return CastType.CChar; + case "Date": + return CastType.CDate; + case "Double": + return CastType.CDbl; + case "Decimal": + return CastType.CDec; + case "Integer": + return CastType.CInt; + case "Long": + return CastType.CLng; + case "Object": + return CastType.CObj; + case "SByte": + return CastType.CSByte; + case "Short": + return CastType.CShort; + case "Single": + return CastType.CSng; + case "String": + return CastType.CStr; + case "UInteger": + return CastType.CUInt; + case "ULong": + return CastType.CULng; + case "UShort": + return CastType.CUShort; + } + + return CastType.CType; + } + + public AstNode VisitCheckedExpression(CSharp.CheckedExpression checkedExpression, object data) + { + blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a checked-expression", false), AstNode.Roles.Comment); + return EndNode(checkedExpression, checkedExpression.Expression.AcceptVisitor(this, data)); + } + + public AstNode VisitConditionalExpression(CSharp.ConditionalExpression conditionalExpression, object data) + { + var cond = new ConditionalExpression() { + ConditionExpression = (Expression)conditionalExpression.Condition.AcceptVisitor(this, data), + TrueExpression = (Expression)conditionalExpression.TrueExpression.AcceptVisitor(this, data), + FalseExpression = (Expression)conditionalExpression.FalseExpression.AcceptVisitor(this, data) + }; + + return EndNode(conditionalExpression, cond); + } + + public AstNode VisitDefaultValueExpression(CSharp.DefaultValueExpression defaultValueExpression, object data) + { + // Nothing is equivalent to default(T) for reference and value types. + return EndNode(defaultValueExpression, new PrimitiveExpression(null)); + } + + public AstNode VisitDirectionExpression(CSharp.DirectionExpression directionExpression, object data) + { + return EndNode(directionExpression, (Expression)directionExpression.Expression.AcceptVisitor(this, data)); + } + + public AstNode VisitIdentifierExpression(CSharp.IdentifierExpression identifierExpression, object data) + { + var expr = new IdentifierExpression(); + expr.Identifier = new Identifier(identifierExpression.Identifier, TextLocation.Empty); + ConvertNodes(identifierExpression.TypeArguments, expr.TypeArguments); + + return EndNode(identifierExpression, expr); + } + + public AstNode VisitIndexerExpression(CSharp.IndexerExpression indexerExpression, object data) + { + var expr = new InvocationExpression((Expression)indexerExpression.Target.AcceptVisitor(this, data)); + ConvertNodes(indexerExpression.Arguments, expr.Arguments); + return EndNode(indexerExpression, expr); + } + + public AstNode VisitInvocationExpression(CSharp.InvocationExpression invocationExpression, object data) + { + var expr = new InvocationExpression( + (Expression)invocationExpression.Target.AcceptVisitor(this, data)); + ConvertNodes(invocationExpression.Arguments, expr.Arguments); + + return EndNode(invocationExpression, expr); + } + + public AstNode VisitIsExpression(CSharp.IsExpression isExpression, object data) + { + var expr = new TypeOfIsExpression() { + Type = (AstType)isExpression.Type.AcceptVisitor(this, data), + TypeOfExpression = (Expression)isExpression.Expression.AcceptVisitor(this, data) + }; + + return EndNode(isExpression, expr); + } + + public AstNode VisitLambdaExpression(CSharp.LambdaExpression lambdaExpression, object data) + { + LambdaExpression expr = null; + + if (lambdaExpression.Body is CSharp.Expression) { + var singleLine = new SingleLineFunctionLambdaExpression() { + EmbeddedExpression = (Expression)lambdaExpression.Body.AcceptVisitor(this, data) + }; + ConvertNodes(lambdaExpression.Parameters, singleLine.Parameters); + expr = singleLine; + } else + throw new NotImplementedException(); + + return EndNode(lambdaExpression, expr); + } + + public AstNode VisitMemberReferenceExpression(CSharp.MemberReferenceExpression memberReferenceExpression, object data) + { + var memberAccessExpression = new MemberAccessExpression(); + + memberAccessExpression.Target = (Expression)memberReferenceExpression.Target.AcceptVisitor(this, data); + memberAccessExpression.MemberName = new Identifier(memberReferenceExpression.MemberName, TextLocation.Empty); + ConvertNodes(memberReferenceExpression.TypeArguments, memberAccessExpression.TypeArguments); + + return EndNode(memberReferenceExpression, memberAccessExpression); + } + + public AstNode VisitNamedArgumentExpression(CSharp.NamedArgumentExpression namedArgumentExpression, object 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)); + } + + public AstNode VisitObjectCreateExpression(CSharp.ObjectCreateExpression objectCreateExpression, object data) + { + var expr = new ObjectCreationExpression((AstType)objectCreateExpression.Type.AcceptVisitor(this, data)); + ConvertNodes(objectCreateExpression.Arguments, expr.Arguments); + if (!objectCreateExpression.Initializer.IsNull) + expr.Initializer = (ArrayInitializerExpression)objectCreateExpression.Initializer.AcceptVisitor(this, data); + + return EndNode(objectCreateExpression, expr); + } + + public AstNode VisitAnonymousTypeCreateExpression(CSharp.AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) + { + var expr = new AnonymousObjectCreationExpression(); + + ConvertNodes(anonymousTypeCreateExpression.Initializers, expr.Initializer); + + return EndNode(anonymousTypeCreateExpression, expr); + } + + public AstNode VisitParenthesizedExpression(CSharp.ParenthesizedExpression parenthesizedExpression, object data) + { + var result = new ParenthesizedExpression(); + + result.Expression = (Expression)parenthesizedExpression.Expression.AcceptVisitor(this, data); + + return EndNode(parenthesizedExpression, result); + } + + public AstNode VisitPointerReferenceExpression(CSharp.PointerReferenceExpression pointerReferenceExpression, object data) + { + return EndNode(pointerReferenceExpression,((Expression)pointerReferenceExpression.Target.AcceptVisitor(this, data)).Invoke("Dereference").Member(pointerReferenceExpression.MemberName)); + } + + public AstNode VisitPrimitiveExpression(CSharp.PrimitiveExpression primitiveExpression, object data) + { + Expression expr; + + if (!string.IsNullOrEmpty(primitiveExpression.Value as string) || primitiveExpression.Value is char) + expr = ConvertToConcat(primitiveExpression.Value.ToString()); + else + expr = new PrimitiveExpression(primitiveExpression.Value); + + return EndNode(primitiveExpression, expr); + } + + Expression ConvertToConcat(string literal) + { + Stack parts = new Stack(); + int start = 0; + + for (int i = 0; i < literal.Length; i++) { + string part; + switch (literal[i]) { + case '\0': + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression("vbNullChar")); + start = i + 1; + break; + case '\b': + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression("vbBack")); + start = i + 1; + break; + case '\f': + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression("vbFormFeed")); + start = i + 1; + break; + case '\r': + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + if (i + 1 < literal.Length && literal[i + 1] == '\n') { + i++; + parts.Push(new IdentifierExpression("vbCrLf")); + } else + parts.Push(new IdentifierExpression("vbCr")); + start = i + 1; + break; + case '\n': + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression("vbLf")); + start = i + 1; + break; + case '\t': + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression("vbTab")); + start = i + 1; + break; + case '\v': + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new IdentifierExpression("vbVerticalTab")); + start = i + 1; + break; + default: + if ((int)literal[i] > 255) { + part = literal.Substring(start, i - start); + if (!string.IsNullOrEmpty(part)) + parts.Push(new PrimitiveExpression(part)); + parts.Push(new InvocationExpression(new IdentifierExpression("ChrW"), new PrimitiveExpression((int)literal[i]))); + } else + continue; + start = i + 1; + break; + } + + } + + if (start < literal.Length) { + string part = literal.Substring(start); + parts.Push(new PrimitiveExpression(part)); + } + + Expression current = parts.Pop(); + + while (parts.Any()) + current = new BinaryOperatorExpression(parts.Pop(), BinaryOperatorType.Concat, current); + + return current; + } + + public AstNode VisitSizeOfExpression(CSharp.SizeOfExpression sizeOfExpression, object data) + { + return EndNode( + sizeOfExpression, + new InvocationExpression( + new IdentifierExpression() { Identifier = "__SizeOf" }, + new TypeReferenceExpression((AstType)sizeOfExpression.Type.AcceptVisitor(this, data)) + ) + ); + } + + public AstNode VisitStackAllocExpression(CSharp.StackAllocExpression stackAllocExpression, object data) + { + return EndNode( + stackAllocExpression, + new InvocationExpression( + new IdentifierExpression() { Identifier = "__StackĄlloc" }, + new TypeReferenceExpression((AstType)stackAllocExpression.Type.AcceptVisitor(this, data)), + (Expression)stackAllocExpression.CountExpression.AcceptVisitor(this, data) + ) + ); + } + + public AstNode VisitThisReferenceExpression(CSharp.ThisReferenceExpression thisReferenceExpression, object data) + { + InstanceExpression result = new InstanceExpression(InstanceExpressionType.Me, thisReferenceExpression.StartLocation); + return EndNode(thisReferenceExpression, result); + } + + public AstNode VisitTypeOfExpression(CSharp.TypeOfExpression typeOfExpression, object data) + { + var expr = new GetTypeExpression(); + expr.Type = (AstType)typeOfExpression.Type.AcceptVisitor(this, data); + return EndNode(typeOfExpression, expr); + } + + public AstNode VisitTypeReferenceExpression(CSharp.TypeReferenceExpression typeReferenceExpression, object data) + { + var expr = new TypeReferenceExpression((AstType)typeReferenceExpression.Type.AcceptVisitor(this, data)); + return EndNode(typeReferenceExpression, expr); + } + + public AstNode VisitUnaryOperatorExpression(CSharp.UnaryOperatorExpression unaryOperatorExpression, object data) + { + Expression expr; + + switch (unaryOperatorExpression.Operator) { + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Not: + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.BitNot: + expr = new UnaryOperatorExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), + Operator = UnaryOperatorType.Not + }; + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Minus: + expr = new UnaryOperatorExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), + Operator = UnaryOperatorType.Minus + }; + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Plus: + expr = new UnaryOperatorExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), + Operator = UnaryOperatorType.Plus + }; + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Increment: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Increment" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostIncrement: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__PostIncrement" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Decrement: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Decrement" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.PostDecrement: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__PostDecrement" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.AddressOf: + expr = new UnaryOperatorExpression() { + Expression = (Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data), + Operator = UnaryOperatorType.AddressOf + }; + break; + case ICSharpCode.NRefactory.CSharp.UnaryOperatorType.Dereference: + expr = new InvocationExpression(); + ((InvocationExpression)expr).Target = new IdentifierExpression() { Identifier = "__Dereference" }; + ((InvocationExpression)expr).Arguments.Add((Expression)unaryOperatorExpression.Expression.AcceptVisitor(this, data)); + break; + default: + throw new Exception("Invalid value for UnaryOperatorType"); + } + + return EndNode(unaryOperatorExpression, expr); + } + + public AstNode VisitUncheckedExpression(CSharp.UncheckedExpression uncheckedExpression, object data) + { + blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a unchecked-expression", false), AstNode.Roles.Comment); + return EndNode(uncheckedExpression, uncheckedExpression.Expression.AcceptVisitor(this, data)); + } + + public AstNode VisitEmptyExpression(CSharp.EmptyExpression emptyExpression, object data) + { + return EndNode(emptyExpression, new EmptyExpression()); + } + + public AstNode VisitQueryExpression(CSharp.QueryExpression queryExpression, object data) + { + var expr = new QueryExpression(); + ConvertNodes(queryExpression.Clauses, expr.QueryOperators); + return EndNode(queryExpression, expr); + } + + public AstNode VisitQueryContinuationClause(CSharp.QueryContinuationClause queryContinuationClause, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitQueryFromClause(CSharp.QueryFromClause queryFromClause, object data) + { + var op = new FromQueryOperator(); + op.Variables.Add( + new CollectionRangeVariableDeclaration { + Identifier = new VariableIdentifier { Name = queryFromClause.Identifier }, + Type = (AstType)queryFromClause.Type.AcceptVisitor(this, data), + Expression = (Expression)queryFromClause.Expression.AcceptVisitor(this, data) + } + ); + + return EndNode(queryFromClause, op); + } + + public AstNode VisitQueryLetClause(CSharp.QueryLetClause queryLetClause, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitQueryWhereClause(CSharp.QueryWhereClause queryWhereClause, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitQueryJoinClause(CSharp.QueryJoinClause queryJoinClause, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitQueryOrderClause(CSharp.QueryOrderClause queryOrderClause, object data) + { + var op = new OrderByQueryOperator(); + + ConvertNodes(queryOrderClause.Orderings, op.Expressions); + + return EndNode(queryOrderClause, op); + } + + public AstNode VisitQueryOrdering(CSharp.QueryOrdering queryOrdering, object data) + { + var expr = new OrderExpression(); + + expr.Direction = (QueryOrderingDirection)queryOrdering.Direction; + expr.Expression = (Expression)queryOrdering.Expression.AcceptVisitor(this, data); + + return EndNode(queryOrdering, expr); + } + + int selectVarCount = 0; + + public AstNode VisitQuerySelectClause(CSharp.QuerySelectClause querySelectClause, object data) + { + var op = new SelectQueryOperator(); + + op.Variables.Add( + new VariableInitializer { + Identifier = new VariableIdentifier { Name = "SelectVar" + selectVarCount }, + Expression = (Expression)querySelectClause.Expression.AcceptVisitor(this, data) + }); + + return EndNode(querySelectClause, op); + } + + public AstNode VisitQueryGroupClause(CSharp.QueryGroupClause queryGroupClause, object data) + { + var op = new GroupByQueryOperator(); + + throw new NotImplementedException(); + + return EndNode(queryGroupClause, op); + } + + public AstNode VisitAttribute(CSharp.Attribute attribute, object data) + { + var attr = new VB.Ast.Attribute(); + AttributeTarget target; + Enum.TryParse(((CSharp.AttributeSection)attribute.Parent).AttributeTarget, true, out target); + attr.Target = target; + attr.Type = (AstType)attribute.Type.AcceptVisitor(this, data); + ConvertNodes(attribute.Arguments, attr.Arguments); + + return EndNode(attribute, attr); + } + + public AstNode VisitAttributeSection(CSharp.AttributeSection attributeSection, object data) + { + AttributeBlock block = new AttributeBlock(); + ConvertNodes(attributeSection.Attributes, block.Attributes); + return EndNode(attributeSection, block); + } + + public AstNode VisitDelegateDeclaration(CSharp.DelegateDeclaration delegateDeclaration, object data) + { + var result = new DelegateDeclaration(); + + ConvertNodes(delegateDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes); + ConvertNodes(delegateDeclaration.ModifierTokens, result.ModifierTokens); + result.Name = new Identifier(delegateDeclaration.Name, TextLocation.Empty); + result.IsSub = IsSub(delegateDeclaration.ReturnType); + ConvertNodes(delegateDeclaration.Parameters, result.Parameters); + ConvertNodes(delegateDeclaration.TypeParameters, result.TypeParameters); + ConvertNodes(delegateDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes); + if (!result.IsSub) + result.ReturnType = (AstType)delegateDeclaration.ReturnType.AcceptVisitor(this, data); + return EndNode(delegateDeclaration, result); + } + + public AstNode VisitNamespaceDeclaration(CSharp.NamespaceDeclaration namespaceDeclaration, object data) + { + var newNamespace = new NamespaceDeclaration(); + + ConvertNodes(namespaceDeclaration.Identifiers, newNamespace.Identifiers); + ConvertNodes(namespaceDeclaration.Members, newNamespace.Members); + + return EndNode(namespaceDeclaration, newNamespace); + } + + public AstNode VisitTypeDeclaration(CSharp.TypeDeclaration typeDeclaration, object data) + { + // TODO add missing features! + + if (typeDeclaration.ClassType == CSharp.ClassType.Enum) { + var type = new EnumDeclaration(); + CopyAnnotations(typeDeclaration, type); + + ConvertNodes(typeDeclaration.Attributes, type.Attributes); + ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens); + + if (typeDeclaration.BaseTypes.Any()) { + var first = typeDeclaration.BaseTypes.First(); + + type.UnderlyingType = (AstType)first.AcceptVisitor(this, data); + } + + type.Name = new Identifier(typeDeclaration.Name, TextLocation.Empty); + + ConvertNodes(typeDeclaration.Members, type.Members); + + return EndNode(typeDeclaration, type); + } else { + var type = new TypeDeclaration(); + CopyAnnotations(typeDeclaration, type); + + CSharp.Attribute stdModAttr; + + if (typeDeclaration.ClassType == CSharp.ClassType.Class && HasAttribute(typeDeclaration.Attributes, "Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute", out stdModAttr)) { + type.ClassType = ClassType.Module; + // remove AttributeSection if only one attribute is present + var attrSec = (CSharp.AttributeSection)stdModAttr.Parent; + if (attrSec.Attributes.Count == 1) + attrSec.Remove(); + else + stdModAttr.Remove(); + } else { + switch (typeDeclaration.ClassType) { + case CSharp.ClassType.Class: + type.ClassType = ClassType.Class; + break; + case CSharp.ClassType.Struct: + type.ClassType = ClassType.Struct; + break; + case CSharp.ClassType.Interface: + type.ClassType = ClassType.Interface; + break; + default: + throw new InvalidOperationException("Invalid value for ClassType"); + } + } + + if ((typeDeclaration.Modifiers & CSharp.Modifiers.Static) == CSharp.Modifiers.Static) { + type.ClassType = ClassType.Module; + typeDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + } + + ConvertNodes(typeDeclaration.Attributes, type.Attributes); + ConvertNodes(typeDeclaration.ModifierTokens, type.ModifierTokens); + + if (typeDeclaration.BaseTypes.Any()) { + var first = typeDeclaration.BaseTypes.First(); + + if (provider.GetClassTypeForAstType(first) != ClassType.Interface) { + ConvertNodes(typeDeclaration.BaseTypes.Skip(1), type.ImplementsTypes); + type.InheritsType = (AstType)first.AcceptVisitor(this, data); + } else + ConvertNodes(typeDeclaration.BaseTypes, type.ImplementsTypes); + } + + type.Name = typeDeclaration.Name; + + types.Push(type); + ConvertNodes(typeDeclaration.Members, type.Members); + types.Pop(); + + return EndNode(typeDeclaration, type); + } + } + + public AstNode VisitUsingAliasDeclaration(CSharp.UsingAliasDeclaration usingAliasDeclaration, object data) + { + var imports = new ImportsStatement(); + + var clause = new AliasImportsClause() { + Name = new Identifier(usingAliasDeclaration.Alias, TextLocation.Empty), + Alias = (AstType)usingAliasDeclaration.Import.AcceptVisitor(this, data) + }; + + imports.AddChild(clause, ImportsStatement.ImportsClauseRole); + + return EndNode(usingAliasDeclaration, imports); + } + + public AstNode VisitUsingDeclaration(CSharp.UsingDeclaration usingDeclaration, object data) + { + var imports = new ImportsStatement(); + + var clause = new MemberImportsClause() { + Member = (AstType)usingDeclaration.Import.AcceptVisitor(this, data) + }; + + imports.AddChild(clause, ImportsStatement.ImportsClauseRole); + + return EndNode(usingDeclaration, imports); + } + + public AstNode VisitExternAliasDeclaration(CSharp.ExternAliasDeclaration externAliasDeclaration, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitBlockStatement(CSharp.BlockStatement blockStatement, object data) + { + var block = new BlockStatement(); + blocks.Push(block); + ConvertNodes(blockStatement, block.Statements); + blocks.Pop(); + return EndNode(blockStatement, block); + } + + public AstNode VisitBreakStatement(CSharp.BreakStatement breakStatement, object data) + { + var exit = new ExitStatement(ExitKind.None); + + foreach (var stmt in breakStatement.Ancestors) { + if (stmt is CSharp.MethodDeclaration) { + exit.ExitKind = IsSub(((CSharp.MethodDeclaration)stmt).ReturnType) ? ExitKind.Sub : ExitKind.Function; + break; + } + if (stmt is CSharp.PropertyDeclaration) { + exit.ExitKind = ExitKind.Property; + break; + } + if (stmt is CSharp.DoWhileStatement) { + exit.ExitKind = ExitKind.Do; + break; + } + if (stmt is CSharp.ForStatement || stmt is CSharp.ForeachStatement) { + exit.ExitKind = ExitKind.For; + break; + } + if (stmt is CSharp.WhileStatement) { + exit.ExitKind = ExitKind.While; + break; + } + if (stmt is CSharp.SwitchStatement) { + exit.ExitKind = ExitKind.Select; + break; + } + if (stmt is CSharp.TryCatchStatement) { + exit.ExitKind = ExitKind.Try; + break; + } + } + + return EndNode(breakStatement, exit); + } + + public AstNode VisitCheckedStatement(CSharp.CheckedStatement checkedStatement, object data) + { + blocks.Peek().AddChild(new Comment(" The following expression was wrapped in a checked-statement", false), AstNode.Roles.Comment); + var body = (BlockStatement)checkedStatement.Body.AcceptVisitor(this, data); + + foreach (var stmt in body) { + stmt.Remove(); + blocks.Peek().Add(stmt); + } + + return EndNode(checkedStatement, null); + } + + public AstNode VisitContinueStatement(CSharp.ContinueStatement continueStatement, object data) + { + var @continue = new ContinueStatement(ContinueKind.None); + + foreach (var stmt in continueStatement.Ancestors) { + if (stmt is CSharp.DoWhileStatement) { + @continue.ContinueKind = ContinueKind.Do; + break; + } + if (stmt is CSharp.ForStatement || stmt is CSharp.ForeachStatement) { + @continue.ContinueKind = ContinueKind.For; + break; + } + if (stmt is CSharp.WhileStatement) { + @continue.ContinueKind = ContinueKind.While; + break; + } + } + + return EndNode(continueStatement, @continue); + } + + public AstNode VisitDoWhileStatement(CSharp.DoWhileStatement doWhileStatement, object data) + { + var stmt = new DoLoopStatement(); + + stmt.ConditionType = ConditionType.LoopWhile; + stmt.Expression = (Expression)doWhileStatement.Condition.AcceptVisitor(this, data); + stmt.Body = (BlockStatement)doWhileStatement.EmbeddedStatement.AcceptVisitor(this, data); + + return EndNode(doWhileStatement, stmt); + } + + public AstNode VisitEmptyStatement(CSharp.EmptyStatement emptyStatement, object data) + { + return EndNode(emptyStatement, null); + } + + public AstNode VisitExpressionStatement(CSharp.ExpressionStatement expressionStatement, object data) + { + var expr = new ExpressionStatement((Expression)expressionStatement.Expression.AcceptVisitor(this, data)); + return EndNode(expressionStatement, expr); + } + + public AstNode VisitFixedStatement(CSharp.FixedStatement fixedStatement, object data) + { + var block = blocks.Peek(); + block.AddChild(new Comment(" Emulating fixed-Statement, might not be entirely correct!", false), AstNode.Roles.Comment); + + var variables = new LocalDeclarationStatement(); + variables.Modifiers = Modifiers.Dim; + var stmt = new TryStatement(); + stmt.FinallyBlock = new BlockStatement(); + foreach (var decl in fixedStatement.Variables) { + var v = new VariableDeclaratorWithTypeAndInitializer { + Identifiers = { new VariableIdentifier { Name = decl.Name } }, + Type = new SimpleType("GCHandle"), + Initializer = new InvocationExpression( + new MemberAccessExpression { Target = new IdentifierExpression { Identifier = "GCHandle" }, MemberName = "Alloc" }, + (Expression)decl.Initializer.AcceptVisitor(this, data), + new MemberAccessExpression { Target = new IdentifierExpression { Identifier = "GCHandleType" }, MemberName = "Pinned" } + ) + }; + variables.Variables.Add(v); + stmt.FinallyBlock.Add(new IdentifierExpression { Identifier = decl.Name }.Invoke("Free")); + } + + block.Add(variables); + + stmt.Body = (BlockStatement)fixedStatement.EmbeddedStatement.AcceptVisitor(this, data); + + foreach (var ident in stmt.Body.Descendants.OfType()) { + ident.ReplaceWith(expr => ((Expression)expr).Invoke("AddrOfPinnedObject")); + } + + return EndNode(fixedStatement, stmt); + } + + public AstNode VisitForeachStatement(CSharp.ForeachStatement foreachStatement, object data) + { + var stmt = new ForEachStatement() { + Body = (BlockStatement)foreachStatement.EmbeddedStatement.AcceptVisitor(this, data), + InExpression = (Expression)foreachStatement.InExpression.AcceptVisitor(this, data), + Variable = new VariableInitializer() { + Identifier = new VariableIdentifier() { Name = foreachStatement.VariableName }, + Type = (AstType)foreachStatement.VariableType.AcceptVisitor(this, data) + } + }; + + return EndNode(foreachStatement, stmt); + } + + public AstNode VisitForStatement(CSharp.ForStatement forStatement, object data) + { + // for (;;) ; + if (!forStatement.Initializers.Any() && forStatement.Condition.IsNull && !forStatement.Iterators.Any()) + return EndNode(forStatement, new WhileStatement() { Condition = new PrimitiveExpression(true), Body = (BlockStatement)forStatement.EmbeddedStatement.AcceptVisitor(this, data) }); + + CSharp.AstNode counterLoop = new CSharp.ForStatement() { + Initializers = { + new NamedNode( + "iteratorVar", + new Choice { + new CSharp.VariableDeclarationStatement { + Type = new Choice { + new CSharp.PrimitiveType("long"), + new CSharp.PrimitiveType("ulong"), + new CSharp.PrimitiveType("int"), + new CSharp.PrimitiveType("uint"), + new CSharp.PrimitiveType("short"), + new CSharp.PrimitiveType("ushort"), + new CSharp.PrimitiveType("sbyte"), + new CSharp.PrimitiveType("byte") + }, + Variables = { + new AnyNode() + } + }, + new CSharp.ExpressionStatement( + new CSharp.AssignmentExpression() + ) + }) + }, + Condition = new NamedNode( + "condition", + new CSharp.BinaryOperatorExpression { + Left = new NamedNode("ident", new CSharp.IdentifierExpression()), + Operator = CSharp.BinaryOperatorType.Any, + Right = new AnyNode("endExpr") + }), + Iterators = { + new CSharp.ExpressionStatement( + new NamedNode( + "increment", + new CSharp.AssignmentExpression { + Left = new Backreference("ident"), + Operator = CSharp.AssignmentOperatorType.Any, + Right = new NamedNode("factor", new AnyNode()) + } + ) + ) + }, + EmbeddedStatement = new NamedNode("body", new AnyNode()) + }; + + var match = counterLoop.Match(forStatement); + + if (match.Success) { + var init = match.Get("iteratorVar").SingleOrDefault(); + + AstNode iteratorVariable; + + if (init is CSharp.VariableDeclarationStatement) { + var var = ((CSharp.VariableDeclarationStatement)init).Variables.First(); + iteratorVariable = new VariableInitializer() { + Identifier = new VariableIdentifier { Name = var.Name }, + Type = (AstType)((CSharp.VariableDeclarationStatement)init).Type.AcceptVisitor(this, data), + Expression = (Expression)var.Initializer.AcceptVisitor(this, data) + }; + } else if (init is CSharp.ExpressionStatement) { + iteratorVariable = init.AcceptVisitor(this, data); + } else goto end; + + Expression toExpr = Expression.Null; + + var cond = match.Get("condition").SingleOrDefault(); + var endExpr = (Expression)match.Get("endExpr").SingleOrDefault().AcceptVisitor(this, data); + + if (cond.Operator == CSharp.BinaryOperatorType.LessThanOrEqual || + cond.Operator == CSharp.BinaryOperatorType.GreaterThanOrEqual) { + toExpr = endExpr; + } + + if (cond.Operator == CSharp.BinaryOperatorType.LessThan) + toExpr = new BinaryOperatorExpression(endExpr, BinaryOperatorType.Subtract, new PrimitiveExpression(1)); + if (cond.Operator == CSharp.BinaryOperatorType.GreaterThan) + toExpr = new BinaryOperatorExpression(endExpr, BinaryOperatorType.Add, new PrimitiveExpression(1)); + + Expression stepExpr = Expression.Null; + + var increment = match.Get("increment").SingleOrDefault(); + var factorExpr = (Expression)match.Get("factor").SingleOrDefault().AcceptVisitor(this, data); + + if (increment.Operator == CSharp.AssignmentOperatorType.Add && (factorExpr is PrimitiveExpression && !IsEqual(((PrimitiveExpression)factorExpr).Value, 1))) + stepExpr = factorExpr; + if (increment.Operator == CSharp.AssignmentOperatorType.Subtract) + stepExpr = new UnaryOperatorExpression(UnaryOperatorType.Minus, factorExpr); + + return new ForStatement() { + Variable = iteratorVariable, + ToExpression = toExpr, + StepExpression = stepExpr, + Body = (BlockStatement)match.Get("body").Single().AcceptVisitor(this, data) + }; + } + + end: + var stmt = new WhileStatement() { + Condition = (Expression)forStatement.Condition.AcceptVisitor(this, data), + Body = (BlockStatement)forStatement.EmbeddedStatement.AcceptVisitor(this, data) + }; + ConvertNodes(forStatement.Iterators, stmt.Body.Statements); + foreach (var initializer in forStatement.Initializers) + blocks.Peek().Statements.Add((Statement)initializer.AcceptVisitor(this, data)); + + return EndNode(forStatement, stmt); + } + + bool IsEqual(object value, int num) + { + if (value is byte) + return (byte)value == num; + if (value is sbyte) + return (sbyte)value == num; + if (value is short) + return (short)value == num; + if (value is ushort) + return (ushort)value == num; + if (value is int) + return (int)value == num; + if (value is uint) + return (uint)value == num; + if (value is long) + return (long)value == num; + if (value is ulong) + return (ulong)value == (ulong)num; + + throw new InvalidCastException(); + } + + public AstNode VisitGotoCaseStatement(CSharp.GotoCaseStatement gotoCaseStatement, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitGotoDefaultStatement(CSharp.GotoDefaultStatement gotoDefaultStatement, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitGotoStatement(CSharp.GotoStatement gotoStatement, object data) + { + return EndNode(gotoStatement, new GoToStatement() { Label = new IdentifierExpression() { Identifier = gotoStatement.Label } }); + } + + public AstNode VisitIfElseStatement(CSharp.IfElseStatement ifElseStatement, object data) + { + var stmt = new IfElseStatement(); + + stmt.Condition = (Expression)ifElseStatement.Condition.AcceptVisitor(this, data); + stmt.Body = (Statement)ifElseStatement.TrueStatement.AcceptVisitor(this, data); + stmt.ElseBlock = (Statement)ifElseStatement.FalseStatement.AcceptVisitor(this, data); + + return EndNode(ifElseStatement, stmt); + } + + public AstNode VisitLabelStatement(CSharp.LabelStatement labelStatement, object data) + { + return EndNode(labelStatement, new LabelDeclarationStatement() { Label = new IdentifierExpression() { Identifier = labelStatement.Label } }); + } + + public AstNode VisitLockStatement(CSharp.LockStatement lockStatement, object data) + { + var stmt = new SyncLockStatement(); + + stmt.Expression = (Expression)lockStatement.Expression.AcceptVisitor(this, data); + stmt.Body = (BlockStatement)lockStatement.EmbeddedStatement.AcceptVisitor(this, data); + + return EndNode(lockStatement, stmt); + } + + public AstNode VisitReturnStatement(CSharp.ReturnStatement returnStatement, object data) + { + var stmt = new ReturnStatement((Expression)returnStatement.Expression.AcceptVisitor(this, data)); + + return EndNode(returnStatement, stmt); + } + + public AstNode VisitSwitchStatement(CSharp.SwitchStatement switchStatement, object data) + { + var stmt = new SelectStatement() { Expression = (Expression)switchStatement.Expression.AcceptVisitor(this, data) }; + ConvertNodes(switchStatement.SwitchSections, stmt.Cases); + + return EndNode(switchStatement, stmt); + } + + public AstNode VisitSwitchSection(CSharp.SwitchSection switchSection, object data) + { + var caseStmt = new CaseStatement(); + ConvertNodes(switchSection.CaseLabels, caseStmt.Clauses); + if (switchSection.Statements.Count == 1 && switchSection.Statements.FirstOrDefault() is CSharp.BlockStatement) + caseStmt.Body = (BlockStatement)switchSection.Statements.FirstOrDefault().AcceptVisitor(this, data); + else { + caseStmt.Body = new BlockStatement(); + ConvertNodes(switchSection.Statements, caseStmt.Body.Statements); + } + if (caseStmt.Body.LastOrDefault() is ExitStatement && ((ExitStatement)caseStmt.Body.LastOrDefault()).ExitKind == ExitKind.Select) + caseStmt.Body.LastOrDefault().Remove(); + return EndNode(switchSection, caseStmt); + } + + public AstNode VisitCaseLabel(CSharp.CaseLabel caseLabel, object data) + { + return EndNode(caseLabel, new SimpleCaseClause() { Expression = (Expression)caseLabel.Expression.AcceptVisitor(this, data) }); + } + + public AstNode VisitThrowStatement(CSharp.ThrowStatement throwStatement, object data) + { + return EndNode(throwStatement, new ThrowStatement((Expression)throwStatement.Expression.AcceptVisitor(this, data))); + } + + public AstNode VisitTryCatchStatement(CSharp.TryCatchStatement tryCatchStatement, object data) + { + var stmt = new TryStatement(); + + stmt.Body = (BlockStatement)tryCatchStatement.TryBlock.AcceptVisitor(this, data); + stmt.FinallyBlock = (BlockStatement)tryCatchStatement.FinallyBlock.AcceptVisitor(this, data); + ConvertNodes(tryCatchStatement.CatchClauses, stmt.CatchBlocks); + + return EndNode(tryCatchStatement, stmt); + } + + public AstNode VisitCatchClause(CSharp.CatchClause catchClause, object data) + { + var clause = new CatchBlock(); + + clause.ExceptionType = (AstType)catchClause.Type.AcceptVisitor(this, data); + clause.ExceptionVariable = catchClause.VariableName; + ConvertNodes(catchClause.Body.Statements, clause.Statements); + + return EndNode(catchClause, clause); + } + + public AstNode VisitUncheckedStatement(CSharp.UncheckedStatement uncheckedStatement, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitUnsafeStatement(CSharp.UnsafeStatement unsafeStatement, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitUsingStatement(CSharp.UsingStatement usingStatement, object data) + { + var stmt = new UsingStatement(); + + stmt.Resources.Add(usingStatement.ResourceAcquisition.AcceptVisitor(this, data)); + stmt.Body = (BlockStatement)usingStatement.EmbeddedStatement.AcceptVisitor(this, data); + + return EndNode(usingStatement, stmt); + } + + public AstNode VisitVariableDeclarationStatement(CSharp.VariableDeclarationStatement variableDeclarationStatement, object data) + { + var decl = new LocalDeclarationStatement(); + decl.Modifiers = Modifiers.Dim; + ConvertNodes(variableDeclarationStatement.Variables, decl.Variables); + + return EndNode(variableDeclarationStatement, decl); + } + + public AstNode VisitWhileStatement(CSharp.WhileStatement whileStatement, object data) + { + var stmt = new WhileStatement() { + Condition = (Expression)whileStatement.Condition.AcceptVisitor(this, data), + Body = (BlockStatement)whileStatement.EmbeddedStatement.AcceptVisitor(this, data) + }; + + return EndNode(whileStatement, stmt); + } + + public AstNode VisitYieldBreakStatement(CSharp.YieldBreakStatement yieldBreakStatement, object data) + { + var frame = members.Peek(); + frame.inIterator = true; + return EndNode(yieldBreakStatement, new ReturnStatement()); + } + + public AstNode VisitYieldReturnStatement(CSharp.YieldReturnStatement yieldReturnStatement, object data) + { + var frame = members.Peek(); + frame.inIterator = true; + return EndNode(yieldReturnStatement, new YieldStatement((Expression)yieldReturnStatement.Expression.AcceptVisitor(this, data))); + } + + public AstNode VisitAccessor(CSharp.Accessor accessor, object data) + { + var result = new Accessor(); + + ConvertNodes(accessor.Attributes, result.Attributes); + ConvertNodes(accessor.ModifierTokens, result.ModifierTokens); + result.Body = (BlockStatement)accessor.Body.AcceptVisitor(this, data); + + return EndNode(accessor, result); + } + + public AstNode VisitConstructorDeclaration(CSharp.ConstructorDeclaration constructorDeclaration, object data) + { + var result = new ConstructorDeclaration(); + + ConvertNodes(constructorDeclaration.Attributes, result.Attributes); + ConvertNodes(constructorDeclaration.ModifierTokens, result.ModifierTokens); + ConvertNodes(constructorDeclaration.Parameters, result.Parameters); + result.Body = (BlockStatement)constructorDeclaration.Body.AcceptVisitor(this, data); + if (!constructorDeclaration.Initializer.IsNull) + result.Body.Statements.InsertBefore(result.Body.FirstOrDefault(), (Statement)constructorDeclaration.Initializer.AcceptVisitor(this, data)); + + return EndNode(constructorDeclaration, result); + } + + public AstNode VisitConstructorInitializer(CSharp.ConstructorInitializer constructorInitializer, object data) + { + var result = new InvocationExpression( + new MemberAccessExpression() { + Target = new InstanceExpression(constructorInitializer.ConstructorInitializerType == CSharp.ConstructorInitializerType.This ? InstanceExpressionType.Me : InstanceExpressionType.MyBase, TextLocation.Empty), + MemberName = new Identifier("New", TextLocation.Empty) + } + ); + ConvertNodes(constructorInitializer.Arguments, result.Arguments); + + return EndNode(constructorInitializer, new ExpressionStatement(result)); + } + + public AstNode VisitDestructorDeclaration(CSharp.DestructorDeclaration destructorDeclaration, object data) + { + var finalizer = new MethodDeclaration() { Name = "Finalize", IsSub = true }; + + ConvertNodes(destructorDeclaration.Attributes, finalizer.Attributes); + ConvertNodes(destructorDeclaration.ModifierTokens, finalizer.ModifierTokens); + finalizer.Body = (BlockStatement)destructorDeclaration.Body.AcceptVisitor(this, data); + + return EndNode(destructorDeclaration, finalizer); + } + + public AstNode VisitEnumMemberDeclaration(CSharp.EnumMemberDeclaration enumMemberDeclaration, object data) + { + var result = new EnumMemberDeclaration(); + + ConvertNodes(enumMemberDeclaration.Attributes, result.Attributes); + result.Name = new Identifier(enumMemberDeclaration.Name, TextLocation.Empty); + result.Value = (Expression)enumMemberDeclaration.Initializer.AcceptVisitor(this, data); + + return EndNode(enumMemberDeclaration, result); + } + + public AstNode VisitEventDeclaration(CSharp.EventDeclaration eventDeclaration, object data) + { + members.Push(new MemberInfo()); + + foreach (var evt in eventDeclaration.Variables) { + var result = new EventDeclaration(); + + ConvertNodes(eventDeclaration.Attributes, result.Attributes); + if (types.Any() && types.Peek().ClassType == ClassType.Module) + eventDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + result.Modifiers = ConvertModifiers(eventDeclaration.Modifiers, eventDeclaration); + result.Name = evt.Name; + result.ReturnType = (AstType)eventDeclaration.ReturnType.AcceptVisitor(this, data); + +// CreateImplementsClausesForEvent(result); + + types.Peek().Members.Add(result); + } + + members.Pop(); + + return EndNode(eventDeclaration, null); + } + + public AstNode VisitCustomEventDeclaration(CSharp.CustomEventDeclaration customEventDeclaration, object data) + { + var result = new EventDeclaration(); + + members.Push(new MemberInfo()); + + ConvertNodes(customEventDeclaration.Attributes, result.Attributes); + if (types.Any() && types.Peek().ClassType == ClassType.Module) + customEventDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + result.Modifiers = ConvertModifiers(customEventDeclaration.Modifiers, customEventDeclaration); + result.IsCustom = true; + result.Name = new Identifier(customEventDeclaration.Name, TextLocation.Empty); + result.ReturnType = (AstType)customEventDeclaration.ReturnType.AcceptVisitor(this, data); + if (!customEventDeclaration.PrivateImplementationType.IsNull) + result.ImplementsClause.Add( + new InterfaceMemberSpecifier((AstType)customEventDeclaration.PrivateImplementationType.AcceptVisitor(this, data), customEventDeclaration.Name)); +// else +// CreateImplementsClausesForEvent(result); + result.AddHandlerBlock = (Accessor)customEventDeclaration.AddAccessor.AcceptVisitor(this, data); + result.RemoveHandlerBlock = (Accessor)customEventDeclaration.RemoveAccessor.AcceptVisitor(this, data); + + members.Pop(); + + return EndNode(customEventDeclaration, result); + } + + public AstNode VisitFieldDeclaration(CSharp.FieldDeclaration fieldDeclaration, object data) + { + var decl = new FieldDeclaration(); + + members.Push(new MemberInfo()); + + ConvertNodes(fieldDeclaration.Attributes, decl.Attributes); + if (types.Any() && types.Peek().ClassType == ClassType.Module) + fieldDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + decl.Modifiers = ConvertModifiers(fieldDeclaration.Modifiers, fieldDeclaration); + ConvertNodes(fieldDeclaration.Variables, decl.Variables); + + members.Pop(); + + return EndNode(fieldDeclaration, decl); + } + + public AstNode VisitIndexerDeclaration(CSharp.IndexerDeclaration indexerDeclaration, object data) + { + var decl = new PropertyDeclaration(); + + members.Push(new MemberInfo()); + + ConvertNodes(indexerDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), decl.Attributes); + decl.Getter = (Accessor)indexerDeclaration.Getter.AcceptVisitor(this, data); + if (types.Any() && types.Peek().ClassType == ClassType.Module) + indexerDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + decl.Modifiers = ConvertModifiers(indexerDeclaration.Modifiers, indexerDeclaration); + decl.Name = new Identifier(indexerDeclaration.Name, TextLocation.Empty); + ConvertNodes(indexerDeclaration.Parameters, decl.Parameters); + ConvertNodes(indexerDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), decl.ReturnTypeAttributes); + if (!indexerDeclaration.PrivateImplementationType.IsNull) + decl.ImplementsClause.Add( + new InterfaceMemberSpecifier((AstType)indexerDeclaration.PrivateImplementationType.AcceptVisitor(this, data), + indexerDeclaration.Name)); + decl.ReturnType = (AstType)indexerDeclaration.ReturnType.AcceptVisitor(this, data); + decl.Setter = (Accessor)indexerDeclaration.Setter.AcceptVisitor(this, data); + + if (!decl.Setter.IsNull) { + decl.Setter.Parameters.Add(new ParameterDeclaration() { + Name = new Identifier("value", TextLocation.Empty), + Type = (AstType)indexerDeclaration.ReturnType.AcceptVisitor(this, data), + }); + } + + members.Pop(); + + return EndNode(indexerDeclaration, decl); + } + + public AstNode VisitMethodDeclaration(CSharp.MethodDeclaration methodDeclaration, object data) + { + CSharp.Attribute attr; + + if (types.Any() && types.Peek().ClassType == ClassType.Module) + methodDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + + if ((methodDeclaration.Modifiers & CSharp.Modifiers.Extern) == CSharp.Modifiers.Extern && HasAttribute(methodDeclaration.Attributes, "System.Runtime.InteropServices.DllImportAttribute", out attr)) { + var result = new ExternalMethodDeclaration(); + + members.Push(new MemberInfo()); + + // remove AttributeSection if only one attribute is present + var attrSec = (CSharp.AttributeSection)attr.Parent; + if (attrSec.Attributes.Count == 1) + attrSec.Remove(); + else + attr.Remove(); + + result.Library = (attr.Arguments.First().AcceptVisitor(this, data) as PrimitiveExpression).Value.ToString(); + result.CharsetModifier = ConvertCharset(attr.Arguments); + result.Alias = ConvertAlias(attr.Arguments); + + ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes); + ConvertNodes(methodDeclaration.ModifierTokens, result.ModifierTokens); + result.Name = new Identifier(methodDeclaration.Name, TextLocation.Empty); + result.IsSub = IsSub(methodDeclaration.ReturnType); + ConvertNodes(methodDeclaration.Parameters, result.Parameters); + ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes); + if (!result.IsSub) + result.ReturnType = (AstType)methodDeclaration.ReturnType.AcceptVisitor(this, data); + + if (members.Pop().inIterator) { + result.Modifiers |= Modifiers.Iterator; + } + + return EndNode(methodDeclaration, result); + } else { + var result = new MethodDeclaration(); + + members.Push(new MemberInfo()); + + ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), result.Attributes); + ConvertNodes(methodDeclaration.ModifierTokens, result.ModifierTokens); + result.Name = new Identifier(methodDeclaration.Name, TextLocation.Empty); + result.IsSub = IsSub(methodDeclaration.ReturnType); + ConvertNodes(methodDeclaration.Parameters, result.Parameters); + ConvertNodes(methodDeclaration.TypeParameters, result.TypeParameters); + ConvertNodes(methodDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), result.ReturnTypeAttributes); + if (!methodDeclaration.PrivateImplementationType.IsNull) + result.ImplementsClause.Add( + new InterfaceMemberSpecifier((AstType)methodDeclaration.PrivateImplementationType.AcceptVisitor(this, data), + methodDeclaration.Name)); +// else +// CreateImplementsClausesForMethod(result); + if (!result.IsSub) + result.ReturnType = (AstType)methodDeclaration.ReturnType.AcceptVisitor(this, data); + + if (methodDeclaration.IsExtensionMethod) { + result.Attributes.Add( + new AttributeBlock { + Attributes = { + new Ast.Attribute { + Type = AstType.FromName("System.Runtime.CompilerServices.ExtensionAttribute") + } + } + }); + } + + result.Body = (BlockStatement)methodDeclaration.Body.AcceptVisitor(this, data); + + if (members.Pop().inIterator) { + result.Modifiers |= Modifiers.Iterator; + } + + return EndNode(methodDeclaration, result); + } + } + + void CreateImplementsClausesForMethod(MethodDeclaration result) + { + if (!types.Any()) return; + var current = types.Peek(); + if (current.ClassType == ClassType.Interface) + return; + + foreach (var type in current.ImplementsTypes) { + var resolved = provider.ResolveType(type, current); + var found = resolved.GetMembers(provider.ResolveContext, m => m.EntityType == EntityType.Method && m.Name == result.Name.Name); + if (found.FirstOrDefault() != null) { + result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name)); + } + } + } + + void CreateImplementsClausesForEvent(EventDeclaration result) + { + if (!types.Any()) return; + var current = types.Peek(); + if (current.ClassType == ClassType.Interface) + return; + + foreach (var type in current.ImplementsTypes) { + var resolved = provider.ResolveType(type, current); + var found = resolved.GetMembers(provider.ResolveContext, m => m.EntityType == EntityType.Event && m.Name == result.Name.Name); + if (found.FirstOrDefault() != null) { + result.ImplementsClause.Add(new InterfaceMemberSpecifier((AstType)type.Clone(), found.FirstOrDefault().Name)); + } + } + } + + string ConvertAlias(CSharp.AstNodeCollection arguments) + { + var pattern = new CSharp.AssignmentExpression() { + Left = new CSharp.IdentifierExpression("EntryPoint"), + Operator = CSharp.AssignmentOperatorType.Assign, + Right = new AnyNode("alias") + }; + + var result = arguments + .Select(expr => pattern.Match(expr)) + .FirstOrDefault(r => r.Success); + + if (result.Success && result.Has("alias")) { + return result.Get("alias") + .First().Value.ToString(); + } + + return null; + } + + CharsetModifier ConvertCharset(CSharp.AstNodeCollection arguments) + { + var pattern = new CSharp.AssignmentExpression() { + Left = new CSharp.IdentifierExpression("CharSet"), + Operator = CSharp.AssignmentOperatorType.Assign, + Right = new NamedNode( + "modifier", + new CSharp.MemberReferenceExpression() { + Target = new CSharp.IdentifierExpression("CharSet") + }) + }; + + var result = arguments + .Select(expr => pattern.Match(expr)) + .FirstOrDefault(r => r.Success); + + if (result.Success && result.Has("modifier")) { + switch (result.Get("modifier").First().MemberName) { + case "Auto": + return CharsetModifier.Auto; + case "Ansi": + return CharsetModifier.Ansi; + case "Unicode": + return CharsetModifier.Unicode; + } + } + + return CharsetModifier.None; + } + + bool IsSub(CSharp.AstType returnType) + { + var t = returnType as CSharp.PrimitiveType; + return t != null && t.Keyword == "void"; + } + + public AstNode VisitOperatorDeclaration(CSharp.OperatorDeclaration operatorDeclaration, object data) + { + MemberDeclaration result; + members.Push(new MemberInfo()); + + if (types.Any() && types.Peek().ClassType == ClassType.Module) + operatorDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + + if (operatorDeclaration.OperatorType == CSharp.OperatorType.Increment || operatorDeclaration.OperatorType == CSharp.OperatorType.Decrement) { + var m = new MethodDeclaration(); + result = m; + + ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), m.Attributes); + ConvertNodes(operatorDeclaration.ModifierTokens, m.ModifierTokens); + m.Name = operatorDeclaration.OperatorType == CSharp.OperatorType.Increment ? "op_Increment" : "op_Decrement"; + ConvertNodes(operatorDeclaration.Parameters, m.Parameters); + ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), m.ReturnTypeAttributes); + m.ReturnType = (AstType)operatorDeclaration.ReturnType.AcceptVisitor(this, data); + m.Body = (BlockStatement)operatorDeclaration.Body.AcceptVisitor(this, data); + } else { + var op = new OperatorDeclaration(); + result = op; + + ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), op.Attributes); + ConvertNodes(operatorDeclaration.ModifierTokens, op.ModifierTokens); + switch (operatorDeclaration.OperatorType) { + case ICSharpCode.NRefactory.CSharp.OperatorType.LogicalNot: + case ICSharpCode.NRefactory.CSharp.OperatorType.OnesComplement: + op.Operator = OverloadableOperatorType.Not; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.True: + op.Operator = OverloadableOperatorType.IsTrue; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.False: + op.Operator = OverloadableOperatorType.IsFalse; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Implicit: + op.Modifiers |= Modifiers.Widening; + op.Operator = OverloadableOperatorType.CType; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Explicit: + op.Modifiers |= Modifiers.Narrowing; + op.Operator = OverloadableOperatorType.CType; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Addition: + op.Operator = OverloadableOperatorType.Add; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Subtraction: + op.Operator = OverloadableOperatorType.Subtract; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.UnaryPlus: + op.Operator = OverloadableOperatorType.UnaryPlus; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.UnaryNegation: + op.Operator = OverloadableOperatorType.UnaryMinus; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Multiply: + op.Operator = OverloadableOperatorType.Multiply; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Division: + op.Operator = OverloadableOperatorType.Divide; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Modulus: + op.Operator = OverloadableOperatorType.Modulus; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.BitwiseAnd: + op.Operator = OverloadableOperatorType.BitwiseAnd; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.BitwiseOr: + op.Operator = OverloadableOperatorType.BitwiseOr; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.ExclusiveOr: + op.Operator = OverloadableOperatorType.ExclusiveOr; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.LeftShift: + op.Operator = OverloadableOperatorType.ShiftLeft; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.RightShift: + op.Operator = OverloadableOperatorType.ShiftRight; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Equality: + op.Operator = OverloadableOperatorType.Equality; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.Inequality: + op.Operator = OverloadableOperatorType.InEquality; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.GreaterThan: + op.Operator = OverloadableOperatorType.GreaterThan; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.LessThan: + op.Operator = OverloadableOperatorType.LessThan; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.GreaterThanOrEqual: + op.Operator = OverloadableOperatorType.GreaterThanOrEqual; + break; + case ICSharpCode.NRefactory.CSharp.OperatorType.LessThanOrEqual: + op.Operator = OverloadableOperatorType.LessThanOrEqual; + break; + default: + throw new Exception("Invalid value for OperatorType"); + } + ConvertNodes(operatorDeclaration.Parameters, op.Parameters); + ConvertNodes(operatorDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), op.ReturnTypeAttributes); + op.ReturnType = (AstType)operatorDeclaration.ReturnType.AcceptVisitor(this, data); + op.Body = (BlockStatement)operatorDeclaration.Body.AcceptVisitor(this, data); + } + + members.Pop(); + + return EndNode(operatorDeclaration, result); + + } + + public AstNode VisitParameterDeclaration(CSharp.ParameterDeclaration parameterDeclaration, object data) + { + var param = new ParameterDeclaration(); + + ConvertNodes(parameterDeclaration.Attributes, param.Attributes); + param.Modifiers = ConvertParamModifiers(parameterDeclaration.ParameterModifier); + if ((param.Modifiers & Modifiers.None) == Modifiers.None) + param.Modifiers = Modifiers.ByVal; + if ((parameterDeclaration.ParameterModifier & ICSharpCode.NRefactory.CSharp.ParameterModifier.Out) == ICSharpCode.NRefactory.CSharp.ParameterModifier.Out) { + AttributeBlock block = new AttributeBlock(); + block.Attributes.Add(new Ast.Attribute() { Type = new SimpleType("System.Runtime.InteropServices.OutAttribute") }); + param.Attributes.Add(block); + } + param.Name = new Identifier(parameterDeclaration.Name, TextLocation.Empty); + param.Type = (AstType)parameterDeclaration.Type.AcceptVisitor(this, data); + param.OptionalValue = (Expression)parameterDeclaration.DefaultExpression.AcceptVisitor(this, data); + if (!param.OptionalValue.IsNull) + param.Modifiers |= Modifiers.Optional; + + return EndNode(parameterDeclaration, param); + } + + Modifiers ConvertParamModifiers(CSharp.ParameterModifier mods) + { + switch (mods) { + case ICSharpCode.NRefactory.CSharp.ParameterModifier.None: + case ICSharpCode.NRefactory.CSharp.ParameterModifier.This: + return Modifiers.None; + case ICSharpCode.NRefactory.CSharp.ParameterModifier.Ref: + return Modifiers.ByRef; + case ICSharpCode.NRefactory.CSharp.ParameterModifier.Out: + return Modifiers.ByRef; + case ICSharpCode.NRefactory.CSharp.ParameterModifier.Params: + return Modifiers.ParamArray; + default: + throw new Exception("Invalid value for ParameterModifier"); + } + } + + public AstNode VisitPropertyDeclaration(CSharp.PropertyDeclaration propertyDeclaration, object data) + { + var decl = new PropertyDeclaration(); + + members.Push(new MemberInfo()); + + if (types.Any() && types.Peek().ClassType == ClassType.Module) + propertyDeclaration.Modifiers &= ~CSharp.Modifiers.Static; + + ConvertNodes(propertyDeclaration.Attributes.Where(section => section.AttributeTarget != "return"), decl.Attributes); + decl.Getter = (Accessor)propertyDeclaration.Getter.AcceptVisitor(this, data); + decl.Modifiers = ConvertModifiers(propertyDeclaration.Modifiers, propertyDeclaration); + decl.Name = new Identifier(propertyDeclaration.Name, TextLocation.Empty); + ConvertNodes(propertyDeclaration.Attributes.Where(section => section.AttributeTarget == "return"), decl.ReturnTypeAttributes); + if (!propertyDeclaration.PrivateImplementationType.IsNull) + decl.ImplementsClause.Add( + new InterfaceMemberSpecifier((AstType)propertyDeclaration.PrivateImplementationType.AcceptVisitor(this, data), + propertyDeclaration.Name)); + decl.ReturnType = (AstType)propertyDeclaration.ReturnType.AcceptVisitor(this, data); + decl.Setter = (Accessor)propertyDeclaration.Setter.AcceptVisitor(this, data); + + if (!decl.Setter.IsNull) { + decl.Setter.Parameters.Add(new ParameterDeclaration() { + Name = new Identifier("value", TextLocation.Empty), + Type = (AstType)propertyDeclaration.ReturnType.AcceptVisitor(this, data), + }); + } + + if (members.Pop().inIterator) { + decl.Modifiers |= Modifiers.Iterator; + } + + return EndNode(propertyDeclaration, decl); + } + + public AstNode VisitVariableInitializer(CSharp.VariableInitializer variableInitializer, object data) + { + var decl = new VariableDeclaratorWithTypeAndInitializer(); + + // look for type in parent + decl.Type = (AstType)variableInitializer.Parent + .GetChildByRole(CSharp.VariableInitializer.Roles.Type) + .AcceptVisitor(this, data); + decl.Identifiers.Add(new VariableIdentifier() { Name = variableInitializer.Name }); + decl.Initializer = (Expression)variableInitializer.Initializer.AcceptVisitor(this, data); + + return EndNode(variableInitializer, decl); + } + + public AstNode VisitFixedFieldDeclaration(CSharp.FixedFieldDeclaration fixedFieldDeclaration, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitFixedVariableInitializer(CSharp.FixedVariableInitializer fixedVariableInitializer, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitCompilationUnit(CSharp.CompilationUnit compilationUnit, object data) + { + var unit = new CompilationUnit(); + + foreach (var node in compilationUnit.Children) + unit.AddChild(node.AcceptVisitor(this, null), CompilationUnit.MemberRole); + + return EndNode(compilationUnit, unit); + } + + public AstNode VisitSimpleType(CSharp.SimpleType simpleType, object data) + { + var type = new SimpleType(simpleType.Identifier); + ConvertNodes(simpleType.TypeArguments, type.TypeArguments); + + return EndNode(simpleType, type); + } + + public AstNode VisitMemberType(CSharp.MemberType memberType, object data) + { + AstType target = null; + + if (memberType.Target is CSharp.SimpleType && ((CSharp.SimpleType)(memberType.Target)).Identifier.Equals("global", StringComparison.Ordinal)) + target = new PrimitiveType("Global"); + else + target = (AstType)memberType.Target.AcceptVisitor(this, data); + + var type = new QualifiedType(target, new Identifier(memberType.MemberName, TextLocation.Empty)); + ConvertNodes(memberType.TypeArguments, type.TypeArguments); + + return EndNode(memberType, type); + } + + public AstNode VisitComposedType(CSharp.ComposedType composedType, object data) + { + AstType type = new ComposedType(); + + ConvertNodes(composedType.ArraySpecifiers, ((ComposedType)type).ArraySpecifiers); + ((ComposedType)type).BaseType = (AstType)composedType.BaseType.AcceptVisitor(this, data); + ((ComposedType)type).HasNullableSpecifier = composedType.HasNullableSpecifier; + + for (int i = 0; i < composedType.PointerRank; i++) { + var tmp = new SimpleType() { Identifier = "__Pointer" }; + tmp.TypeArguments.Add(type); + type = tmp; + } + + return EndNode(composedType, type); + } + + public AstNode VisitArraySpecifier(CSharp.ArraySpecifier arraySpecifier, object data) + { + return EndNode(arraySpecifier, new ArraySpecifier(arraySpecifier.Dimensions)); + } + + public AstNode VisitPrimitiveType(CSharp.PrimitiveType primitiveType, object data) + { + string typeName; + + switch (primitiveType.Keyword) { + case "object": + typeName = "Object"; + break; + case "bool": + typeName = "Boolean"; + break; + case "char": + typeName = "Char"; + break; + case "sbyte": + typeName = "SByte"; + break; + case "byte": + typeName = "Byte"; + break; + case "short": + typeName = "Short"; + break; + case "ushort": + typeName = "UShort"; + break; + case "int": + typeName = "Integer"; + break; + case "uint": + typeName = "UInteger"; + break; + case "long": + typeName = "Long"; + break; + case "ulong": + typeName = "ULong"; + break; + case "float": + typeName = "Single"; + break; + case "double": + typeName = "Double"; + break; + case "decimal": + typeName = "Decimal"; + break; + case "string": + typeName = "String"; + break; + // generic constraints + case "new": + typeName = "New"; + break; + case "struct": + typeName = "Structure"; + break; + case "class": + typeName = "Class"; + break; + case "void": + typeName = "Void"; + break; + default: + typeName = "unknown"; + break; + } + + return EndNode(primitiveType, new PrimitiveType(typeName)); + } + + public AstNode VisitComment(CSharp.Comment comment, object data) + { + var c = new Comment(comment.Content, comment.CommentType == CSharp.CommentType.Documentation); + + if (comment.CommentType == CSharp.CommentType.MultiLine) + throw new NotImplementedException(); + + return EndNode(comment, c); + } + + public AstNode VisitTypeParameterDeclaration(CSharp.TypeParameterDeclaration typeParameterDeclaration, object data) + { + var param = new TypeParameterDeclaration() { + Variance = typeParameterDeclaration.Variance, + Name = typeParameterDeclaration.Name + }; + + var constraint = typeParameterDeclaration.Parent + .GetChildrenByRole(CSharp.AstNode.Roles.Constraint) + .SingleOrDefault(c => c.TypeParameter == typeParameterDeclaration.Name); + + if (constraint != null) + ConvertNodes(constraint.BaseTypes, param.Constraints); + + // TODO : typeParameterDeclaration.Attributes get lost? + //ConvertNodes(typeParameterDeclaration.Attributes + + return EndNode(typeParameterDeclaration, param); + } + + public AstNode VisitConstraint(CSharp.Constraint constraint, object data) + { + throw new NotImplementedException(); + } + + public AstNode VisitCSharpTokenNode(CSharp.CSharpTokenNode cSharpTokenNode, object data) + { + var mod = cSharpTokenNode as CSharp.CSharpModifierToken; + if (mod != null) { + var convertedModifiers = ConvertModifiers(mod.Modifier, mod.Parent); + VBModifierToken token = null; + if (convertedModifiers != Modifiers.None) { + token = new VBModifierToken(TextLocation.Empty, convertedModifiers); + return EndNode(cSharpTokenNode, token); + } + return EndNode(cSharpTokenNode, token); + } else { + throw new NotSupportedException("Should never visit individual tokens"); + } + } + + Modifiers ConvertModifiers(CSharp.Modifiers modifier, CSharp.AstNode container) + { + if ((modifier & CSharp.Modifiers.Any) == CSharp.Modifiers.Any) + return Modifiers.Any; + + var mod = Modifiers.None; + + if ((modifier & CSharp.Modifiers.Const) == CSharp.Modifiers.Const) + mod |= Modifiers.Const; + if ((modifier & CSharp.Modifiers.Abstract) == CSharp.Modifiers.Abstract) { + if (container is CSharp.TypeDeclaration) + mod |= Modifiers.MustInherit; + else + mod |= Modifiers.MustOverride; + } + if ((modifier & CSharp.Modifiers.Static) == CSharp.Modifiers.Static) + mod |= Modifiers.Shared; + + if ((modifier & CSharp.Modifiers.Public) == CSharp.Modifiers.Public) + mod |= Modifiers.Public; + if ((modifier & CSharp.Modifiers.Protected) == CSharp.Modifiers.Protected) + mod |= Modifiers.Protected; + if ((modifier & CSharp.Modifiers.Internal) == CSharp.Modifiers.Internal) + mod |= Modifiers.Friend; + if ((modifier & CSharp.Modifiers.Private) == CSharp.Modifiers.Private) + mod |= Modifiers.Private; + if (container is CSharp.IndexerDeclaration) + mod |= Modifiers.Default; + bool writeable = IsWriteableProperty(container); + bool readable = IsReadableProperty(container); + if (writeable && !readable) + mod |= Modifiers.WriteOnly; + if (readable && !writeable) + mod |= Modifiers.ReadOnly; + + + return mod; + } + + bool IsReadableProperty(ICSharpCode.NRefactory.CSharp.AstNode container) + { + if (container is CSharp.IndexerDeclaration) { + var i = container as CSharp.IndexerDeclaration; + return !i.Getter.IsNull; + } + + if (container is CSharp.PropertyDeclaration) { + var p = container as CSharp.PropertyDeclaration; + return !p.Getter.IsNull; + } + + return false; + } + + bool IsWriteableProperty(ICSharpCode.NRefactory.CSharp.AstNode container) + { + if (container is CSharp.IndexerDeclaration) { + var i = container as CSharp.IndexerDeclaration; + return !i.Setter.IsNull; + } + + if (container is CSharp.PropertyDeclaration) { + var p = container as CSharp.PropertyDeclaration; + return !p.Setter.IsNull; + } + + return false; + } + + public AstNode VisitIdentifier(CSharp.Identifier identifier, object data) + { + var ident = new Identifier(identifier.Name, identifier.StartLocation); + + return EndNode(identifier, ident); + } + + public AstNode VisitPatternPlaceholder(CSharp.AstNode placeholder, ICSharpCode.NRefactory.PatternMatching.Pattern pattern, object data) + { + throw new NotImplementedException(); + } + + void ConvertNodes(IEnumerable nodes, VB.AstNodeCollection result) where T : VB.AstNode + { + foreach (var node in nodes) { + T n = (T)node.AcceptVisitor(this, null); + if (n != null) + result.Add(n); + } + } + + T EndNode(CSharp.AstNode node, T result) where T : VB.AstNode + { + if (result != null) { + CopyAnnotations(node, result); + } + + return result; + } + + void CopyAnnotations(CSharp.AstNode node, T result) where T : VB.AstNode + { + foreach (var ann in node.Annotations) + result.AddAnnotation(ann); + } + + bool HasAttribute(CSharp.AstNodeCollection attributes, string name, out CSharp.Attribute foundAttribute) + { + foreach (var attr in attributes.SelectMany(a => a.Attributes)) { + if (provider.GetTypeNameForAttribute(attr) == name) { + foundAttribute = attr; + return true; + } + } + foundAttribute = null; + return false; + } + } +} diff --git a/ICSharpCode.NRefactory.snk b/ICSharpCode.NRefactory.snk new file mode 100644 index 0000000000000000000000000000000000000000..c07767c3cfaa3816d01fa69e33ce039c6a208f16 GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa50096^&pCO-=>qSh-63P3IdC4;f-Y|nG}m`G zDQdg9d+>lTgU_-NdrwqGq8E5CTzq3spW*yqw80%>#k12jMFVFBDQz*3J>2(Dhh4LZ zios3=2?u@CELj5GtTdOJ&HbrO|Zdf z+{#hizS<$8FY$@`qwWHWyPKT8*Ig-vg^R9j8YP1CUd{1Cmb~t26G-?pA4)XYP?c-! ieu4UE7{na^>dNh#i9x~BEL_PgB4dHwc}sKdSZ)dh(;oo< literal 0 HcmV?d00001 diff --git a/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs b/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs deleted file mode 100644 index 2d0a5a796..000000000 --- a/ICSharpCode.NRefactory/CSharp/Ast/AstLocation.cs +++ /dev/null @@ -1,137 +0,0 @@ -// -// DomLocation.cs -// -// Author: -// Mike Krüger -// -// Copyright (C) 2008 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining -// a copy of this software and associated documentation files (the -// "Software"), to deal in the Software without restriction, including -// without limitation the rights to use, copy, modify, merge, publish, -// distribute, sublicense, and/or sell copies of the Software, and to -// permit persons to whom the Software is furnished to do so, subject to -// the following conditions: -// -// The above copyright notice and this permission notice shall be -// included in all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF -// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION -// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION -// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -// - -using System; - -namespace ICSharpCode.NRefactory.CSharp -{ - [Serializable] - public struct AstLocation : IComparable, IEquatable - { - public static readonly AstLocation Empty = new AstLocation(0, 0); - - readonly int line, column; - - public AstLocation (int line, int column) - { - this.line = line; - this.column = column; - } - - public bool IsEmpty { - get { - return line <= 0; - } - } - - public int Line { - get { return line; } - } - - public int Column { - get { return column; } - } - - public override bool Equals (object obj) - { - if (!(obj is AstLocation)) - return false; - return (AstLocation)obj == this; - } - - public override int GetHashCode () - { - unchecked { - return line + column * 5000; - } - } - - public bool Equals (AstLocation other) - { - return other == this; - } - - public int CompareTo (AstLocation other) - { - if (this == other) - return 0; - if (this < other) - return -1; - return 1; - } - - public override string ToString () - { - return String.Format ("(Line {0}, Column {1})", Line, Column); - } - - public static AstLocation FromInvariantString (string invariantString) - { - if (string.Equals(invariantString, "EMPTY", StringComparison.OrdinalIgnoreCase)) - return AstLocation.Empty; - string[] splits = invariantString.Split (',', '/'); - if (splits.Length == 2) - return new AstLocation (Int32.Parse (splits[0]), Int32.Parse (splits[1])); - return AstLocation.Empty; - } - - public string ToInvariantString () - { - if (IsEmpty) - return "Empty"; - return String.Format ("{0}/{1}", line, column); - } - - public static bool operator==(AstLocation left, AstLocation right) - { - return left.line == right.line && left.column == right.column; - } - - public static bool operator!=(AstLocation left, AstLocation right) - { - return left.line != right.line || left.column != right.column; - } - - public static bool operator<(AstLocation left, AstLocation right) - { - return left.line < right.line || left.line == right.line && left.column < right.column; - } - public static bool operator>(AstLocation left, AstLocation right) - { - return left.line > right.line || left.line == right.line && left.column > right.column; - } - public static bool operator<=(AstLocation left, AstLocation right) - { - return !(left > right); - } - public static bool operator>=(AstLocation left, AstLocation right) - { - return !(left < right); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs b/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs deleted file mode 100644 index 4568f8736..000000000 --- a/ICSharpCode.NRefactory/CSharp/Formatter/ITextEditorAdapter.cs +++ /dev/null @@ -1,83 +0,0 @@ -// -// ITextEditorAdapter.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2011 Novell, Inc (http://www.novell.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. -using System; -using System.Collections.Generic; - -namespace ICSharpCode.NRefactory -{ - public interface ITextEditorAdapter - { - bool TabsToSpaces { get; } - - int TabSize { get; } - - string EolMarker { get; } - - string Text { get; } - - int Length { get; } - - int LocationToOffset (int line, int col); - char GetCharAt (int offset); - string GetTextAt (int offset, int length); - - int LineCount { get; } - - int GetEditableLength (int lineNumber); - string GetIndentation (int lineNumber); - int GetLineOffset (int lineNumber); - int GetLineLength (int lineNumber); - int GetLineEndOffset (int lineNumber); - - void Replace (int offset, int count, string text); - } - - /* - public static class ITextEditorAdapterHelperMethods - { - public static void AcceptChanges (this ITextEditorAdapter adapter, List changes) - { - for (int i = 0; i < changes.Count; i++) { - changes [i].PerformChange (adapter); - var replaceChange = changes [i]; - for (int j = i + 1; j < changes.Count; j++) { - var change = changes [j]; - if (replaceChange.Offset >= 0 && change.Offset >= 0) { - if (replaceChange.Offset < change.Offset) { - change.Offset -= replaceChange.RemovedChars; - if (!string.IsNullOrEmpty (replaceChange.InsertedText)) - change.Offset += replaceChange.InsertedText.Length; - } else if (replaceChange.Offset < change.Offset + change.RemovedChars) { - change.RemovedChars -= replaceChange.RemovedChars; - change.Offset = replaceChange.Offset + (!string.IsNullOrEmpty (replaceChange.InsertedText) ? replaceChange.InsertedText.Length : 0); - } - } - } - } - } - }*/ -} - diff --git a/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs b/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs deleted file mode 100644 index ac1966296..000000000 --- a/ICSharpCode.NRefactory/CSharp/OutputVisitor/IOutputFormatter.cs +++ /dev/null @@ -1,44 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.NRefactory.CSharp -{ - /// - /// Output formatter for the Output visitor. - /// - public interface IOutputFormatter - { - void StartNode(AstNode node); - void EndNode(AstNode node); - - /// - /// Writes an identifier. - /// If the identifier conflicts with a keyword, the output visitor will - /// call WriteToken("@") before calling WriteIdentifier(). - /// - void WriteIdentifier(string identifier); - - /// - /// Writes a keyword to the output. - /// - void WriteKeyword(string keyword); - - /// - /// Writes a token to the output. - /// - void WriteToken(string token); - void Space(); - - void OpenBrace(BraceStyle style); - void CloseBrace(BraceStyle style); - - void Indent(); - void Unindent(); - - void NewLine(); - - void WriteComment(CommentType commentType, string content); - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs b/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs deleted file mode 100644 index 63830b47a..000000000 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/StringBuilderOutputFormatter.cs +++ /dev/null @@ -1,158 +0,0 @@ -// -// StringBuilderOutputFormatter.cs -// -// Author: -// Mike Krüger -// -// Copyright (c) 2011 Mike Krüger -// -// 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.Text; - -namespace ICSharpCode.NRefactory.CSharp.Refactoring -{ - public class StringBuilderOutputFormatter : IOutputFormatter - { - readonly StringBuilder sb = new StringBuilder (); - int indentation; - bool needsIndent = true; - - public int Length { - get { - WriteIndentation (); - return sb.Length; - } - } - - public int Indentation { - get { - return this.indentation; - } - set { - indentation = value; - } - } - - public string EolMarker { - get; - set; - } - - public override string ToString () - { - return sb.ToString (); - } - - public void WriteIdentifier (string ident) - { - WriteIndentation (); - sb.Append (ident); - } - - public void WriteKeyword (string keyword) - { - WriteIndentation (); - sb.Append (keyword); - } - - public void WriteToken (string token) - { - WriteIndentation (); - sb.Append (token); - } - - public void Space () - { - WriteIndentation (); - sb.Append (' '); - } - - public void OpenBrace (BraceStyle style) - { - WriteIndentation (); - sb.Append (' '); - sb.Append ('{'); - Indent (); - NewLine (); - } - - public void CloseBrace (BraceStyle style) - { - Unindent (); - WriteIndentation (); - sb.Append ('}'); - } - - void WriteIndentation () - { - if (needsIndent) { - needsIndent = false; - for (int i = 0; i < indentation; i++) { - sb.Append ('\t'); - } - } - } - - public void NewLine () - { - sb.Append (EolMarker); - needsIndent = true; - } - - public void Indent () - { - indentation++; - } - - public void Unindent () - { - indentation--; - } - - public void WriteComment (CommentType commentType, string content) - { - WriteIndentation (); - switch (commentType) { - case CommentType.SingleLine: - sb.Append ("//"); - sb.AppendLine (content); - break; - case CommentType.MultiLine: - sb.Append ("/*"); - sb.Append (content); - sb.Append ("*/"); - break; - case CommentType.Documentation: - sb.Append ("///"); - sb.AppendLine (content); - break; - } - } - - public virtual void StartNode (AstNode node) - { - } - - public virtual void EndNode (AstNode node) - { - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs b/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs deleted file mode 100644 index 6bd0c9830..000000000 --- a/ICSharpCode.NRefactory/CSharp/Refactoring/TypeSystemAstBuilder.cs +++ /dev/null @@ -1,218 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Diagnostics; - -using ICSharpCode.NRefactory.CSharp.Resolver; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; - -namespace ICSharpCode.NRefactory.CSharp.Refactoring -{ - /// - /// Converts from type system to the C# AST. - /// - public class TypeSystemAstBuilder - { - readonly CSharpResolver resolver; - - /// - /// Creates a new TypeSystemAstBuilder. - /// - /// - /// A resolver initialized for the position where the type will be inserted. - /// - public TypeSystemAstBuilder(CSharpResolver resolver = null) - { - this.resolver = resolver; - } - - public AstType ConvertType(IType type) - { - if (type == null) - throw new ArgumentNullException("type"); - TypeWithElementType typeWithElementType = type as TypeWithElementType; - if (typeWithElementType != null) { - if (typeWithElementType is PointerType) { - return ConvertType(typeWithElementType.ElementType).MakePointerType(); - } else if (typeWithElementType is ArrayType) { - return ConvertType(typeWithElementType.ElementType).MakeArrayType(((ArrayType)type).Dimensions); - } else { - // e.g. ByReferenceType; not supported as type in C# - return ConvertType(typeWithElementType.ElementType); - } - } - ParameterizedType pt = type as ParameterizedType; - if (pt != null) { - if (pt.Name == "Nullable" && pt.Namespace == "System" && pt.TypeParameterCount == 1) { - return ConvertType(pt.TypeArguments[0]).MakeNullableType(); - } - return ConvertTypeDefinition(pt.GetDefinition(), pt.TypeArguments); - } - ITypeDefinition typeDef = type as ITypeDefinition; - if (typeDef != null) { - if (typeDef.TypeParameterCount > 0) { - // Create an unbound type - IType[] typeArguments = new IType[typeDef.TypeParameterCount]; - for (int i = 0; i < typeArguments.Length; i++) { - typeArguments[i] = SharedTypes.UnknownType; - } - return ConvertTypeDefinition(typeDef, typeArguments); - } else { - return ConvertTypeDefinition(typeDef, EmptyList.Instance); - } - } - return new SimpleType(type.Name); - } - - AstType ConvertTypeDefinition(ITypeDefinition typeDef, IList typeArguments) - { - Debug.Assert(typeArguments.Count >= typeDef.TypeParameterCount); - switch (ReflectionHelper.GetTypeCode(typeDef)) { - case TypeCode.Object: - return new PrimitiveType("object"); - case TypeCode.Boolean: - return new PrimitiveType("bool"); - case TypeCode.Char: - return new PrimitiveType("char"); - case TypeCode.SByte: - return new PrimitiveType("sbyte"); - case TypeCode.Byte: - return new PrimitiveType("byte"); - case TypeCode.Int16: - return new PrimitiveType("short"); - case TypeCode.UInt16: - return new PrimitiveType("ushort"); - case TypeCode.Int32: - return new PrimitiveType("int"); - case TypeCode.UInt32: - return new PrimitiveType("uint"); - case TypeCode.Int64: - return new PrimitiveType("long"); - case TypeCode.UInt64: - return new PrimitiveType("ulong"); - case TypeCode.Single: - return new PrimitiveType("float"); - case TypeCode.Double: - return new PrimitiveType("double"); - case TypeCode.Decimal: - return new PrimitiveType("decimal"); - case TypeCode.String: - return new PrimitiveType("string"); - } - // There is no type code for System.Void - if (typeDef != null && typeDef.Namespace == "System" && typeDef.Name == "Void" && typeDef.TypeParameterCount == 0) - return new PrimitiveType("void"); - if (resolver != null && TypeArgumentsTrivial(typeArguments, OuterTypeParameterCount(typeDef))) { - TypeResolveResult trr = resolver.ResolveSimpleName(typeDef.Name, typeArguments) as TypeResolveResult; - if (trr != null && !trr.IsError && trr.Type.GetDefinition() == typeDef) { - // We can use the short type name - SimpleType shortResult = new SimpleType(typeDef.Name); - AddTypeArguments(shortResult, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount); - return shortResult; - } - } - - MemberType result = new MemberType(); - if (typeDef.DeclaringTypeDefinition != null) { - // Handle nested types - result.Target = ConvertTypeDefinition(typeDef.DeclaringTypeDefinition, typeArguments); - } else { - // Handle top-level types - if (string.IsNullOrEmpty(typeDef.Namespace)) { - result.Target = new SimpleType("global"); - result.IsDoubleColon = true; - } else { - result.Target = ConvertNamespace(typeDef.Namespace); - } - } - result.MemberName = typeDef.Name; - AddTypeArguments(result, typeArguments, OuterTypeParameterCount(typeDef), typeDef.TypeParameterCount); - return result; - } - - /// - /// Gets the number of type parameters belonging to outer classes. - /// - int OuterTypeParameterCount(ITypeDefinition typeDef) - { - if (typeDef.DeclaringType != null) - return typeDef.DeclaringType.TypeParameterCount; - else - return 0; - } - - /// - /// Gets whether the first type arguments are trivial, - /// that is, they point to a type parameter with the same index. - /// - bool TypeArgumentsTrivial(IList typeArguments, int num) - { - for (int i = 0; i < num; i++) { - ITypeParameter tp = typeArguments[i] as ITypeParameter; - if (!(tp != null && tp.OwnerType == EntityType.TypeDefinition && tp.Index == i)) - return false; - } - return true; - } - - /// - /// Adds type arguments to the result type. - /// - /// The result AST node (a SimpleType or MemberType) - /// The list of type arguments - /// Index of first type argument to add - /// Index after last type argument to add - void AddTypeArguments(AstType result, IList typeArguments, int startIndex, int endIndex) - { - for (int i = startIndex; i < endIndex; i++) { - result.AddChild(ConvertType(typeArguments[i]), AstType.Roles.TypeArgument); - } - } - - AstType ConvertNamespace(string ns) - { - if (resolver != null) { - // Look if there's an alias to the target namespace - for (UsingScope usingScope = resolver.UsingScope; usingScope != null; usingScope = usingScope.Parent) { - foreach (var pair in usingScope.UsingAliases) { - // maybe add some caching? we're resolving all aliases N times when converting a namespace name with N parts - NamespaceResolveResult nrr = pair.Value.ResolveNamespace(resolver.Context); - if (nrr != null && nrr.NamespaceName == ns) - return new SimpleType(pair.Key); - } - } - } - - int pos = ns.LastIndexOf('.'); - if (pos < 0) { - if (IsValidNamespace(ns)) { - return new SimpleType(ns); - } else { - return new MemberType { - Target = new SimpleType("global"), - IsDoubleColon = true, - MemberName = ns - }; - } - } else { - string parentNamespace = ns.Substring(0, pos); - string localNamespace = ns.Substring(pos + 1); - return new MemberType { - Target = ConvertNamespace(parentNamespace), - MemberName = localNamespace - }; - } - } - - bool IsValidNamespace(string firstNamespacePart) - { - if (resolver == null) - return true; // just assume namespaces are valid if we don't have a resolver - NamespaceResolveResult nrr = resolver.ResolveSimpleName(firstNamespacePart, EmptyList.Instance) as NamespaceResolveResult; - return nrr != null && !nrr.IsError && nrr.NamespaceName == firstNamespacePart; - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs deleted file mode 100644 index 49acbf90d..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/AliasNamespaceReference.cs +++ /dev/null @@ -1,51 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Looks up an alias (identifier in front of :: operator). - /// - /// - /// The member lookup performed by the :: operator is handled - /// by . - /// - public class AliasNamespaceReference : ITypeOrNamespaceReference - { - readonly UsingScope parentUsingScope; - readonly string identifier; - - public AliasNamespaceReference(string identifier, UsingScope parentUsingScope) - { - if (identifier == null) - throw new ArgumentNullException("identifier"); - this.identifier = identifier; - this.parentUsingScope = parentUsingScope; - } - - public ResolveResult DoResolve(ITypeResolveContext context) - { - CSharpResolver r = new CSharpResolver(context); - r.UsingScope = parentUsingScope; - return r.ResolveAlias(identifier); - } - - public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) - { - return DoResolve(context) as NamespaceResolveResult; - } - - public IType Resolve(ITypeResolveContext context) - { - return SharedTypes.UnknownType; - } - - public override string ToString() - { - return identifier + "::"; - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs deleted file mode 100644 index 3c17dd65f..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/AmbiguousResolveResult.cs +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents an ambiguous type resolve result. - /// - public class AmbiguousTypeResolveResult : TypeResolveResult - { - public AmbiguousTypeResolveResult(IType type) : base(type) - { - } - - public override bool IsError { - get { return true; } - } - } - - public class AmbiguousMemberResultResult : MemberResolveResult - { - public AmbiguousMemberResultResult(IMember member, IType returnType) : base(member, returnType) - { - } - - public override bool IsError { - get { return true; } - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ByReferenceResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ByReferenceResolveResult.cs deleted file mode 100644 index 2056fe4c3..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ByReferenceResolveResult.cs +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents the resolve result of an 'ref x' or 'out x' expression. - /// - public class ByReferenceResolveResult : ResolveResult - { - public bool IsOut { get; private set; } - public bool IsRef { get { return !IsOut;} } - - public ByReferenceResolveResult(IType elementType, bool isOut) - : base(new ByReferenceType(elementType)) - { - this.IsOut = isOut; - } - - public IType ElementType { - get { return ((ByReferenceType)this.Type).ElementType; } - } - - public override string ToString() - { - return string.Format("[{0} {1} {2}]", GetType().Name, IsOut ? "out" : "ref", ElementType); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ConstantResolveResult.cs deleted file mode 100644 index 32489a1d8..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ConstantResolveResult.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// ResolveResult representing a compile-time constant. - /// - public class ConstantResolveResult : ResolveResult - { - object constantValue; - - public ConstantResolveResult(IType type, object constantValue) : base(type) - { - this.constantValue = constantValue; - } - - public override bool IsCompileTimeConstant { - get { return true; } - } - - public override object ConstantValue { - get { return constantValue; } - } - - public override string ToString() - { - return string.Format("[{0} {1} = {2}]", GetType().Name, this.Type, constantValue); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs b/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs deleted file mode 100644 index 3109fb8f8..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/Conversions.cs +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Linq; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.Utils; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Contains logic that determines whether an implicit conversion exists between two types. - /// - public class Conversions : IConversions - { - readonly ITypeResolveContext context; - readonly IType objectType; - - public Conversions(ITypeResolveContext context) - { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; - this.objectType = KnownTypeReference.Object.Resolve(context); - this.dynamicErasure = new DynamicErasure(this); - } - - #region ImplicitConversion - public bool ImplicitConversion(ResolveResult resolveResult, IType toType) - { - if (resolveResult == null) - throw new ArgumentNullException("resolveResult"); - if (resolveResult.IsCompileTimeConstant) { - if (ImplicitEnumerationConversion(resolveResult, toType)) - return true; - if (ImplicitConstantExpressionConversion(resolveResult, toType)) - return true; - } - if (ImplicitConversion(resolveResult.Type, toType)) - return true; - // TODO: Anonymous function conversions - // TODO: Method group conversions - return false; - } - - public bool ImplicitConversion(IType fromType, IType toType) - { - if (fromType == null) - throw new ArgumentNullException("fromType"); - if (toType == null) - throw new ArgumentNullException("toType"); - // C# 4.0 spec: §6.1 - if (IdentityConversion(fromType, toType)) - return true; - if (ImplicitNumericConversion(fromType, toType)) - return true; - if (ImplicitNullableConversion(fromType, toType)) - return true; - if (NullLiteralConversion(fromType, toType)) - return true; - if (ImplicitReferenceConversion(fromType, toType)) - return true; - if (BoxingConversion(fromType, toType)) - return true; - if (ImplicitDynamicConversion(fromType, toType)) - return true; - if (ImplicitTypeParameterConversion(fromType, toType)) - return true; - if (ImplicitPointerConversion(fromType, toType)) - return true; - if (ImplicitUserDefinedConversion(fromType, toType)) - return true; - return false; - } - - public bool StandardImplicitConversion(IType fromType, IType toType) - { - if (fromType == null) - throw new ArgumentNullException("fromType"); - if (toType == null) - throw new ArgumentNullException("toType"); - // C# 4.0 spec: §6.3.1 - if (IdentityConversion(fromType, toType)) - return true; - if (ImplicitNumericConversion(fromType, toType)) - return true; - if (ImplicitNullableConversion(fromType, toType)) - return true; - if (ImplicitReferenceConversion(fromType, toType)) - return true; - if (ImplicitTypeParameterConversion(fromType, toType)) - return true; - if (BoxingConversion(fromType, toType)) - return true; - return false; - } - #endregion - - #region IdentityConversion - /// - /// Gets whether there is an identity conversion from to - /// - public bool IdentityConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §6.1.1 - return fromType.AcceptVisitor(dynamicErasure).Equals(toType.AcceptVisitor(dynamicErasure)); - } - - readonly DynamicErasure dynamicErasure; - - sealed class DynamicErasure : TypeVisitor - { - readonly IType objectType; - - public DynamicErasure(Conversions conversions) - { - this.objectType = conversions.objectType; - } - - public override IType VisitOtherType(IType type) - { - if (type == SharedTypes.Dynamic) - return objectType; - else - return base.VisitOtherType(type); - } - } - #endregion - - #region ImplicitNumericConversion - static readonly bool[,] implicitNumericConversionLookup = { - // to: short ushort int uint long ulong - // from: - /* char */ { false, true , true , true , true , true }, - /* sbyte */ { true , false, true , false, true , false }, - /* byte */ { true , true , true , true , true , true }, - /* short */ { false, false, true , false, true , false }, - /* ushort */ { false, false, true , true , true , true }, - /* int */ { false, false, false, false, true , false }, - /* uint */ { false, false, false, false, true , true }, - }; - - bool ImplicitNumericConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §6.1.2 - - TypeCode from = ReflectionHelper.GetTypeCode(fromType); - TypeCode to = ReflectionHelper.GetTypeCode(toType); - if (to >= TypeCode.Single && to <= TypeCode.Decimal) { - // Conversions to float/double/decimal exist from all integral types, - // and there's a conversion from float to double. - return from >= TypeCode.Char && from <= TypeCode.UInt64 - || from == TypeCode.Single && to == TypeCode.Double; - } else { - // Conversions to integral types: look at the table - return from >= TypeCode.Char && from <= TypeCode.UInt32 - && to >= TypeCode.Int16 && to <= TypeCode.UInt64 - && implicitNumericConversionLookup[from - TypeCode.Char, to - TypeCode.Int16]; - } - } - #endregion - - #region ImplicitEnumerationConversion - bool ImplicitEnumerationConversion(ResolveResult rr, IType toType) - { - // C# 4.0 spec: §6.1.3 - TypeCode constantType = ReflectionHelper.GetTypeCode(rr.Type); - if (constantType >= TypeCode.SByte && constantType <= TypeCode.Decimal && Convert.ToDouble(rr.ConstantValue) == 0) { - return NullableType.GetUnderlyingType(toType).IsEnum(); - } - return false; - } - #endregion - - #region ImplicitNullableConversion - bool ImplicitNullableConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §6.1.4 - if (NullableType.IsNullable(toType)) { - IType t = NullableType.GetUnderlyingType(toType); - IType s = NullableType.GetUnderlyingType(fromType); // might or might not be nullable - return IdentityConversion(s, t) || ImplicitNumericConversion(s, t); - } else { - return false; - } - } - #endregion - - #region NullLiteralConversion - bool NullLiteralConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §6.1.5 - return fromType == SharedTypes.Null && NullableType.IsNullable(toType); - // This function only handles the conversion from the null literal to nullable value types, - // reference types are handled by ImplicitReferenceConversion instead. - } - #endregion - - #region ImplicitReferenceConversion - public bool ImplicitReferenceConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §6.1.6 - - // reference conversions are possible only if both types are known to be reference types - if (!(fromType.IsReferenceType(context) == true && toType.IsReferenceType(context) == true)) - return false; - - // conversion from null literal is always possible - if (fromType == SharedTypes.Null) - return true; - - ArrayType fromArray = fromType as ArrayType; - if (fromArray != null) { - ArrayType toArray = toType as ArrayType; - if (toArray != null) { - // array covariance (the broken kind) - return fromArray.Dimensions == toArray.Dimensions - && ImplicitReferenceConversion(fromArray.ElementType, toArray.ElementType); - } - // conversion from single-dimensional array S[] to IList: - ParameterizedType toPT = toType as ParameterizedType; - if (fromArray.Dimensions == 1 && toPT != null && toPT.TypeArguments.Count == 1 - && toPT.Namespace == "System.Collections.Generic" - && (toPT.Name == "IList" || toPT.Name == "ICollection" || toPT.Name == "IEnumerable")) - { - // array covariance plays a part here as well (string[] is IList) - return IdentityConversion(fromArray.ElementType, toPT.TypeArguments[0]) - || ImplicitReferenceConversion(fromArray.ElementType, toPT.TypeArguments[0]); - } - // conversion from any array to System.Array and the interfaces it implements: - ITypeDefinition systemArray = context.GetTypeDefinition("System", "Array", 0, StringComparer.Ordinal); - return systemArray != null && (systemArray.Equals(toType) || ImplicitReferenceConversion(systemArray, toType)); - } - - // now comes the hard part: traverse the inheritance chain and figure out generics+variance - return IsSubtypeOf(fromType, toType); - } - - // Determines whether s is a subtype of t. - // Helper method used for ImplicitReferenceConversion, BoxingConversion and ImplicitTypeParameterConversion - bool IsSubtypeOf(IType s, IType t) - { - // conversion to dynamic + object are always possible - if (t == SharedTypes.Dynamic || t.Equals(objectType)) - return true; - - // let GetAllBaseTypes do the work for us - foreach (IType baseType in s.GetAllBaseTypes(context)) { - if (IdentityOrVarianceConversion(baseType, t)) - return true; - } - return false; - } - - bool IdentityOrVarianceConversion(IType s, IType t) - { - ITypeDefinition def = s.GetDefinition(); - if (def != null && def.Equals(t.GetDefinition())) { - ParameterizedType ps = s as ParameterizedType; - ParameterizedType pt = t as ParameterizedType; - if (ps != null && pt != null - && ps.TypeArguments.Count == pt.TypeArguments.Count - && ps.TypeArguments.Count == def.TypeParameters.Count) - { - // C# 4.0 spec: §13.1.3.2 Variance Conversion - for (int i = 0; i < def.TypeParameters.Count; i++) { - IType si = ps.TypeArguments[i]; - IType ti = pt.TypeArguments[i]; - if (IdentityConversion(si, ti)) - continue; - ITypeParameter xi = def.TypeParameters[i]; - switch (xi.Variance) { - case VarianceModifier.Covariant: - if (!ImplicitReferenceConversion(si, ti)) - return false; - break; - case VarianceModifier.Contravariant: - if (!ImplicitReferenceConversion(ti, si)) - return false; - break; - default: - return false; - } - } - } else if (ps != null || pt != null) { - return false; // only of of them is parameterized, or counts don't match? -> not valid conversion - } - return true; - } - return false; - } - #endregion - - #region BoxingConversion - bool BoxingConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §6.1.7 - fromType = NullableType.GetUnderlyingType(fromType); - return fromType.IsReferenceType(context) == false && toType.IsReferenceType(context) == true && IsSubtypeOf(fromType, toType); - } - #endregion - - #region ImplicitDynamicConversion - bool ImplicitDynamicConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §6.1.8 - return fromType == SharedTypes.Dynamic; - } - #endregion - - #region ImplicitConstantExpressionConversion - bool ImplicitConstantExpressionConversion(ResolveResult rr, IType toType) - { - // C# 4.0 spec: §6.1.9 - TypeCode fromTypeCode = ReflectionHelper.GetTypeCode(rr.Type); - TypeCode toTypeCode = ReflectionHelper.GetTypeCode(NullableType.GetUnderlyingType(toType)); - if (fromTypeCode == TypeCode.Int64) { - long val = (long)rr.ConstantValue; - return val >= 0 && toTypeCode == TypeCode.UInt64; - } else if (fromTypeCode == TypeCode.Int32) { - int val = (int)rr.ConstantValue; - switch (toTypeCode) { - case TypeCode.SByte: - return val >= SByte.MinValue && val <= SByte.MaxValue; - case TypeCode.Byte: - return val >= Byte.MinValue && val <= Byte.MaxValue; - case TypeCode.Int16: - return val >= Int16.MinValue && val <= Int16.MaxValue; - case TypeCode.UInt16: - return val >= UInt16.MinValue && val <= UInt16.MaxValue; - case TypeCode.UInt32: - return val >= 0; - case TypeCode.UInt64: - return val >= 0; - } - } - return false; - } - #endregion - - #region ImplicitTypeParameterConversion - /// - /// Implicit conversions involving type parameters. - /// - bool ImplicitTypeParameterConversion(IType fromType, IType toType) - { - ITypeParameter t = fromType as ITypeParameter; - if (t == null) - return false; // not a type parameter - if (t.IsReferenceType(context) == true) - return false; // already handled by ImplicitReferenceConversion - return IsSubtypeOf(t, toType); - } - #endregion - - #region ImplicitPointerConversion - bool ImplicitPointerConversion(IType fromType, IType toType) - { - // C# 4.0 spec: §18.4 Pointer conversions - if (fromType is PointerType && toType is PointerType && toType.ReflectionName == "System.Void*") - return true; - if (fromType == SharedTypes.Null && toType is PointerType) - return true; - return false; - } - #endregion - - #region ImplicitUserDefinedConversion - bool ImplicitUserDefinedConversion(IType fromType, IType toType) - { - // C# 4.0 spec §6.4.4 User-defined implicit conversions - // Currently we only test whether an applicable implicit conversion exists, - // we do not resolve which conversion is the most specific and gets used. - - // Find the candidate operators: - Predicate opImplicitFilter = m => m.IsStatic && m.IsOperator && m.Name == "op_Implicit" && m.Parameters.Count == 1; - var operators = NullableType.GetUnderlyingType(fromType).GetMethods(context, opImplicitFilter) - .Concat(NullableType.GetUnderlyingType(toType).GetMethods(context, opImplicitFilter)); - // Determine whether one of them is applicable: - foreach (IMethod op in operators) { - IType sourceType = op.Parameters[0].Type.Resolve(context); - IType targetType = op.ReturnType.Resolve(context); - // Try if the operator is applicable: - if (StandardImplicitConversion(fromType, sourceType) && StandardImplicitConversion(targetType, toType)) { - return true; - } - // Try if the operator is applicable in lifted form: - if (sourceType.IsReferenceType(context) == false && targetType.IsReferenceType(context) == false) { - IType liftedSourceType = NullableType.Create(sourceType, context); - IType liftedTargetType = NullableType.Create(targetType, context); - if (StandardImplicitConversion(fromType, liftedSourceType) && StandardImplicitConversion(liftedTargetType, toType)) { - return true; - } - } - } - return false; - } - #endregion - - #region BetterConversion - /// - /// Gets the better conversion (C# 4.0 spec, §7.5.3.3) - /// - /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better - public int BetterConversion(ResolveResult resolveResult, IType t1, IType t2) - { - // TODO: implement the special logic for anonymous functions - return BetterConversion(resolveResult.Type, t1, t2); - } - - /// - /// Gets the better conversion (C# 4.0 spec, §7.5.3.4) - /// - /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better - public int BetterConversion(IType s, IType t1, IType t2) - { - bool ident1 = IdentityConversion(s, t1); - bool ident2 = IdentityConversion(s, t2); - if (ident1 && !ident2) - return 1; - if (ident2 && !ident1) - return 2; - return BetterConversionTarget(t1, t2); - } - - /// - /// Gets the better conversion target (C# 4.0 spec, §7.5.3.5) - /// - /// 0 = neither is better; 1 = t1 is better; 2 = t2 is better - int BetterConversionTarget(IType t1, IType t2) - { - bool t1To2 = ImplicitConversion(t1, t2); - bool t2To1 = ImplicitConversion(t2, t1); - if (t1To2 && !t2To1) - return 1; - if (t2To1 && !t1To2) - return 2; - TypeCode t1Code = ReflectionHelper.GetTypeCode(t1); - TypeCode t2Code = ReflectionHelper.GetTypeCode(t2); - if (IsBetterIntegralType(t1Code, t2Code)) - return 1; - if (IsBetterIntegralType(t2Code, t1Code)) - return 2; - return 0; - } - - bool IsBetterIntegralType(TypeCode t1, TypeCode t2) - { - // signed types are better than unsigned types - switch (t1) { - case TypeCode.SByte: - return t2 == TypeCode.Byte || t2 == TypeCode.UInt16 || t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; - case TypeCode.Int16: - return t2 == TypeCode.UInt16 || t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; - case TypeCode.Int32: - return t2 == TypeCode.UInt32 || t2 == TypeCode.UInt64; - case TypeCode.Int64: - return t2 == TypeCode.UInt64; - default: - return false; - } - } - #endregion - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ErrorResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ErrorResolveResult.cs deleted file mode 100644 index 75a36470f..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ErrorResolveResult.cs +++ /dev/null @@ -1,22 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents a resolve error. - /// - public class ErrorResolveResult : ResolveResult - { - public ErrorResolveResult(IType type) : base(type) - { - } - - public override bool IsError { - get { return true; } - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs b/ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs deleted file mode 100644 index be956b22f..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/IResolveVisitorNavigator.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Allows controlling which nodes are resolved by the resolve visitor. - /// - /// - public interface IResolveVisitorNavigator - { - ResolveVisitorNavigationMode Scan(AstNode node); - } - - /// - /// Represents the operation mode of the resolve visitor. - /// - /// - public enum ResolveVisitorNavigationMode - { - /// - /// Scan into the children of the current node, without resolving the current node. - /// - Scan, - /// - /// Skip the current node - do not scan into it; do not resolve it. - /// - Skip, - /// - /// Resolve the current node; but only scan subnodes which are not required for resolving the current node. - /// - Resolve, - /// - /// Resolves all nodes in the current subtree. - /// - ResolveAll - } - - sealed class ConstantModeResolveVisitorNavigator : IResolveVisitorNavigator - { - ResolveVisitorNavigationMode mode; - - public static readonly IResolveVisitorNavigator Skip = new ConstantModeResolveVisitorNavigator { mode = ResolveVisitorNavigationMode.Skip }; - - ResolveVisitorNavigationMode IResolveVisitorNavigator.Scan(AstNode node) - { - return mode; - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ITypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ITypeOrNamespaceReference.cs deleted file mode 100644 index fdca6acb3..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ITypeOrNamespaceReference.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents a reference which could point to a type or namespace. - /// - public interface ITypeOrNamespaceReference : ITypeReference - { - /// - /// Resolves the reference and returns the ResolveResult. - /// - ResolveResult DoResolve(ITypeResolveContext context); - - /// - /// Returns the namespace that is referenced; or null if no such namespace is found. - /// - NamespaceResolveResult ResolveNamespace(ITypeResolveContext context); - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs deleted file mode 100644 index 130946670..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/LocalResolveResult.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents a local variable. - /// - public class LocalResolveResult : ResolveResult - { - readonly IVariable variable; - readonly object constantValue; - - public LocalResolveResult(IVariable variable, IType type, object constantValue = null) - : base(type) - { - if (variable == null) - throw new ArgumentNullException("variable"); - this.variable = variable; - this.constantValue = constantValue; - } - - public IVariable Variable { - get { return variable; } - } - - public bool IsParameter { - get { return variable is IParameter; } - } - - public override bool IsCompileTimeConstant { - get { return variable.IsConst; } - } - - public override object ConstantValue { - get { return constantValue; } - } - - public override string ToString() - { - return string.Format("[VariableResolveResult {0}]", variable); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs deleted file mode 100644 index 06c1e67bc..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberLookup.cs +++ /dev/null @@ -1,274 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections; -using System.Collections.Generic; -using System.Linq; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Implementation of member lookup (C# 4.0 spec, §7.4). - /// - public class MemberLookup - { - #region Static helper methods - /// - /// Gets whether the member is considered to be invocable. - /// - public static bool IsInvocable(IMember member, ITypeResolveContext context) - { - if (member == null) - throw new ArgumentNullException("member"); - // C# 4.0 spec, §7.4 member lookup - if (member is IEvent || member is IMethod) - return true; - IType returnType = member.ReturnType.Resolve(context); - if (returnType == SharedTypes.Dynamic) - return true; - return returnType.IsDelegate(); - } - #endregion - - ITypeResolveContext context; - ITypeDefinition currentTypeDefinition; - IProjectContent currentProject; - - public MemberLookup(ITypeResolveContext context, ITypeDefinition currentTypeDefinition, IProjectContent currentProject) - { - if (context == null) - throw new ArgumentNullException("context"); - this.context = context; - this.currentTypeDefinition = currentTypeDefinition; - this.currentProject = currentProject; - } - - #region IsAccessible - public bool IsProtectedAccessAllowed(IType targetType) - { - ITypeDefinition typeDef = targetType.GetDefinition(); - return typeDef != null && typeDef.IsDerivedFrom(currentTypeDefinition, context); - } - - /// - /// Gets whether is accessible in the current class. - /// - /// The entity to test - /// Whether protected access is allowed. - /// True if the type of the reference is derived from the current class. - public bool IsAccessible(IEntity entity, bool allowProtectedAccess) - { - if (entity == null) - throw new ArgumentNullException("entity"); - // C# 4.0 spec, §3.5.2 Accessiblity domains - switch (entity.Accessibility) { - case Accessibility.None: - return false; - case Accessibility.Private: - // check for members of outer classes (private members of outer classes can be accessed) - var lookupTypeDefinition = currentTypeDefinition; - while (lookupTypeDefinition != null) { - if (entity.DeclaringTypeDefinition.Equals (lookupTypeDefinition)) - return true; - lookupTypeDefinition = lookupTypeDefinition.DeclaringTypeDefinition; - } - return false; - case Accessibility.Public: - return true; - case Accessibility.Protected: - return allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition); - case Accessibility.Internal: - return IsInternalAccessible(entity.ProjectContent); - case Accessibility.ProtectedOrInternal: - return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) - || IsInternalAccessible(entity.ProjectContent); - case Accessibility.ProtectedAndInternal: - return (allowProtectedAccess && IsProtectedAccessible(entity.DeclaringTypeDefinition)) - && IsInternalAccessible(entity.ProjectContent); - default: - throw new Exception("Invalid value for Accessibility"); - } - } - - bool IsInternalAccessible(IProjectContent declaringProject) - { - return declaringProject != null && currentProject != null && declaringProject.InternalsVisibleTo(currentProject, context); - } - - bool IsProtectedAccessible(ITypeDefinition declaringType) - { - if (declaringType.Equals (currentTypeDefinition)) - return true; - // PERF: this might hurt performance as this method is called several times (once for each member) - // make sure resolving base types is cheap (caches?) or cache within the MemberLookup instance - return currentTypeDefinition != null && currentTypeDefinition.IsDerivedFrom(declaringType, context); - } - #endregion - - public ResolveResult LookupType(IType declaringType, string name, IList typeArguments) - { - int typeArgumentCount = typeArguments.Count; - Predicate typeFilter = delegate (ITypeDefinition d) { - return d.TypeParameterCount == typeArgumentCount && d.Name == name && IsAccessible(d, true); - }; - List types = declaringType.GetNestedTypes(context, typeFilter).ToList(); - RemoveTypesHiddenByOtherTypes(types); - if (types.Count > 0) - return CreateTypeResolveResult(types[0], types.Count > 1, typeArguments); - else - return new UnknownMemberResolveResult(declaringType, name, typeArguments); - } - - void RemoveTypesHiddenByOtherTypes(List types) - { - for (int i = types.Count - 1; i >= 0; i--) { - ITypeDefinition d = GetDeclaringTypeDef(types[i]); - if (d == null) - continue; - // nested loop depends on the fact that the members of more derived classes appear later in the list - for (int j = i + 1; j < types.Count; j++) { - if (types[i].TypeParameterCount != types[j].TypeParameterCount) - continue; - ITypeDefinition s = GetDeclaringTypeDef(types[j]); - if (s != null && s != d && s.IsDerivedFrom(d, context)) { - // types[j] hides types[i] - types.RemoveAt(i); - break; - } - } - } - } - - ResolveResult CreateTypeResolveResult(IType returnedType, bool isAmbiguous, IList typeArguments) - { - if (typeArguments.Count > 0) { - // parameterize the type if necessary - ITypeDefinition returnedTypeDef = returnedType as ITypeDefinition; - if (returnedTypeDef != null) - returnedType = new ParameterizedType(returnedTypeDef, typeArguments); - } - if (isAmbiguous) - return new AmbiguousTypeResolveResult(returnedType); - else - return new TypeResolveResult(returnedType); - } - - /// - /// Performs a member lookup. - /// - public ResolveResult Lookup(IType type, string name, IList typeArguments, bool isInvocation) - { - int typeArgumentCount = typeArguments.Count; - - List types = new List(); - List members = new List(); - if (!isInvocation) { - // Consider nested types only if it's not an invocation. The type parameter count must match in this case. - Predicate typeFilter = delegate (ITypeDefinition d) { - // inner types contain the type parameters of outer types. therefore this count has to been adjusted. - int correctedCount = d.TypeParameterCount - (d.DeclaringType != null ? d.DeclaringType.TypeParameterCount : 0); - return correctedCount == typeArgumentCount && d.Name == name && IsAccessible(d, true); - }; - types.AddRange(type.GetNestedTypes(context, typeFilter)); - } - - bool allowProtectedAccess = IsProtectedAccessAllowed(type); - - if (typeArgumentCount == 0) { - Predicate memberFilter = delegate(IMember member) { - return !member.IsOverride && member.Name == name && IsAccessible(member, allowProtectedAccess); - }; - members.AddRange(type.GetMembers(context, memberFilter)); - if (isInvocation) - members.RemoveAll(m => !IsInvocable(m, context)); - } else { - // No need to check for isInvocation/isInvocable here: - // we filter out all non-methods - Predicate memberFilter = delegate(IMethod method) { - return method.TypeParameters.Count == typeArgumentCount - && !method.IsOverride && method.Name == name && IsAccessible(method, allowProtectedAccess); - }; - members.AddRange(type.GetMethods(context, memberFilter).SafeCast()); - } - - // TODO: can't members also hide types? - - RemoveTypesHiddenByOtherTypes(types); - // remove members hidden by types - for (int i = 0; i < types.Count; i++) { - ITypeDefinition d = GetDeclaringTypeDef(types[i]); - if (d != null) - members.RemoveAll(m => d.IsDerivedFrom(m.DeclaringTypeDefinition, context)); - } - // remove members hidden by other members - for (int i = members.Count - 1; i >= 0; i--) { - ITypeDefinition d = members[i].DeclaringTypeDefinition; - IMethod mi = members[i] as IMethod; - // nested loop depends on the fact that the members of more derived classes appear later in the list - for (int j = i + 1; j < members.Count; j++) { - if (mi != null) { - IMethod mj = members[j] as IMethod; - if (mj != null && !ParameterListComparer.Instance.Equals(mi, mj)) - continue; - } - ITypeDefinition s = members[j].DeclaringTypeDefinition; - if (s != null && s != d && s.IsDerivedFrom(d, context)) { - // members[j] hides members[i] - members.RemoveAt(i); - break; - } - } - } - // remove interface members hidden by class members - if (type is ITypeParameter) { - // this can happen only with type parameters - for (int i = members.Count - 1; i >= 0; i--) { - ITypeDefinition d = members[i].DeclaringTypeDefinition; - if (d.ClassType != ClassType.Interface) - continue; - IMethod mi = members[i] as IMethod; - for (int j = 0; j < members.Count; j++) { - if (mi != null) { - IMethod mj = members[j] as IMethod; - if (mj != null && !ParameterListComparer.Instance.Equals(mi, mj)) - continue; - } - ITypeDefinition s = members[j].DeclaringTypeDefinition; - if (s != null && IsNonInterfaceType(s)) { - // members[j] hides members[i] - members.RemoveAt(i); - break; - } - } - } - } - - if (types.Count > 0) { - bool isAmbiguous = !(types.Count == 1 && members.Count == 0); - return CreateTypeResolveResult(types[0], isAmbiguous, typeArguments); - } - if (members.Count == 0) - return new UnknownMemberResolveResult(type, name, typeArguments); - IMember firstNonMethod = members.FirstOrDefault(m => !(m is IMethod)); - if (members.Count == 1 && firstNonMethod != null) - return new MemberResolveResult(firstNonMethod, context); - if (firstNonMethod == null) - return new MethodGroupResolveResult(type, name, members.ConvertAll(m => (IMethod)m), typeArguments); - return new AmbiguousMemberResultResult(firstNonMethod, firstNonMethod.ReturnType.Resolve(context)); - } - - static bool IsNonInterfaceType(ITypeDefinition def) - { - // return type if def is neither an interface nor System.Object - return def.ClassType != ClassType.Interface && !(def.Name == "Object" && def.Namespace == "System" && def.TypeParameterCount == 0); - } - - static ITypeDefinition GetDeclaringTypeDef(IType type) - { - IType declType = type.DeclaringType; - return declType != null ? declType.GetDefinition() : null; - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs deleted file mode 100644 index f6994ef3a..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberResolveResult.cs +++ /dev/null @@ -1,62 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents the result of a member invocation. - /// - public class MemberResolveResult : ResolveResult - { - readonly IMember member; - readonly bool isConstant; - readonly object constantValue; - - public MemberResolveResult(IMember member, IType returnType) : base(returnType) - { - if (member == null) - throw new ArgumentNullException("member"); - this.member = member; - } - - public MemberResolveResult(IMember member, IType returnType, object constantValue) : base(returnType) - { - if (member == null) - throw new ArgumentNullException("member"); - this.member = member; - this.isConstant = true; - this.constantValue = constantValue; - } - - public MemberResolveResult(IMember member, ITypeResolveContext context) : base(member.ReturnType.Resolve(context)) - { - this.member = member; - IField field = member as IField; - if (field != null) { - isConstant = field.IsConst; - if (isConstant) - constantValue = field.ConstantValue.GetValue(context); - } - } - - public IMember Member { - get { return member; } - } - - public override bool IsCompileTimeConstant { - get { return isConstant; } - } - - public override object ConstantValue { - get { return constantValue; } - } - - public override string ToString() - { - return string.Format("[{0} {1}]", GetType().Name, member); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs deleted file mode 100644 index c6c9e00a4..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MemberTypeOrNamespaceReference.cs +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Reference to a qualified type or namespace name. - /// - public sealed class MemberTypeOrNamespaceReference : ITypeOrNamespaceReference - { - readonly ITypeOrNamespaceReference target; - readonly ITypeDefinition parentTypeDefinition; - readonly UsingScope parentUsingScope; - readonly string identifier; - readonly IList typeArguments; - - public MemberTypeOrNamespaceReference(ITypeOrNamespaceReference target, string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope) - { - if (target == null) - throw new ArgumentNullException("target"); - if (identifier == null) - throw new ArgumentNullException("identifier"); - this.target = target; - this.identifier = identifier; - this.typeArguments = typeArguments ?? EmptyList.Instance; - this.parentTypeDefinition = parentTypeDefinition; - this.parentUsingScope = parentUsingScope; - } - - /// - /// Adds a suffix to the identifier. - /// Does not modify the existing type reference, but returns a new one. - /// - public MemberTypeOrNamespaceReference AddSuffix(string suffix) - { - return new MemberTypeOrNamespaceReference(target, identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope); - } - - public ResolveResult DoResolve(ITypeResolveContext context) - { - ResolveResult targetRR = target.DoResolve(context); - if (targetRR.IsError) - return targetRR; - CSharpResolver r = new CSharpResolver(context); - r.CurrentTypeDefinition = parentTypeDefinition != null ? parentTypeDefinition.GetCompoundClass() : null; - r.UsingScope = parentUsingScope; - IType[] typeArgs = new IType[typeArguments.Count]; - for (int i = 0; i < typeArgs.Length; i++) { - typeArgs[i] = typeArguments[i].Resolve(context); - } - return r.ResolveMemberAccess(targetRR, identifier, typeArgs, false); - } - - public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible - return DoResolve(context) as NamespaceResolveResult; - } - - public IType Resolve(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible; then map the result type into the new context - TypeResolveResult rr = DoResolve(context) as TypeResolveResult; - return rr != null ? rr.Type : SharedTypes.UnknownType; - } - - public override string ToString() - { - if (typeArguments.Count == 0) - return target.ToString() + "." + identifier; - else - return target.ToString() + "." + identifier + "<" + DotNet35Compat.StringJoin(",", typeArguments) + ">"; - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs deleted file mode 100644 index ec456a013..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/MethodGroupResolveResult.cs +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; - -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents a group of methods. - /// - public class MethodGroupResolveResult : ResolveResult - { - readonly ReadOnlyCollection methods; - readonly ReadOnlyCollection typeArguments; - readonly IType targetType; - readonly string methodName; - - /// - /// List of extension methods, used to avoid re-calculating it in ResolveInvocation() when it was already - /// calculated by ResolveMemberAccess(). - /// - internal List> ExtensionMethods; - - public MethodGroupResolveResult(IType targetType, string methodName, IList methods, IList typeArguments) : base(SharedTypes.UnknownType) - { - if (targetType == null) - throw new ArgumentNullException("targetType"); - if (methods == null) - throw new ArgumentNullException("methods"); - this.targetType = targetType; - this.methodName = methodName; - this.methods = new ReadOnlyCollection(methods); - this.typeArguments = typeArguments != null ? new ReadOnlyCollection(typeArguments) : EmptyList.Instance; - } - - public IType TargetType { - get { return targetType; } - } - - public string MethodName { - get { return methodName; } - } - - public ReadOnlyCollection Methods { - get { return methods; } - } - - public ReadOnlyCollection TypeArguments { - get { return typeArguments; } - } - - public override string ToString() - { - return string.Format("[{0} with {1} method(s)]", GetType().Name, methods.Count); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/NamespaceResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/NamespaceResolveResult.cs deleted file mode 100644 index 8b4ed998b..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/NamespaceResolveResult.cs +++ /dev/null @@ -1,30 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents that an expression resolved to a namespace. - /// - public class NamespaceResolveResult : ResolveResult - { - readonly string namespaceName; - - public NamespaceResolveResult(string namespaceName) : base(SharedTypes.UnknownType) - { - this.namespaceName = namespaceName; - } - - public string NamespaceName { - get { return namespaceName; } - } - - public override string ToString() - { - return string.Format("[{0} {1}]", GetType().Name, namespaceName); - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs b/ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs deleted file mode 100644 index 5ed4c619e..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/NodeListResolveVisitorNavigator.cs +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// implementation that resolves a list of nodes. - /// We will skip all nodes which are not the target nodes or ancestors of the target nodes. - /// - public sealed class NodeListResolveVisitorNavigator : IResolveVisitorNavigator - { - readonly Dictionary dict = new Dictionary(); - - /// - /// Creates a new NodeListResolveVisitorNavigator that resolves the specified nodes. - /// - public NodeListResolveVisitorNavigator(IEnumerable nodes) - { - if (nodes == null) - throw new ArgumentNullException("nodes"); - foreach (var node in nodes) { - dict[node] = ResolveVisitorNavigationMode.Resolve; - for (var ancestor = node.Parent; ancestor != null && !dict.ContainsKey(ancestor); ancestor = ancestor.Parent) { - dict.Add(ancestor, ResolveVisitorNavigationMode.Scan); - } - } - } - - /// - public ResolveVisitorNavigationMode Scan(AstNode node) - { - ResolveVisitorNavigationMode mode; - if (dict.TryGetValue(node, out mode)) { - return mode; - } else { - return ResolveVisitorNavigationMode.Skip; - } - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs deleted file mode 100644 index 0327e1379..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveResult.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents the result of resolving an expression. - /// - public class ResolveResult - { - IType type; - - public ResolveResult(IType type) - { - if (type == null) - throw new ArgumentNullException("type"); - this.type = type; - } - - public IType Type { - get { return type; } - } - - public virtual bool IsCompileTimeConstant { - get { return false; } - } - - public virtual object ConstantValue { - get { return null; } - } - - public virtual bool IsError { - get { return false; } - } - - public override string ToString() - { - return "[" + GetType().Name + " " + type + "]"; - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs b/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs deleted file mode 100644 index 3e10c6016..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/ResolveVisitor.cs +++ /dev/null @@ -1,1265 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Threading; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Traverses the DOM and resolves expressions. - /// - /// - /// The ResolveVisitor does two jobs at the same time: it tracks the resolve context (properties on CSharpResolver) - /// and it resolves the expressions visited. - /// To allow using the context tracking without having to resolve every expression in the file (e.g. when you want to resolve - /// only a single node deep within the DOM), you can use the interface. - /// The navigator allows you to switch the between scanning mode and resolving mode. - /// In scanning mode, the context is tracked (local variables registered etc.), but nodes are not resolved. - /// While scanning, the navigator will get asked about every node that the resolve visitor is about to enter. - /// This allows the navigator whether to keep scanning, whether switch to resolving mode, or whether to completely skip the - /// subtree rooted at that node. - /// - /// In resolving mode, the context is tracked and nodes will be resolved. - /// The resolve visitor may decide that it needs to resolve other nodes as well in order to resolve the current node. - /// In this case, those nodes will be resolved automatically, without asking the navigator interface. - /// For child nodes that are not essential to resolving, the resolve visitor will switch back to scanning mode (and thus will - /// ask the navigator for further instructions). - /// - /// Moreover, there is the ResolveAll mode - it works similar to resolving mode, but will not switch back to scanning mode. - /// The whole subtree will be resolved without notifying the navigator. - /// - public sealed class ResolveVisitor : DepthFirstAstVisitor - { - static readonly ResolveResult errorResult = new ErrorResolveResult(SharedTypes.UnknownType); - CSharpResolver resolver; - readonly ParsedFile parsedFile; - readonly Dictionary resolveResultCache = new Dictionary(); - readonly Dictionary resolverBeforeDict = new Dictionary(); - - readonly IResolveVisitorNavigator navigator; - ResolveVisitorNavigationMode mode = ResolveVisitorNavigationMode.Scan; - - #region Constructor - /// - /// Creates a new ResolveVisitor instance. - /// - /// - /// The CSharpResolver, describing the initial resolve context. - /// If you visit a whole CompilationUnit with the resolve visitor, you can simply pass - /// new CSharpResolver(typeResolveContext) without setting up the context. - /// If you only visit a subtree, you need to pass a CSharpResolver initialized to the context for that subtree. - /// - /// - /// Result of the for the file being passed. This is used for setting up the context on the resolver. - /// You may pass null if you are only visiting a part of a method body and have already set up the context in the . - /// - /// - /// The navigator, which controls where the resolve visitor will switch between scanning mode and resolving mode. - /// If you pass null, then ResolveAll mode will be used. - /// - public ResolveVisitor(CSharpResolver resolver, ParsedFile parsedFile, IResolveVisitorNavigator navigator = null) - { - if (resolver == null) - throw new ArgumentNullException("resolver"); - this.resolver = resolver; - this.parsedFile = parsedFile; - this.navigator = navigator; - if (navigator == null) - mode = ResolveVisitorNavigationMode.ResolveAll; - } - #endregion - - /// - /// Gets the TypeResolveContext used by this ResolveVisitor. - /// - public ITypeResolveContext TypeResolveContext { - get { return resolver.Context; } - } - - /// - /// Gets the CancellationToken used by this ResolveVisitor. - /// - public CancellationToken CancellationToken { - get { return resolver.cancellationToken; } - } - - #region Scan / Resolve - bool resolverEnabled { - get { return mode != ResolveVisitorNavigationMode.Scan; } - } - - public void Scan(AstNode node) - { - if (node == null || node.IsNull) - return; - if (mode == ResolveVisitorNavigationMode.ResolveAll) { - Resolve(node); - } else { - ResolveVisitorNavigationMode oldMode = mode; - mode = navigator.Scan(node); - switch (mode) { - case ResolveVisitorNavigationMode.Skip: - if (node is VariableDeclarationStatement) { - // Enforce scanning of variable declarations. - goto case ResolveVisitorNavigationMode.Scan; - } - break; - case ResolveVisitorNavigationMode.Scan: - resolverBeforeDict[node] = resolver.Clone(); - node.AcceptVisitor(this, null); - break; - case ResolveVisitorNavigationMode.Resolve: - case ResolveVisitorNavigationMode.ResolveAll: - Resolve(node); - break; - default: - throw new InvalidOperationException("Invalid value for ResolveVisitorNavigationMode"); - } - mode = oldMode; - } - } - - public ResolveResult Resolve(AstNode node) - { - if (node == null || node.IsNull) - return errorResult; - bool wasScan = mode == ResolveVisitorNavigationMode.Scan; - if (wasScan) - mode = ResolveVisitorNavigationMode.Resolve; - ResolveResult result; - if (!resolveResultCache.TryGetValue(node, out result)) { - resolver.cancellationToken.ThrowIfCancellationRequested(); - resolverBeforeDict[node] = resolver.Clone(); - result = resolveResultCache[node] = node.AcceptVisitor(this, null) ?? errorResult; - } - if (wasScan) - mode = ResolveVisitorNavigationMode.Scan; - return result; - } - - protected override ResolveResult VisitChildren(AstNode node, object data) - { - ScanChildren(node); - return null; - } - - void ScanChildren(AstNode node) - { - for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { - Scan(child); - } - } - #endregion - - #region GetResolveResult - /// - /// Gets the cached resolve result for the specified node. - /// Returns null if no cached result was found (e.g. if the node was not visited; or if it was visited in scanning mode). - /// - public ResolveResult GetResolveResult(AstNode node) - { - ResolveResult result; - if (resolveResultCache.TryGetValue(node, out result)) - return result; - else - return null; - } - - /// - /// Gets the resolver state in front of the specified node. - /// Returns null if no cached resolver was found (e.g. if the node was skipped by the navigator) - /// - public CSharpResolver GetResolverStateBefore(AstNode node) - { - CSharpResolver r; - if (resolverBeforeDict.TryGetValue(node, out r)) - return r; - else - return null; - } - #endregion - - #region Track UsingScope - public override ResolveResult VisitCompilationUnit(CompilationUnit unit, object data) - { - UsingScope previousUsingScope = resolver.UsingScope; - try { - if (parsedFile != null) - resolver.UsingScope = parsedFile.RootUsingScope; - ScanChildren(unit); - return null; - } finally { - resolver.UsingScope = previousUsingScope; - } - } - - public override ResolveResult VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) - { - UsingScope previousUsingScope = resolver.UsingScope; - try { - if (parsedFile != null) { - resolver.UsingScope = parsedFile.GetUsingScope(namespaceDeclaration.StartLocation); - } - ScanChildren(namespaceDeclaration); - return new NamespaceResolveResult(resolver.UsingScope.NamespaceName); - } finally { - resolver.UsingScope = previousUsingScope; - } - } - #endregion - - #region Track CurrentTypeDefinition - ResolveResult VisitTypeOrDelegate(AstNode typeDeclaration) - { - ITypeDefinition previousTypeDefinition = resolver.CurrentTypeDefinition; - try { - ITypeDefinition newTypeDefinition = null; - if (resolver.CurrentTypeDefinition != null) { - foreach (ITypeDefinition nestedType in resolver.CurrentTypeDefinition.NestedTypes) { - if (nestedType.Region.IsInside(typeDeclaration.StartLocation)) { - newTypeDefinition = nestedType; - break; - } - } - } else if (parsedFile != null) { - newTypeDefinition = parsedFile.GetTopLevelTypeDefinition(typeDeclaration.StartLocation); - } - if (newTypeDefinition != null) - resolver.CurrentTypeDefinition = newTypeDefinition; - ScanChildren(typeDeclaration); - return newTypeDefinition != null ? new TypeResolveResult(newTypeDefinition) : errorResult; - } finally { - resolver.CurrentTypeDefinition = previousTypeDefinition; - } - } - - public override ResolveResult VisitTypeDeclaration(TypeDeclaration typeDeclaration, object data) - { - return VisitTypeOrDelegate(typeDeclaration); - } - - public override ResolveResult VisitDelegateDeclaration(DelegateDeclaration delegateDeclaration, object data) - { - return VisitTypeOrDelegate(delegateDeclaration); - } - #endregion - - #region Track CurrentMember - public override ResolveResult VisitFieldDeclaration(FieldDeclaration fieldDeclaration, object data) - { - return VisitFieldOrEventDeclaration(fieldDeclaration); - } - - public override ResolveResult VisitEventDeclaration(EventDeclaration eventDeclaration, object data) - { - return VisitFieldOrEventDeclaration(eventDeclaration); - } - - ResolveResult VisitFieldOrEventDeclaration(AttributedNode fieldOrEventDeclaration) - { - int initializerCount = fieldOrEventDeclaration.GetChildrenByRole(FieldDeclaration.Roles.Variable).Count; - ResolveResult result = null; - for (AstNode node = fieldOrEventDeclaration.FirstChild; node != null; node = node.NextSibling) { - if (node.Role == FieldDeclaration.Roles.Variable) { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Fields.FirstOrDefault(f => f.Region.IsInside(node.StartLocation)); - } - - if (resolverEnabled && initializerCount == 1) { - result = Resolve(node); - } else { - Scan(node); - } - - resolver.CurrentMember = null; - } else { - Scan(node); - } - } - return result; - } - - public override ResolveResult VisitVariableInitializer(VariableInitializer variableInitializer, object data) - { - ScanChildren(variableInitializer); - if (resolverEnabled) { - if (variableInitializer.Parent is FieldDeclaration) { - if (resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.CurrentMember.ReturnType.Resolve(resolver.Context)); - } else { - string identifier = variableInitializer.Name; - foreach (IVariable v in resolver.LocalVariables) { - if (v.Name == identifier) { - object constantValue = v.IsConst ? v.ConstantValue.GetValue(resolver.Context) : null; - return new LocalResolveResult(v, v.Type.Resolve(resolver.Context), constantValue); - } - } - } - return errorResult; - } else { - return null; - } - } - - ResolveResult VisitMethodMember(AttributedNode member) - { - try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Methods.FirstOrDefault(m => m.Region.IsInside(member.StartLocation)); - } - - ScanChildren(member); - - if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.Context); - else - return errorResult; - } finally { - resolver.CurrentMember = null; - } - } - - public override ResolveResult VisitMethodDeclaration(MethodDeclaration methodDeclaration, object data) - { - return VisitMethodMember(methodDeclaration); - } - - public override ResolveResult VisitOperatorDeclaration(OperatorDeclaration operatorDeclaration, object data) - { - return VisitMethodMember(operatorDeclaration); - } - - public override ResolveResult VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration, object data) - { - return VisitMethodMember(constructorDeclaration); - } - - public override ResolveResult VisitDestructorDeclaration(DestructorDeclaration destructorDeclaration, object data) - { - return VisitMethodMember(destructorDeclaration); - } - - // handle properties/indexers - ResolveResult VisitPropertyMember(MemberDeclaration propertyOrIndexerDeclaration) - { - try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Properties.FirstOrDefault(p => p.Region.IsInside(propertyOrIndexerDeclaration.StartLocation)); - } - - for (AstNode node = propertyOrIndexerDeclaration.FirstChild; node != null; node = node.NextSibling) { - if (node.Role == PropertyDeclaration.SetterRole && resolver.CurrentMember != null) { - resolver.PushBlock(); - resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); - Scan(node); - resolver.PopBlock(); - } else { - Scan(node); - } - } - if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.Context); - else - return errorResult; - } finally { - resolver.CurrentMember = null; - } - } - - public override ResolveResult VisitPropertyDeclaration(PropertyDeclaration propertyDeclaration, object data) - { - return VisitPropertyMember(propertyDeclaration); - } - - public override ResolveResult VisitIndexerDeclaration(IndexerDeclaration indexerDeclaration, object data) - { - return VisitPropertyMember(indexerDeclaration); - } - - public override ResolveResult VisitCustomEventDeclaration(CustomEventDeclaration eventDeclaration, object data) - { - try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Events.FirstOrDefault(e => e.Region.IsInside(eventDeclaration.StartLocation)); - } - - if (resolver.CurrentMember != null) { - resolver.PushBlock(); - resolver.AddVariable(resolver.CurrentMember.ReturnType, DomRegion.Empty, "value"); - ScanChildren(eventDeclaration); - resolver.PopBlock(); - } else { - ScanChildren(eventDeclaration); - } - - if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.Context); - else - return errorResult; - } finally { - resolver.CurrentMember = null; - } - } - - public override ResolveResult VisitParameterDeclaration(ParameterDeclaration parameterDeclaration, object data) - { - ScanChildren(parameterDeclaration); - if (resolverEnabled) { - IParameterizedMember pm = resolver.CurrentMember as IParameterizedMember; - if (pm != null) { - foreach (IParameter p in pm.Parameters) { - if (p.Name == parameterDeclaration.Name) { - return new LocalResolveResult(p, p.Type.Resolve(resolver.Context)); - } - } - } - return errorResult; - } else { - return null; - } - } - - public override ResolveResult VisitTypeParameterDeclaration(TypeParameterDeclaration typeParameterDeclaration, object data) - { - ScanChildren(typeParameterDeclaration); - if (resolverEnabled) { - string name = typeParameterDeclaration.Name; - IMethod m = resolver.CurrentMember as IMethod; - if (m != null) { - foreach (var tp in m.TypeParameters) { - if (tp.Name == name) - return new TypeResolveResult(tp); - } - } - if (resolver.CurrentTypeDefinition != null) { - var typeParameters = resolver.CurrentTypeDefinition.TypeParameters; - // look backwards so that TPs in the current type take precedence over those copied from outer types - for (int i = typeParameters.Count - 1; i >= 0; i--) { - if (typeParameters[i].Name == name) - return new TypeResolveResult(typeParameters[i]); - } - } - return errorResult; - } else { - return null; - } - } - - public override ResolveResult VisitEnumMemberDeclaration(EnumMemberDeclaration enumMemberDeclaration, object data) - { - try { - if (resolver.CurrentTypeDefinition != null) { - resolver.CurrentMember = resolver.CurrentTypeDefinition.Fields.FirstOrDefault(f => f.Region.IsInside(enumMemberDeclaration.StartLocation)); - } - - ScanChildren(enumMemberDeclaration); - - if (resolverEnabled && resolver.CurrentMember != null) - return new MemberResolveResult(resolver.CurrentMember, resolver.Context); - else - return errorResult; - } finally { - resolver.CurrentMember = null; - } - } - - public override ResolveResult VisitFixedFieldDeclaration(FixedFieldDeclaration fixedFieldDeclaration, object data) - { - throw new NotImplementedException(); - } - #endregion - - #region Track CheckForOverflow - public override ResolveResult VisitCheckedExpression(CheckedExpression checkedExpression, object data) - { - bool oldCheckForOverflow = resolver.CheckForOverflow; - try { - resolver.CheckForOverflow = true; - if (resolverEnabled) { - return Resolve(checkedExpression.Expression); - } else { - ScanChildren(checkedExpression); - return null; - } - } finally { - resolver.CheckForOverflow = oldCheckForOverflow; - } - } - - public override ResolveResult VisitUncheckedExpression(UncheckedExpression uncheckedExpression, object data) - { - bool oldCheckForOverflow = resolver.CheckForOverflow; - try { - resolver.CheckForOverflow = false; - if (resolverEnabled) { - return Resolve(uncheckedExpression.Expression); - } else { - ScanChildren(uncheckedExpression); - return null; - } - } finally { - resolver.CheckForOverflow = oldCheckForOverflow; - } - } - - public override ResolveResult VisitCheckedStatement(CheckedStatement checkedStatement, object data) - { - bool oldCheckForOverflow = resolver.CheckForOverflow; - try { - resolver.CheckForOverflow = true; - ScanChildren(checkedStatement); - return null; - } finally { - resolver.CheckForOverflow = oldCheckForOverflow; - } - } - - public override ResolveResult VisitUncheckedStatement(UncheckedStatement uncheckedStatement, object data) - { - bool oldCheckForOverflow = resolver.CheckForOverflow; - try { - resolver.CheckForOverflow = false; - ScanChildren(uncheckedStatement); - return null; - } finally { - resolver.CheckForOverflow = oldCheckForOverflow; - } - } - #endregion - - #region Visit Expressions - static bool IsTargetOfInvocation(AstNode node) - { - InvocationExpression ie = node.Parent as InvocationExpression; - return ie != null && ie.Target == node; - } - - IType ResolveType(AstType type) - { - return MakeTypeReference(type).Resolve(resolver.Context); - } - - public override ResolveResult VisitAnonymousMethodExpression(AnonymousMethodExpression anonymousMethodExpression, object data) - { - throw new NotImplementedException(); - } - - static string GetAnonymousTypePropertyName(Expression expr, out Expression resolveExpr) - { - if (expr is NamedArgumentExpression) { - var namedArgExpr = (NamedArgumentExpression)expr; - resolveExpr = namedArgExpr.Expression; - return namedArgExpr.Identifier; - } - // no name given, so it's a projection initializer - if (expr is MemberReferenceExpression) { - resolveExpr = expr; - return ((MemberReferenceExpression)expr).MemberName; - } - if (expr is IdentifierExpression) { - resolveExpr = expr; - return ((IdentifierExpression)expr).Identifier; - } - resolveExpr = null; - return null; - } - - public override ResolveResult VisitAnonymousTypeCreateExpression(AnonymousTypeCreateExpression anonymousTypeCreateExpression, object data) - { - // 7.6.10.6 Anonymous object creation expressions - var anonymousType = new DefaultTypeDefinition(resolver.CurrentTypeDefinition, "$Anonymous$"); - anonymousType.IsSynthetic = true; - foreach (var expr in anonymousTypeCreateExpression.Initializer) { - 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); - } - return new TypeResolveResult(anonymousType); - } - - public override ResolveResult VisitArrayCreateExpression(ArrayCreateExpression arrayCreateExpression, object data) - { - throw new NotImplementedException(); - } - - public override ResolveResult VisitAsExpression(AsExpression asExpression, object data) - { - if (resolverEnabled) { - Scan(asExpression.Expression); - return new ResolveResult(ResolveType(asExpression.Type)); - } else { - ScanChildren(asExpression); - return null; - } - } - - public override ResolveResult VisitAssignmentExpression(AssignmentExpression assignmentExpression, object data) - { - if (resolverEnabled) { - ResolveResult left = Resolve(assignmentExpression.Left); - Scan(assignmentExpression.Right); - return new ResolveResult(left.Type); - } else { - ScanChildren(assignmentExpression); - return null; - } - } - - public override ResolveResult VisitBaseReferenceExpression(BaseReferenceExpression baseReferenceExpression, object data) - { - if (resolverEnabled) { - return resolver.ResolveBaseReference(); - } else { - ScanChildren(baseReferenceExpression); - return null; - } - } - - public override ResolveResult VisitBinaryOperatorExpression(BinaryOperatorExpression binaryOperatorExpression, object data) - { - if (resolverEnabled) { - ResolveResult left = Resolve(binaryOperatorExpression.Left); - ResolveResult right = Resolve(binaryOperatorExpression.Right); - return resolver.ResolveBinaryOperator(binaryOperatorExpression.Operator, left, right); - } else { - ScanChildren(binaryOperatorExpression); - return null; - } - } - - public override ResolveResult VisitCastExpression(CastExpression castExpression, object data) - { - if (resolverEnabled) { - return resolver.ResolveCast(ResolveType(castExpression.Type), Resolve(castExpression.Expression)); - } else { - ScanChildren(castExpression); - return null; - } - } - - public override ResolveResult VisitConditionalExpression(ConditionalExpression conditionalExpression, object data) - { - if (resolverEnabled) { - return resolver.ResolveConditional( - Resolve(conditionalExpression.Condition), - Resolve(conditionalExpression.TrueExpression), - Resolve(conditionalExpression.FalseExpression)); - } else { - ScanChildren(conditionalExpression); - return null; - } - } - - public override ResolveResult VisitDefaultValueExpression(DefaultValueExpression defaultValueExpression, object data) - { - if (resolverEnabled) { - return resolver.ResolveDefaultValue(ResolveType(defaultValueExpression.Type)); - } else { - ScanChildren(defaultValueExpression); - return null; - } - } - - public override ResolveResult VisitDirectionExpression(DirectionExpression directionExpression, object data) - { - if (resolverEnabled) { - ResolveResult rr = Resolve(directionExpression.Expression); - return new ByReferenceResolveResult(rr.Type, directionExpression.FieldDirection == FieldDirection.Out); - } else { - ScanChildren(directionExpression); - return null; - } - } - - public override ResolveResult VisitEmptyExpression(EmptyExpression emptyExpression, object data) - { - return errorResult; - } - - public override ResolveResult VisitIdentifierExpression(IdentifierExpression identifierExpression, object data) - { - if (resolverEnabled) { - List typeArguments = new List(); - foreach (AstType typeArgument in identifierExpression.TypeArguments) { - typeArguments.Add(ResolveType(typeArgument)); - } - return resolver.ResolveSimpleName(identifierExpression.Identifier, typeArguments, - IsTargetOfInvocation(identifierExpression)); - } else { - ScanChildren(identifierExpression); - return null; - } - } - - ResolveResult[] GetArguments(IEnumerable argumentExpressions, out string[] argumentNames) - { - argumentNames = null; // TODO: add support for named arguments - ResolveResult[] arguments = new ResolveResult[argumentExpressions.Count()]; - int i = 0; - foreach (AstNode argument in argumentExpressions) { - arguments[i++] = Resolve(argument); - } - return arguments; - } - - public override ResolveResult VisitIndexerExpression(IndexerExpression indexerExpression, object data) - { - if (resolverEnabled) { - ResolveResult target = Resolve(indexerExpression.Target); - string[] argumentNames; - ResolveResult[] arguments = GetArguments(indexerExpression.Arguments, out argumentNames); - return resolver.ResolveIndexer(target, arguments, argumentNames); - } else { - ScanChildren(indexerExpression); - return null; - } - } - - public override ResolveResult VisitInvocationExpression(InvocationExpression invocationExpression, object data) - { - if (resolverEnabled) { - ResolveResult target = Resolve(invocationExpression.Target); - string[] argumentNames; - ResolveResult[] arguments = GetArguments(invocationExpression.Arguments, out argumentNames); - return resolver.ResolveInvocation(target, arguments, argumentNames); - } else { - ScanChildren(invocationExpression); - return null; - } - } - - public override ResolveResult VisitIsExpression(IsExpression isExpression, object data) - { - ScanChildren(isExpression); - if (resolverEnabled) - return new ResolveResult(KnownTypeReference.Boolean.Resolve(resolver.Context)); - else - return null; - } - - public override ResolveResult VisitLambdaExpression(LambdaExpression lambdaExpression, object data) - { - throw new NotImplementedException(); - } - - public override ResolveResult VisitMemberReferenceExpression(MemberReferenceExpression memberReferenceExpression, object data) - { - if (resolverEnabled) { - ResolveResult target = Resolve(memberReferenceExpression.Target); - List typeArguments = new List(); - foreach (AstType typeArgument in memberReferenceExpression.TypeArguments) { - typeArguments.Add(ResolveType(typeArgument)); - } - return resolver.ResolveMemberAccess(target, memberReferenceExpression.MemberName, - typeArguments, - IsTargetOfInvocation(memberReferenceExpression)); - } else { - ScanChildren(memberReferenceExpression); - return null; - } - } - - public override ResolveResult VisitNullReferenceExpression(NullReferenceExpression nullReferenceExpression, object data) - { - if (resolverEnabled) { - return resolver.ResolvePrimitive(null); - } else { - return null; - } - } - - public override ResolveResult VisitObjectCreateExpression(ObjectCreateExpression objectCreateExpression, object data) - { - if (resolverEnabled) { - IType type = ResolveType(objectCreateExpression.Type); - string[] argumentNames; - ResolveResult[] arguments = GetArguments(objectCreateExpression.Arguments, out argumentNames); - return resolver.ResolveObjectCreation(type, arguments, argumentNames); - } else { - ScanChildren(objectCreateExpression); - return null; - } - } - - public override ResolveResult VisitParenthesizedExpression(ParenthesizedExpression parenthesizedExpression, object data) - { - if (resolverEnabled) { - return Resolve(parenthesizedExpression.Expression); - } else { - Scan(parenthesizedExpression.Expression); - return null; - } - } - - public override ResolveResult VisitPointerReferenceExpression(PointerReferenceExpression pointerReferenceExpression, object data) - { - if (resolverEnabled) { - ResolveResult target = Resolve(pointerReferenceExpression.Target); - ResolveResult deferencedTarget = resolver.ResolveUnaryOperator(UnaryOperatorType.Dereference, target); - List typeArguments = new List(); - foreach (AstType typeArgument in pointerReferenceExpression.TypeArguments) { - typeArguments.Add(ResolveType(typeArgument)); - } - return resolver.ResolveMemberAccess(deferencedTarget, pointerReferenceExpression.MemberName, - typeArguments, - IsTargetOfInvocation(pointerReferenceExpression)); - } else { - ScanChildren(pointerReferenceExpression); - return null; - } - } - - public override ResolveResult VisitPrimitiveExpression(PrimitiveExpression primitiveExpression, object data) - { - if (resolverEnabled) { - return resolver.ResolvePrimitive(primitiveExpression.Value); - } else { - return null; - } - } - - public override ResolveResult VisitSizeOfExpression(SizeOfExpression sizeOfExpression, object data) - { - if (resolverEnabled) { - return resolver.ResolveSizeOf(ResolveType(sizeOfExpression.Type)); - } else { - ScanChildren(sizeOfExpression); - return null; - } - } - - public override ResolveResult VisitStackAllocExpression(StackAllocExpression stackAllocExpression, object data) - { - if (resolverEnabled) { - Scan(stackAllocExpression.CountExpression); - return new ResolveResult(new PointerType(ResolveType(stackAllocExpression.Type))); - } else { - ScanChildren(stackAllocExpression); - return null; - } - } - - public override ResolveResult VisitThisReferenceExpression(ThisReferenceExpression thisReferenceExpression, object data) - { - return resolver.ResolveThisReference(); - } - - static readonly GetClassTypeReference systemType = new GetClassTypeReference("System", "Type", 0); - - public override ResolveResult VisitTypeOfExpression(TypeOfExpression typeOfExpression, object data) - { - ScanChildren(typeOfExpression); - if (resolverEnabled) - return new ResolveResult(systemType.Resolve(resolver.Context)); - else - return null; - } - - public override ResolveResult VisitTypeReferenceExpression(TypeReferenceExpression typeReferenceExpression, object data) - { - if (resolverEnabled) { - return Resolve(typeReferenceExpression.Type); - } else { - Scan(typeReferenceExpression.Type); - return null; - } - } - - public override ResolveResult VisitUnaryOperatorExpression(UnaryOperatorExpression unaryOperatorExpression, object data) - { - if (resolverEnabled) { - ResolveResult expr = Resolve(unaryOperatorExpression.Expression); - return resolver.ResolveUnaryOperator(unaryOperatorExpression.Operator, expr); - } else { - ScanChildren(unaryOperatorExpression); - return null; - } - } - - public override ResolveResult VisitUndocumentedExpression(UndocumentedExpression undocumentedExpression, object data) - { - ScanChildren(undocumentedExpression); - if (resolverEnabled) { - ITypeReference resultType; - switch (undocumentedExpression.UndocumentedExpressionType) { - case UndocumentedExpressionType.ArgListAccess: - case UndocumentedExpressionType.ArgList: - resultType = typeof(RuntimeArgumentHandle).ToTypeReference(); - break; - case UndocumentedExpressionType.RefValue: - var tre = undocumentedExpression.Arguments.ElementAtOrDefault(1) as TypeReferenceExpression; - if (tre != null) - resultType = ResolveType(tre.Type); - else - resultType = SharedTypes.UnknownType; - break; - case UndocumentedExpressionType.RefType: - resultType = systemType; - break; - case UndocumentedExpressionType.MakeRef: - resultType = typeof(TypedReference).ToTypeReference(); - break; - default: - throw new InvalidOperationException("Invalid value for UndocumentedExpressionType"); - } - return new ResolveResult(resultType.Resolve(resolver.Context)); - } else { - return null; - } - } - #endregion - - #region Local Variable Scopes (Block Statements) - public override ResolveResult VisitBlockStatement(BlockStatement blockStatement, object data) - { - resolver.PushBlock(); - ScanChildren(blockStatement); - resolver.PopBlock(); - return null; - } - - public override ResolveResult VisitUsingStatement(UsingStatement usingStatement, object data) - { - resolver.PushBlock(); - ScanChildren(usingStatement); - resolver.PopBlock(); - return null; - } - - public override ResolveResult VisitFixedStatement(FixedStatement fixedStatement, object data) - { - resolver.PushBlock(); - - VariableInitializer firstInitializer = fixedStatement.Variables.FirstOrDefault(); - ITypeReference type = MakeTypeReference(fixedStatement.Type, - firstInitializer != null ? firstInitializer.Initializer : null, - false); - - for (AstNode node = fixedStatement.FirstChild; node != null; node = node.NextSibling) { - if (node.Role == FixedStatement.Roles.Variable) { - VariableInitializer vi = (VariableInitializer)node; - resolver.AddVariable(type, new DomRegion (parsedFile.FileName, vi.StartLocation, vi.EndLocation) , vi.Name); - } - Scan(node); - } - resolver.PopBlock(); - return null; - } - - public override ResolveResult VisitForStatement(ForStatement forStatement, object data) - { - resolver.PushBlock(); - ScanChildren(forStatement); - resolver.PopBlock(); - return null; - } - - - public override ResolveResult VisitForeachStatement(ForeachStatement foreachStatement, object data) - { - resolver.PushBlock(); - ITypeReference type = MakeTypeReference(foreachStatement.VariableType, foreachStatement.InExpression, true); - resolver.AddVariable(type, new DomRegion (parsedFile.FileName, foreachStatement.VariableNameToken.StartLocation, foreachStatement.VariableNameToken.EndLocation), foreachStatement.VariableName); - ScanChildren(foreachStatement); - resolver.PopBlock(); - return null; - } - - public override ResolveResult VisitCatchClause(CatchClause catchClause, object data) - { - resolver.PushBlock(); - if (catchClause.VariableName != null) { - resolver.AddVariable(MakeTypeReference(catchClause.Type, null, false), new DomRegion (parsedFile.FileName, catchClause.VariableNameToken.StartLocation, catchClause.VariableNameToken.EndLocation), catchClause.VariableName); - } - ScanChildren(catchClause); - resolver.PopBlock(); - return null; - } - #endregion - - #region VariableDeclarationStatement - public override ResolveResult VisitVariableDeclarationStatement(VariableDeclarationStatement variableDeclarationStatement, object data) - { - bool isConst = (variableDeclarationStatement.Modifiers & Modifiers.Const) != 0; - VariableInitializer firstInitializer = variableDeclarationStatement.Variables.FirstOrDefault(); - ITypeReference type = MakeTypeReference(variableDeclarationStatement.Type, - firstInitializer != null ? firstInitializer.Initializer : null, - false); - - int initializerCount = variableDeclarationStatement.Variables.Count; - ResolveResult result = null; - for (AstNode node = variableDeclarationStatement.FirstChild; node != null; node = node.NextSibling) { - if (node.Role == VariableDeclarationStatement.Roles.Variable) { - VariableInitializer vi = (VariableInitializer)node; - - IConstantValue cv = null; - if (isConst) - throw new NotImplementedException(); - resolver.AddVariable(type, new DomRegion (parsedFile.FileName, vi.StartLocation, vi.EndLocation), vi.Name, cv); - - if (resolverEnabled && initializerCount == 1) { - result = Resolve(node); - } else { - Scan(node); - } - } else { - Scan(node); - } - } - return result; - } - #endregion - - #region Local Variable Type Inference - /// - /// Creates a type reference for the specified type node. - /// If the type node is 'var', performs type inference on the initializer expression. - /// - ITypeReference MakeTypeReference(AstType type, AstNode initializerExpression, bool isForEach) - { - if (initializerExpression != null && IsVar(type)) { - return new VarTypeReference(this, resolver.Clone(), initializerExpression, isForEach); - } else { - return MakeTypeReference(type); - } - } - - ITypeReference MakeTypeReference(AstType type) - { - return TypeSystemConvertVisitor.ConvertType(type, resolver.CurrentTypeDefinition, resolver.CurrentMember as IMethod, resolver.UsingScope, false); - } - - static bool IsVar(AstType returnType) - { - return returnType is SimpleType - && ((SimpleType)returnType).Identifier == "var" - && ((SimpleType)returnType).TypeArguments.Count == 0; - } - - sealed class VarTypeReference : ITypeReference - { - ResolveVisitor visitor; - CSharpResolver storedContext; - AstNode initializerExpression; - bool isForEach; - - IType result; - - public VarTypeReference(ResolveVisitor visitor, CSharpResolver storedContext, AstNode initializerExpression, bool isForEach) - { - this.visitor = visitor; - this.storedContext = storedContext; - this.initializerExpression = initializerExpression; - this.isForEach = isForEach; - } - - public IType Resolve(ITypeResolveContext context) - { - if (visitor == null) - return result ?? SharedTypes.UnknownType; - - var oldMode = visitor.mode; - var oldResolver = visitor.resolver; - try { - visitor.mode = ResolveVisitorNavigationMode.Resolve; - visitor.resolver = storedContext; - - result = visitor.Resolve(initializerExpression).Type; - - if (isForEach) { - result = GetElementType(result); - } - - return result; - } finally { - visitor.mode = oldMode; - visitor.resolver = oldResolver; - - visitor = null; - storedContext = null; - initializerExpression = null; - } - } - - IType GetElementType(IType result) - { - foreach (IType baseType in result.GetAllBaseTypes(storedContext.Context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && baseTypeDef.Name == "IEnumerable") { - if (baseTypeDef.Namespace == "System.Collections.Generic" && baseTypeDef.TypeParameterCount == 1) { - ParameterizedType pt = baseType as ParameterizedType; - if (pt != null) { - return pt.TypeArguments[0]; - } - } else if (baseTypeDef.Namespace == "System.Collections" && baseTypeDef.TypeParameterCount == 0) { - return KnownTypeReference.Object.Resolve(storedContext.Context); - } - } - } - return SharedTypes.UnknownType; - } - - public override string ToString() - { - if (visitor == null) - return "var=" + result; - else - return "var (not yet resolved)"; - } - } - #endregion - - #region Attributes - ITypeReference GetAttributeType (Attribute attribute) - { - var withoutSuffix = MakeTypeReference(attribute.Type); - ITypeReference withSuffix; - if (attribute.Type is SimpleType) { - var st = (SimpleType)attribute.Type; - withSuffix = MakeTypeReference(new SimpleType (st.Identifier + "Attribute")); - } else if (attribute.Type is MemberType) { - var mt = (MemberType)attribute.Type; - withSuffix = MakeTypeReference(new MemberType (mt.Target.Clone (), mt.MemberName + "Attribute")); - } else { - // unsupported type. - return SharedTypes.UnknownType; - } - return new AttributeTypeReference(withoutSuffix, withSuffix); - } - - public override ResolveResult VisitAttribute(Attribute attribute, object data) - { - ScanChildren(attribute); - if (resolverEnabled) { - var type = GetAttributeType (attribute).Resolve (resolver.Context); - if (!attribute.HasArgumentList) - return new TypeResolveResult (type); - // try if the attribute usage references a constructuor - string[] argumentNames; - ResolveResult[] arguments = GetArguments(attribute.Arguments, out argumentNames); - var result = resolver.ResolveObjectCreation(type, arguments, argumentNames); - Console.WriteLine (result); - // if this is an error give back type resolve result, an attribute arg list isn't a constructor reference - // in all cases. - is it better to always give back the type resolve result ? - if (result.IsError) - return new TypeResolveResult (type); - return result; - } - return null; - } - #endregion - - #region Using Declaration - public override ResolveResult VisitUsingDeclaration(UsingDeclaration usingDeclaration, object data) - { - // TODO: set isInUsingDeclaration - ScanChildren(usingDeclaration); - return null; - } - - public override ResolveResult VisitUsingAliasDeclaration(UsingAliasDeclaration usingDeclaration, object data) - { - // TODO: set isInUsingDeclaration - ScanChildren(usingDeclaration); - return null; - } - #endregion - - #region Type References - public override ResolveResult VisitPrimitiveType(PrimitiveType primitiveType, object data) - { - ScanChildren(primitiveType); - return new TypeResolveResult(ResolveType(primitiveType)); - } - - public override ResolveResult VisitSimpleType(SimpleType simpleType, object data) - { - ScanChildren(simpleType); - return ResolveTypeOrNamespace(simpleType); - } - - ResolveResult ResolveTypeOrNamespace(AstType type) - { - ITypeReference typeRef = MakeTypeReference(type); - ITypeOrNamespaceReference typeOrNsRef = typeRef as ITypeOrNamespaceReference; - if (typeOrNsRef != null) { - return typeOrNsRef.DoResolve(resolver.Context); - } else { - return new TypeResolveResult(typeRef.Resolve(resolver.Context)); - } - } - - public override ResolveResult VisitMemberType(MemberType memberType, object data) - { - ScanChildren(memberType); - return ResolveTypeOrNamespace(memberType); - } - - public override ResolveResult VisitComposedType(ComposedType composedType, object data) - { - ScanChildren(composedType); - return new TypeResolveResult(ResolveType(composedType)); - } - #endregion - - #region Query Expressions - public override ResolveResult VisitQueryExpression(QueryExpression queryExpression, object data) - { - throw new NotImplementedException(); - } - #endregion - - public override ResolveResult VisitConstructorInitializer(ConstructorInitializer constructorInitializer, object data) - { - ScanChildren(constructorInitializer); - return null; - } - - public override ResolveResult VisitArrayInitializerExpression(ArrayInitializerExpression arrayInitializerExpression, object data) - { - // TODO: array initializers are valid expressions if the parent node is a variable/field declaration - // that explicitly defines an array type - return errorResult; - } - - public override ResolveResult VisitNamedArgumentExpression(NamedArgumentExpression namedArgumentExpression, object data) - { - throw new NotImplementedException(); - } - - public override ResolveResult VisitFixedVariableInitializer(FixedVariableInitializer fixedVariableInitializer, object data) - { - throw new NotImplementedException(); - } - - #region Token Nodes - public override ResolveResult VisitIdentifier(Identifier identifier, object data) - { - return null; - } - - public override ResolveResult VisitComment(Comment comment, object data) - { - return null; - } - - public override ResolveResult VisitCSharpTokenNode(CSharpTokenNode cSharpTokenNode, object data) - { - return null; - } - #endregion - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs b/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs deleted file mode 100644 index 12699dd1c..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/SimpleTypeOrNamespaceReference.cs +++ /dev/null @@ -1,74 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// Represents a simple C# name. (a single non-qualified identifier with an optional list of type arguments) - /// - public sealed class SimpleTypeOrNamespaceReference : ITypeOrNamespaceReference - { - readonly ITypeDefinition parentTypeDefinition; - readonly UsingScope parentUsingScope; - readonly string identifier; - readonly IList typeArguments; - readonly bool isInUsingDeclaration; - - public SimpleTypeOrNamespaceReference(string identifier, IList typeArguments, ITypeDefinition parentTypeDefinition, UsingScope parentUsingScope, bool isInUsingDeclaration = false) - { - if (identifier == null) - throw new ArgumentNullException("identifier"); - this.identifier = identifier; - this.typeArguments = typeArguments ?? EmptyList.Instance; - this.parentTypeDefinition = parentTypeDefinition; - this.parentUsingScope = parentUsingScope; - this.isInUsingDeclaration = isInUsingDeclaration; - } - - /// - /// Adds a suffix to the identifier. - /// Does not modify the existing type reference, but returns a new one. - /// - public SimpleTypeOrNamespaceReference AddSuffix(string suffix) - { - return new SimpleTypeOrNamespaceReference(identifier + suffix, typeArguments, parentTypeDefinition, parentUsingScope, isInUsingDeclaration); - } - - public ResolveResult DoResolve(ITypeResolveContext context) - { - CSharpResolver r = new CSharpResolver(context); - r.CurrentTypeDefinition = parentTypeDefinition != null ? parentTypeDefinition.GetCompoundClass() : null; - r.UsingScope = parentUsingScope; - IType[] typeArgs = new IType[typeArguments.Count]; - for (int i = 0; i < typeArgs.Length; i++) { - typeArgs[i] = typeArguments[i].Resolve(context); - } - return r.LookupSimpleNamespaceOrTypeName(identifier, typeArgs, isInUsingDeclaration); - } - - public NamespaceResolveResult ResolveNamespace(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible - return DoResolve(context) as NamespaceResolveResult; - } - - public IType Resolve(ITypeResolveContext context) - { - // TODO: use resolve context for original project, if possible; then map the result type into the new context - TypeResolveResult rr = DoResolve(context) as TypeResolveResult; - return rr != null ? rr.Type : SharedTypes.UnknownType; - } - - public override string ToString() - { - if (typeArguments.Count == 0) - return identifier; - else - return identifier + "<" + DotNet35Compat.StringJoin(",", typeArguments) + ">"; - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs b/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs deleted file mode 100644 index 093d77c7f..000000000 --- a/ICSharpCode.NRefactory/CSharp/Resolver/TypeResolveResult.cs +++ /dev/null @@ -1,19 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using ICSharpCode.NRefactory.TypeSystem; - -namespace ICSharpCode.NRefactory.CSharp.Resolver -{ - /// - /// The resolved expression refers to a type name. - /// - public class TypeResolveResult : ResolveResult - { - public TypeResolveResult(IType type) - : base(type) - { - } - } -} diff --git a/ICSharpCode.NRefactory/Completion/DisplayFlags.cs b/ICSharpCode.NRefactory/Completion/DisplayFlags.cs new file mode 100644 index 000000000..ae4e1fe5f --- /dev/null +++ b/ICSharpCode.NRefactory/Completion/DisplayFlags.cs @@ -0,0 +1,38 @@ +// +// DisplayFlags.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; + +namespace ICSharpCode.NRefactory.Completion +{ + [Flags] + public enum DisplayFlags + { + None = 0, + Hidden = 1, + Obsolete = 2 + } +} + diff --git a/ICSharpCode.NRefactory/Completion/ICompletionData.cs b/ICSharpCode.NRefactory/Completion/ICompletionData.cs new file mode 100644 index 000000000..832075513 --- /dev/null +++ b/ICSharpCode.NRefactory/Completion/ICompletionData.cs @@ -0,0 +1,47 @@ +// +// ICompletionData.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; + +namespace ICSharpCode.NRefactory.Completion +{ + public interface ICompletionData + { + string DisplayText { get; set; } + string Description { get; set; } + + DisplayFlags DisplayFlags { get; set; } + + bool HasOverloads { + get; + } + + IEnumerable OverloadedData { + get; + } + } +} diff --git a/ICSharpCode.NRefactory/Completion/ICompletionDataFactory.cs b/ICSharpCode.NRefactory/Completion/ICompletionDataFactory.cs new file mode 100644 index 000000000..41000503b --- /dev/null +++ b/ICSharpCode.NRefactory/Completion/ICompletionDataFactory.cs @@ -0,0 +1,49 @@ +// +// ICompletionDataFactory.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Completion +{ + public interface ICompletionDataFactory + { + ICompletionData CreateEntityCompletionData (IEntity entity); + + /// + /// Creates a generic completion data. + /// + /// + /// The title of the completion data + /// + /// + /// The description of the literal. + /// + /// + /// The insert text. If null, title is taken. + /// + ICompletionData CreateLiteralCompletionData (string title, string description, string insertText = null); + } +} diff --git a/ICSharpCode.NRefactory/Completion/IEntityCompletionData.cs b/ICSharpCode.NRefactory/Completion/IEntityCompletionData.cs new file mode 100644 index 000000000..0744f4723 --- /dev/null +++ b/ICSharpCode.NRefactory/Completion/IEntityCompletionData.cs @@ -0,0 +1,37 @@ +// +// IEntityCompletionData.cs +// +// Author: +// Mike Krüger +// +// Copyright (c) 2011 Xamarin Inc. (http://xamarin.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. +using System; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Completion +{ + public interface IEntityCompletionData : ICompletionData + { + IEntity Entity { + get; + } + } +} diff --git a/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs b/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs new file mode 100644 index 000000000..0131125c5 --- /dev/null +++ b/ICSharpCode.NRefactory/Documentation/IDStringProvider.cs @@ -0,0 +1,284 @@ +// 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.Collections.Generic; +using System.Text; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.Documentation +{ + /// + /// Provides ID strings for entities. (C# 4.0 spec, §A.3.1) + /// ID strings are used to identify members in XML documentation files. + /// + public static class IDStringProvider + { + /// + /// Gets the ID string (C# 4.0 spec, §A.3.1) for the specified entity. + /// + /// + /// The type resolve context is optional and is not needed for entities loaded from assemblies: + /// This method can get the ID string for any type reference produced by the CecilLoader without + /// having to resolve the type reference. + /// + public static string GetIDString(IEntity entity, ITypeResolveContext context = null) + { + StringBuilder b = new StringBuilder(); + switch (entity.EntityType) { + case EntityType.TypeDefinition: + b.Append("T:"); + AppendTypeName(b, (ITypeDefinition)entity); + return b.ToString(); + case EntityType.Field: + b.Append("F:"); + break; + case EntityType.Property: + case EntityType.Indexer: + b.Append("P:"); + break; + case EntityType.Event: + b.Append("E:"); + break; + default: + b.Append("M:"); + break; + } + IMember member = (IMember)entity; + AppendTypeName(b, member.DeclaringType); + b.Append('.'); + b.Append(member.Name.Replace('.', '#')); + IMethod method = member as IMethod; + if (method != null && method.TypeParameters.Count > 0) { + b.Append("``"); + b.Append(method.TypeParameters.Count); + } + IParameterizedMember parameterizedMember = member as IParameterizedMember; + if (parameterizedMember != null && parameterizedMember.Parameters.Count > 0) { + b.Append('('); + var parameters = parameterizedMember.Parameters; + for (int i = 0; i < parameters.Count; i++) { + if (i > 0) b.Append(','); + AppendTypeName(b, parameters[i].Type, context); + } + b.Append(')'); + } + if (member.EntityType == EntityType.Operator && (member.Name == "op_Implicit" || member.Name == "op_Explicit")) { + b.Append('~'); + AppendTypeName(b, member.ReturnType, context); + } + return b.ToString(); + } + + public static string GetTypeName(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + StringBuilder b = new StringBuilder(); + AppendTypeName(b, type); + return b.ToString(); + } + + static void AppendTypeName(StringBuilder b, IType type) + { + switch (type.Kind) { + case TypeKind.Dynamic: + b.Append("System.Object"); + break; + case TypeKind.TypeParameter: + ITypeParameter tp = (ITypeParameter)type; + b.Append('`'); + if (tp.OwnerType == EntityType.Method) + b.Append('`'); + b.Append(tp.Index); + break; + case TypeKind.Array: + ArrayType array = (ArrayType)type; + AppendTypeName(b, array.ElementType); + b.Append('['); + if (array.Dimensions > 1) { + for (int i = 0; i < array.Dimensions; i++) { + if (i > 0) b.Append(','); + b.Append("0:"); + } + } + b.Append(']'); + break; + case TypeKind.Pointer: + AppendTypeName(b, ((PointerType)type).ElementType); + b.Append('*'); + break; + case TypeKind.ByReference: + AppendTypeName(b, ((ByReferenceType)type).ElementType); + b.Append('@'); + break; + default: + IType declType = type.DeclaringType; + if (declType != null) { + AppendTypeName(b, declType); + b.Append('.'); + b.Append(type.Name); + AppendTypeParameters(b, type, declType.TypeParameterCount); + } else { + b.Append(type.FullName); + AppendTypeParameters(b, type, 0); + } + break; + } + } + + static void AppendTypeParameters(StringBuilder b, IType type, int outerTypeParameterCount) + { + int tpc = type.TypeParameterCount - outerTypeParameterCount; + if (tpc > 0) { + ParameterizedType pt = type as ParameterizedType; + if (pt != null) { + b.Append('{'); + var ta = pt.TypeArguments; + for (int i = outerTypeParameterCount; i < ta.Count; i++) { + if (i > outerTypeParameterCount) b.Append(','); + AppendTypeName(b, ta[i]); + } + b.Append('}'); + } else { + b.Append('`'); + b.Append(tpc); + } + } + } + + static void AppendTypeName(StringBuilder b, ITypeReference type, ITypeResolveContext context) + { + IType resolvedType = type as IType; + if (resolvedType != null) { + AppendTypeName(b, resolvedType); + return; + } + KnownTypeReference knownType = type as KnownTypeReference; + if (knownType != null) { + if (!string.IsNullOrEmpty(knownType.Namespace)) { + b.Append(knownType.Namespace); + b.Append('.'); + } + b.Append(knownType.Name); + return; + } + GetClassTypeReference gctr = type as GetClassTypeReference; + if (gctr != null) { + if (!string.IsNullOrEmpty(gctr.Namespace)) { + b.Append(gctr.Namespace); + b.Append('.'); + } + b.Append(gctr.Name); + if (gctr.TypeParameterCount > 0) { + b.Append('`'); + b.Append(gctr.TypeParameterCount); + } + return; + } + NestedTypeReference ntr = type as NestedTypeReference; + if (ntr != null) { + AppendTypeName(b, ntr.DeclaringTypeReference, context); + b.Append('.'); + b.Append(ntr.Name); + if (ntr.AdditionalTypeParameterCount > 0) { + b.Append('`'); + b.Append(ntr.AdditionalTypeParameterCount); + } + return; + } + ParameterizedTypeReference pt = type as ParameterizedTypeReference; + if (pt != null && IsGetClassTypeReference(pt.GenericType)) { + AppendParameterizedTypeName(b, pt.GenericType, pt.TypeArguments, context); + return; + } + ArrayTypeReference array = type as ArrayTypeReference; + if (array != null) { + AppendTypeName(b, array.ElementType, context); + b.Append('['); + if (array.Dimensions > 1) { + for (int i = 0; i < array.Dimensions; i++) { + if (i > 0) b.Append(','); + b.Append("0:"); + } + } + b.Append(']'); + return; + } + PointerTypeReference ptr = type as PointerTypeReference; + if (ptr != null) { + AppendTypeName(b, ptr.ElementType, context); + b.Append('*'); + return; + } + ByReferenceTypeReference brtr = type as ByReferenceTypeReference; + if (brtr != null) { + AppendTypeName(b, brtr.ElementType, context); + b.Append('@'); + return; + } + if (context == null) + b.Append('?'); + else + AppendTypeName(b, type.Resolve(context)); + } + + static bool IsGetClassTypeReference(ITypeReference type) + { + NestedTypeReference ntr; + while ((ntr = type as NestedTypeReference) != null) + type = ntr.DeclaringTypeReference; + return type is GetClassTypeReference; + } + + static int AppendParameterizedTypeName(StringBuilder b, ITypeReference type, IList typeArguments, ITypeResolveContext context) + { + GetClassTypeReference gctr = type as GetClassTypeReference; + if (gctr != null) { + if (!string.IsNullOrEmpty(gctr.Namespace)) { + b.Append(gctr.Namespace); + b.Append('.'); + } + b.Append(gctr.Name); + if (gctr.TypeParameterCount > 0) { + b.Append('{'); + for (int i = 0; i < gctr.TypeParameterCount && i < typeArguments.Count; i++) { + if (i > 0) b.Append(','); + AppendTypeName(b, typeArguments[i], context); + } + b.Append('}'); + } + return gctr.TypeParameterCount; + } else { + NestedTypeReference ntr = (NestedTypeReference)type; + int outerTpc = AppendParameterizedTypeName(b, ntr.DeclaringTypeReference, typeArguments, context); + b.Append('.'); + if (ntr.AdditionalTypeParameterCount > 0) { + b.Append('{'); + for (int i = 0; i < ntr.AdditionalTypeParameterCount && i + outerTpc < typeArguments.Count; i++) { + if (i > 0) b.Append(','); + AppendTypeName(b, typeArguments[i + outerTpc], context); + } + b.Append('}'); + } + return outerTpc + ntr.AdditionalTypeParameterCount; + } + } + } +} diff --git a/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs b/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs index 70d88aa16..e16d15799 100644 --- a/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs +++ b/ICSharpCode.NRefactory/Documentation/XmlDocumentationProvider.cs @@ -1,12 +1,27 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Runtime.Serialization; using System.Xml; - using ICSharpCode.NRefactory.TypeSystem; namespace ICSharpCode.NRefactory.Documentation @@ -18,7 +33,8 @@ 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. /// - public class XmlDocumentationProvider : IDocumentationProvider + [Serializable] + public class XmlDocumentationProvider : IDocumentationProvider, IDeserializationCallback { #region Cache sealed class XmlDocumentationCache @@ -51,6 +67,7 @@ namespace ICSharpCode.NRefactory.Documentation } #endregion + [Serializable] struct IndexEntry : IComparable { /// @@ -75,7 +92,9 @@ namespace ICSharpCode.NRefactory.Documentation } } - readonly XmlDocumentationCache cache = new XmlDocumentationCache(); + [NonSerialized] + XmlDocumentationCache cache = new XmlDocumentationCache(); + readonly string fileName; DateTime lastWriteDate; IndexEntry[] index; // SORTED array of index entries @@ -90,22 +109,26 @@ namespace ICSharpCode.NRefactory.Documentation if (fileName == null) throw new ArgumentNullException("fileName"); - using (XmlTextReader xmlReader = new XmlTextReader(fileName)) { - xmlReader.XmlResolver = null; // no DTD resolving - xmlReader.MoveToContent(); - if (string.IsNullOrEmpty(xmlReader.GetAttribute("redirect"))) { - this.fileName = fileName; - ReadXmlDoc(xmlReader); - } else { - string redirectionTarget = GetRedirectionTarget(xmlReader.GetAttribute("redirect")); - if (redirectionTarget != null) { - Debug.WriteLine("XmlDoc " + fileName + " is redirecting to " + redirectionTarget); - using (XmlTextReader redirectedXmlReader = new XmlTextReader(redirectionTarget)) { - this.fileName = redirectionTarget; - ReadXmlDoc(redirectedXmlReader); - } + using (FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { + using (XmlTextReader xmlReader = new XmlTextReader(fs)) { + xmlReader.XmlResolver = null; // no DTD resolving + xmlReader.MoveToContent(); + if (string.IsNullOrEmpty(xmlReader.GetAttribute("redirect"))) { + this.fileName = fileName; + ReadXmlDoc(xmlReader); } else { - throw new XmlException("XmlDoc " + fileName + " is redirecting to " + xmlReader.GetAttribute("redirect") + ", but that file was not found."); + string redirectionTarget = GetRedirectionTarget(xmlReader.GetAttribute("redirect")); + if (redirectionTarget != null) { + Debug.WriteLine("XmlDoc " + fileName + " is redirecting to " + redirectionTarget); + using (FileStream redirectedFs = new FileStream(redirectionTarget, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete)) { + using (XmlTextReader redirectedXmlReader = new XmlTextReader(redirectedFs)) { + this.fileName = redirectionTarget; + ReadXmlDoc(redirectedXmlReader); + } + } + } else { + throw new XmlException("XmlDoc " + fileName + " is redirecting to " + xmlReader.GetAttribute("redirect") + ", but that file was not found."); + } } } } @@ -138,7 +161,11 @@ namespace ICSharpCode.NRefactory.Documentation return dir + Path.DirectorySeparatorChar; } - internal static string LookupLocalizedXmlDoc(string fileName) + /// + /// Given the assembly file name, looks up the XML documentation file name. + /// Returns null if no XML documentation file is found. + /// + public static string LookupLocalizedXmlDoc(string fileName) { string xmlFileName = Path.ChangeExtension(fileName, ".xml"); string currentCulture = System.Threading.Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName; @@ -242,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; @@ -305,7 +334,7 @@ namespace ICSharpCode.NRefactory.Documentation /// public string GetDocumentation(IEntity entity) { - return GetDocumentation(GetDocumentationKey(entity)); + return GetDocumentation(IDStringProvider.GetIDString(entity)); } /// @@ -366,13 +395,9 @@ namespace ICSharpCode.NRefactory.Documentation } #endregion - #region GetDocumentationKey - public static string GetDocumentationKey(IEntity entity) + public virtual void OnDeserialization(object sender) { - if (entity == null) - throw new ArgumentNullException("entity"); - throw new NotImplementedException(); + cache = new XmlDocumentationCache(); } - #endregion } } diff --git a/ICSharpCode.Editor/IDocument.cs b/ICSharpCode.NRefactory/Editor/IDocument.cs similarity index 74% rename from ICSharpCode.Editor/IDocument.cs rename to ICSharpCode.NRefactory/Editor/IDocument.cs index 925eaee66..07057cdb3 100644 --- a/ICSharpCode.Editor/IDocument.cs +++ b/ICSharpCode.NRefactory/Editor/IDocument.cs @@ -1,9 +1,24 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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; -namespace ICSharpCode.Editor +namespace ICSharpCode.NRefactory.Editor { /// /// A document representing a source code file for refactoring. @@ -18,20 +33,41 @@ namespace ICSharpCode.Editor new string Text { get; set; } // hides TextBuffer.Text to add the setter /// - /// Is raised when the Text property changes. + /// This event is called directly before a change is applied to the document. + /// + /// + /// It is invalid to modify the document within this event handler. + /// Aborting the change (by throwing an exception) is likely to cause corruption of data structures + /// that listen to the Changing and Changed events. + /// + event EventHandler TextChanging; + + /// + /// This event is called directly after a change is applied to the document. + /// + /// + /// It is invalid to modify the document within this event handler. + /// Aborting the event handler (by throwing an exception) is likely to cause corruption of data structures + /// that listen to the Changing and Changed events. + /// + event EventHandler TextChanged; + + /// + /// This event is called after a group of changes is completed. /// - event EventHandler TextChanged; + /// + event EventHandler ChangeCompleted; /// - /// Gets the total number of lines in the document. + /// Gets the number of lines in the document. /// - int TotalNumberOfLines { get; } + int LineCount { get; } /// /// Gets the document line with the specified number. /// /// The number of the line to retrieve. The first line has number 1. - IDocumentLine GetLine(int lineNumber); + IDocumentLine GetLineByNumber(int lineNumber); /// /// Gets the document line that contains the specified offset. @@ -117,25 +153,5 @@ namespace ICSharpCode.Editor /// /// ITextAnchor CreateAnchor(int offset); - - /// - /// This event is called directly before a change is applied to the document. - /// - /// - /// It is invalid to modify the document within this event handler. - /// Aborting the change (by throwing an exception) is likely to cause corruption of data structures - /// that listen to the Changing and Changed events. - /// - event EventHandler Changing; - - /// - /// This event is called directly after a change is applied to the document. - /// - /// - /// It is invalid to modify the document within this event handler. - /// Aborting the event handler (by throwing an exception) is likely to cause corruption of data structures - /// that listen to the Changing and Changed events. - /// - event EventHandler Changed; } } diff --git a/ICSharpCode.NRefactory/Editor/IDocumentLine.cs b/ICSharpCode.NRefactory/Editor/IDocumentLine.cs new file mode 100644 index 000000000..0471509fd --- /dev/null +++ b/ICSharpCode.NRefactory/Editor/IDocumentLine.cs @@ -0,0 +1,55 @@ +// 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; + +namespace ICSharpCode.NRefactory.Editor +{ + /// + /// A line inside a . + /// + public interface IDocumentLine : ISegment + { + /// + /// Gets the length of this line, including the line delimiter. + /// + int TotalLength { get; } + + /// + /// Gets the length of the line terminator. + /// Returns 1 or 2; or 0 at the end of the document. + /// + int DelimiterLength { get; } + + /// + /// Gets the number of this line. + /// The first line has the number 1. + /// + int LineNumber { get; } + + /// + /// Gets the previous line. Returns null if this is the first line in the document. + /// + IDocumentLine PreviousLine { get; } + + /// + /// Gets the next line. Returns null if this is the last line in the document. + /// + IDocumentLine NextLine { get; } + } +} diff --git a/ICSharpCode.NRefactory/Editor/ISegment.cs b/ICSharpCode.NRefactory/Editor/ISegment.cs new file mode 100644 index 000000000..f0e430ec0 --- /dev/null +++ b/ICSharpCode.NRefactory/Editor/ISegment.cs @@ -0,0 +1,70 @@ +// 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; + +namespace ICSharpCode.NRefactory.Editor +{ + /// + /// An (Offset,Length)-pair. + /// + public interface ISegment + { + /// + /// Gets the start offset of the segment. + /// + int Offset { get; } + + /// + /// Gets the length of the segment. + /// + /// For line segments (IDocumentLine), the length does not include the line delimeter. + int Length { get; } + + /// + /// Gets the end offset of the segment. + /// + /// EndOffset = Offset + Length; + int EndOffset { get; } + } + + /// + /// Extension methods for . + /// + public static class ISegmentExtensions + { + /// + /// Gets whether the segment contains the offset. + /// + /// + /// True, if offset is between segment.Start and segment.End (inclusive); otherwise, false. + /// + public static bool Contains (this ISegment segment, int offset) + { + return segment.Offset <= offset && offset <= segment.EndOffset; + } + + /// + /// True, if the segment contains the specified segment, false otherwise. + /// + public static bool Contains (this ISegment thisSegment, ISegment segment) + { + return segment != null && thisSegment.Offset <= segment.Offset && segment.EndOffset <= thisSegment.EndOffset; + } + } +} diff --git a/ICSharpCode.Editor/ITextAnchor.cs b/ICSharpCode.NRefactory/Editor/ITextAnchor.cs similarity index 58% rename from ICSharpCode.Editor/ITextAnchor.cs rename to ICSharpCode.NRefactory/Editor/ITextAnchor.cs index dfc95c9e7..6020ddc8d 100644 --- a/ICSharpCode.Editor/ITextAnchor.cs +++ b/ICSharpCode.NRefactory/Editor/ITextAnchor.cs @@ -1,9 +1,24 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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; -namespace ICSharpCode.Editor +namespace ICSharpCode.NRefactory.Editor { /// /// The TextAnchor class references an offset (a position between two characters). @@ -45,23 +60,45 @@ namespace ICSharpCode.Editor /// /// Controls how the anchor moves. /// + /// Anchor movement is ambiguous if text is inserted exactly at the anchor's location. + /// Does the anchor stay before the inserted text, or does it move after it? + /// The property will be used to determine which of these two options the anchor will choose. + /// The default value is . AnchorMovementType MovementType { get; set; } /// + /// /// Specifies whether the anchor survives deletion of the text containing it. + /// /// false: The anchor is deleted when the a selection that includes the anchor is deleted. /// true: The anchor is not deleted. + /// /// + /// bool SurviveDeletion { get; set; } /// /// Gets whether the anchor was deleted. /// + /// + /// When a piece of text containing an anchor is removed, then that anchor will be deleted. + /// First, the property is set to true on all deleted anchors, + /// then the events are raised. + /// You cannot retrieve the offset from an anchor that has been deleted. + /// This deletion behavior might be useful when using anchors for building a bookmark feature, + /// but in other cases you want to still be able to use the anchor. For those cases, set = true. + /// bool IsDeleted { get; } /// /// Occurs after the anchor was deleted. /// + /// + /// + /// Due to the 'weak reference' nature of text anchors, you will receive + /// the Deleted event only while your code holds a reference to the TextAnchor object. + /// + /// event EventHandler Deleted; /// diff --git a/ICSharpCode.Editor/ITextSource.cs b/ICSharpCode.NRefactory/Editor/ITextSource.cs similarity index 69% rename from ICSharpCode.Editor/ITextSource.cs rename to ICSharpCode.NRefactory/Editor/ITextSource.cs index d5c6f9e9f..2b894121b 100644 --- a/ICSharpCode.Editor/ITextSource.cs +++ b/ICSharpCode.NRefactory/Editor/ITextSource.cs @@ -1,11 +1,26 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.IO; -namespace ICSharpCode.Editor +namespace ICSharpCode.NRefactory.Editor { /// /// A read-only view on a (potentially mutable) text source. @@ -82,11 +97,31 @@ namespace ICSharpCode.Editor /// Gets the index of the first occurrence of any character in the specified array. /// /// Characters to search for - /// Start index of the search. + /// Start index of the area to search. /// Length of the area to search. /// The first index where any character was found; or -1 if no occurrence was found. int IndexOfAny(char[] anyOf, int startIndex, int count); + /// + /// Gets the index of the first occurrence of the specified search text in this text source. + /// + /// The search text + /// Start index of the area to search. + /// Length of the area to search. + /// String comparison to use. + /// The first index where the search term was found; or -1 if no occurrence was found. + int IndexOf(string searchText, int startIndex, int count, StringComparison comparisonType); + + /// + /// Gets the index of the last occurrence of the specified search text in this text source. + /// + /// The search text + /// Start index of the area to search. + /// Length of the area to search. + /// String comparison to use. + /// The last index where the search term was found; or -1 if no occurrence was found. + int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType); + /* What about: void Insert (int offset, string value); void Remove (int offset, int count); @@ -101,7 +136,7 @@ namespace ICSharpCode.Editor IEnumerable SearchBackward (string pattern, int startIndex); IEnumerable SearchBackwardIgnoreCase (string pattern, int startIndex); - */ + */ } /// diff --git a/ICSharpCode.Editor/ReadOnlyDocument.cs b/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs similarity index 73% rename from ICSharpCode.Editor/ReadOnlyDocument.cs rename to ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs index d175cea82..0d5e81006 100644 --- a/ICSharpCode.Editor/ReadOnlyDocument.cs +++ b/ICSharpCode.NRefactory/Editor/ReadOnlyDocument.cs @@ -1,10 +1,25 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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.Collections.Generic; -namespace ICSharpCode.Editor +namespace ICSharpCode.NRefactory.Editor { /// /// Read-only implementation of . @@ -48,7 +63,7 @@ namespace ICSharpCode.Editor } /// - public IDocumentLine GetLine(int lineNumber) + public IDocumentLine GetLineByNumber(int lineNumber) { if (lineNumber < 1 || lineNumber > lines.Length) throw new ArgumentOutOfRangeException("lineNumber", lineNumber, "Value must be between 1 and " + lines.Length); @@ -96,6 +111,24 @@ namespace ICSharpCode.Editor public int LineNumber { get { return lineNumber; } } + + public IDocumentLine PreviousLine { + get { + if (lineNumber == 1) + return null; + else + return new ReadOnlyDocumentLine(doc, lineNumber - 1); + } + } + + public IDocumentLine NextLine { + get { + if (lineNumber == doc.LineCount) + return null; + else + return new ReadOnlyDocumentLine(doc, lineNumber + 1); + } + } } int GetStartOffset(int lineNumber) @@ -121,7 +154,7 @@ namespace ICSharpCode.Editor /// public IDocumentLine GetLineByOffset(int offset) { - return GetLine(GetLineNumberForOffset(offset)); + return GetLineByNumber(GetLineNumberForOffset(offset)); } int GetLineNumberForOffset(int offset) @@ -136,10 +169,10 @@ namespace ICSharpCode.Editor if (line < 1 || line > lines.Length) throw new ArgumentOutOfRangeException("line", line, "Value must be between 1 and " + lines.Length); int lineStart = GetStartOffset(line); - if (column <= 0) + if (column <= 1) return lineStart; int lineEnd = GetEndOffset(line); - if (column >= lineEnd - lineStart) + if (column - 1 >= lineEnd - lineStart) return lineEnd; return lineStart + column - 1; } @@ -156,7 +189,7 @@ namespace ICSharpCode.Editor if (offset < 0 || offset > textSource.TextLength) throw new ArgumentOutOfRangeException("offset", offset, "Value must be between 0 and " + textSource.TextLength); int line = GetLineNumberForOffset(offset); - return new TextLocation(offset-GetStartOffset(line)+1, line); + return new TextLocation(line, offset-GetStartOffset(line)+1); } /// @@ -168,7 +201,7 @@ namespace ICSharpCode.Editor } /// - public int TotalNumberOfLines { + public int LineCount { get { return lines.Length; } } @@ -181,11 +214,11 @@ namespace ICSharpCode.Editor get { return textSource.TextLength; } } - event EventHandler IDocument.Changing { add {} remove {} } + event EventHandler IDocument.TextChanging { add {} remove {} } - event EventHandler IDocument.Changed { add {} remove {} } + event EventHandler IDocument.TextChanged { add {} remove {} } - event EventHandler IDocument.TextChanged { add {} remove {} } + event EventHandler IDocument.ChangeCompleted { add {} remove {} } void IDocument.Insert(int offset, string text) { @@ -313,7 +346,18 @@ namespace ICSharpCode.Editor } /// - public object GetService(Type serviceType) + public int IndexOf(string searchText, int startIndex, int count, StringComparison comparisonType) + { + return textSource.IndexOf(searchText, startIndex, count, comparisonType); + } + + /// + public int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType) + { + return textSource.LastIndexOf(searchText, startIndex, count, comparisonType); + } + + object IServiceProvider.GetService(Type serviceType) { return null; } diff --git a/ICSharpCode.Editor/StringTextSource.cs b/ICSharpCode.NRefactory/Editor/StringTextSource.cs similarity index 52% rename from ICSharpCode.Editor/StringTextSource.cs rename to ICSharpCode.NRefactory/Editor/StringTextSource.cs index 1d5d3386f..f54558be9 100644 --- a/ICSharpCode.Editor/StringTextSource.cs +++ b/ICSharpCode.NRefactory/Editor/StringTextSource.cs @@ -1,10 +1,25 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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; -namespace ICSharpCode.Editor +namespace ICSharpCode.NRefactory.Editor { /// /// Implements the ITextSource interface using a string. @@ -87,5 +102,17 @@ namespace ICSharpCode.Editor { return text.IndexOfAny(anyOf, startIndex, count); } + + /// + public int IndexOf(string searchText, int startIndex, int count, StringComparison comparisonType) + { + return text.IndexOf(searchText, startIndex, count, comparisonType); + } + + /// + public int LastIndexOf(string searchText, int startIndex, int count, StringComparison comparisonType) + { + return text.LastIndexOf(searchText, startIndex, count, comparisonType); + } } } diff --git a/ICSharpCode.Editor/TextChangeEventArgs.cs b/ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs similarity index 50% rename from ICSharpCode.Editor/TextChangeEventArgs.cs rename to ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs index 385f5104a..a0c0f659e 100644 --- a/ICSharpCode.Editor/TextChangeEventArgs.cs +++ b/ICSharpCode.NRefactory/Editor/TextChangeEventArgs.cs @@ -1,9 +1,24 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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; -namespace ICSharpCode.Editor +namespace ICSharpCode.NRefactory.Editor { /// /// Describes a change of the document text. @@ -24,7 +39,7 @@ namespace ICSharpCode.Editor } /// - /// The text that was inserted. + /// The text that was removed. /// public string RemovedText { get { return removedText; } diff --git a/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj b/ICSharpCode.NRefactory/ICSharpCode.NRefactory.csproj index 1fad1819d..88c69f54a 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,6 +16,10 @@ 1591,0618 False -Microsoft.Design#CA1026;-Microsoft.Security#CA2104 + true + ..\ICSharpCode.NRefactory.snk + False + File AnyCPU @@ -29,16 +32,17 @@ bin\Debug\ Full False - DEBUG;TRACE;FULL_AST - False + DEBUG;TRACE + True true bin\Release\ None True - TRACE;FULL_AST + TRACE False + false 4 @@ -48,172 +52,57 @@ - - + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - @@ -226,6 +115,8 @@ + + @@ -237,7 +128,9 @@ - + + + @@ -246,6 +139,7 @@ + @@ -271,146 +165,39 @@ + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - + {D68133BD-1E63-496E-9EDE-4FBDBF77B486} Mono.Cecil - - {F054A788-B591-4561-A8BA-AE745BBEB817} - ICSharpCode.Editor - \ No newline at end of file diff --git a/ICSharpCode.NRefactory/PatternMatching/AnyNode.cs b/ICSharpCode.NRefactory/PatternMatching/AnyNode.cs index 0f3673680..ba142b14c 100644 --- a/ICSharpCode.NRefactory/PatternMatching/AnyNode.cs +++ b/ICSharpCode.NRefactory/PatternMatching/AnyNode.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -27,10 +42,5 @@ namespace ICSharpCode.NRefactory.PatternMatching match.Add(this.groupName, other); return other != null && !other.IsNull; } - - public override S AcceptVisitor(IPatternAstVisitor visitor, T data) - { - return visitor.VisitAnyNode(this, data); - } } } diff --git a/ICSharpCode.NRefactory/PatternMatching/Backreference.cs b/ICSharpCode.NRefactory/PatternMatching/Backreference.cs index 61338dde6..0f0e0f96a 100644 --- a/ICSharpCode.NRefactory/PatternMatching/Backreference.cs +++ b/ICSharpCode.NRefactory/PatternMatching/Backreference.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Linq; @@ -28,45 +43,5 @@ namespace ICSharpCode.NRefactory.PatternMatching { return match.Get(referencedGroupName).Last().IsMatch(other); } - - public override S AcceptVisitor(IPatternAstVisitor visitor, T data) - { - return visitor.VisitBackreference(this, data); - } - } - - /// - /// Matches identifier expressions that have the same identifier as the referenced variable/type definition/method definition. - /// - public class IdentifierExpressionBackreference : Pattern - { - readonly string referencedGroupName; - - public string ReferencedGroupName { - get { return referencedGroupName; } - } - - public IdentifierExpressionBackreference(string referencedGroupName) - { - if (referencedGroupName == null) - throw new ArgumentNullException("referencedGroupName"); - this.referencedGroupName = referencedGroupName; - } - - public override bool DoMatch(INode other, Match match) - { - CSharp.IdentifierExpression ident = other as CSharp.IdentifierExpression; - if (ident == null || ident.TypeArguments.Any()) - return false; - CSharp.AstNode referenced = (CSharp.AstNode)match.Get(referencedGroupName).Last(); - if (referenced == null) - return false; - return ident.Identifier == referenced.GetChildByRole(CSharp.AstNode.Roles.Identifier).Name; - } - - public override S AcceptVisitor(IPatternAstVisitor visitor, T data) - { - return visitor.VisitIdentifierExpressionBackreference(this, data); - } } } diff --git a/ICSharpCode.NRefactory/PatternMatching/BacktrackingInfo.cs b/ICSharpCode.NRefactory/PatternMatching/BacktrackingInfo.cs index 35721c496..54b547e17 100644 --- a/ICSharpCode.NRefactory/PatternMatching/BacktrackingInfo.cs +++ b/ICSharpCode.NRefactory/PatternMatching/BacktrackingInfo.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/PatternMatching/Choice.cs b/ICSharpCode.NRefactory/PatternMatching/Choice.cs index 8c19cc645..45e408bbf 100644 --- a/ICSharpCode.NRefactory/PatternMatching/Choice.cs +++ b/ICSharpCode.NRefactory/PatternMatching/Choice.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; @@ -49,10 +64,5 @@ namespace ICSharpCode.NRefactory.PatternMatching { return alternatives.GetEnumerator(); } - - public override S AcceptVisitor(IPatternAstVisitor visitor, T data) - { - return visitor.VisitChoice(this, data); - } } } diff --git a/ICSharpCode.NRefactory/PatternMatching/INode.cs b/ICSharpCode.NRefactory/PatternMatching/INode.cs index 4e54cff3e..7dc0a7dc3 100644 --- a/ICSharpCode.NRefactory/PatternMatching/INode.cs +++ b/ICSharpCode.NRefactory/PatternMatching/INode.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/PatternMatching/IPatternAstVisitor.cs b/ICSharpCode.NRefactory/PatternMatching/IPatternAstVisitor.cs deleted file mode 100644 index e5246cce3..000000000 --- a/ICSharpCode.NRefactory/PatternMatching/IPatternAstVisitor.cs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.NRefactory.PatternMatching -{ - /// - /// AST visitor that works for patterns. - /// - public interface IPatternAstVisitor - { - S VisitAnyNode(AnyNode anyNode, T data); - S VisitBackreference(Backreference backreference, T data); - S VisitChoice(Choice choice, T data); - S VisitNamedNode(NamedNode namedNode, T data); - S VisitRepeat(Repeat repeat, T data); - S VisitOptionalNode(OptionalNode optionalNode, T data); - S VisitIdentifierExpressionBackreference(IdentifierExpressionBackreference identifierExpressionBackreference, T data); - } -} diff --git a/ICSharpCode.NRefactory/PatternMatching/Match.cs b/ICSharpCode.NRefactory/PatternMatching/Match.cs index 7fd683039..de13c035d 100644 --- a/ICSharpCode.NRefactory/PatternMatching/Match.cs +++ b/ICSharpCode.NRefactory/PatternMatching/Match.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/PatternMatching/NamedNode.cs b/ICSharpCode.NRefactory/PatternMatching/NamedNode.cs index 64802ce57..07f2138a6 100644 --- a/ICSharpCode.NRefactory/PatternMatching/NamedNode.cs +++ b/ICSharpCode.NRefactory/PatternMatching/NamedNode.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -34,10 +49,5 @@ namespace ICSharpCode.NRefactory.PatternMatching match.Add(this.groupName, other); return childNode.DoMatch(other, match); } - - public override S AcceptVisitor(IPatternAstVisitor visitor, T data) - { - return visitor.VisitNamedNode(this, data); - } } } diff --git a/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs b/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs index b42db0209..c3c8a5529 100644 --- a/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs +++ b/ICSharpCode.NRefactory/PatternMatching/OptionalNode.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -39,10 +54,5 @@ namespace ICSharpCode.NRefactory.PatternMatching else return childNode.DoMatch(other, match); } - - public override S AcceptVisitor(IPatternAstVisitor visitor, T data) - { - return visitor.VisitOptionalNode(this, data); - } } } diff --git a/ICSharpCode.NRefactory/PatternMatching/Pattern.cs b/ICSharpCode.NRefactory/PatternMatching/Pattern.cs index 5553840af..d39b5713d 100644 --- a/ICSharpCode.NRefactory/PatternMatching/Pattern.cs +++ b/ICSharpCode.NRefactory/PatternMatching/Pattern.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -48,18 +63,6 @@ namespace ICSharpCode.NRefactory.PatternMatching return DoMatch (pos, match); } - public abstract S AcceptVisitor (IPatternAstVisitor visitor, T data); - - // Make debugging easier by giving Patterns a ToString() implementation - public override string ToString() - { - // TODO: what if this pattern contains a VB-AST? - // either remove ToString() here, or add some magic to figure out the correct output visitor - StringWriter w = new StringWriter(); - AcceptVisitor(new CSharp.OutputVisitor(w, new CSharp.CSharpFormattingOptions()), null); - return w.ToString(); - } - public static bool DoMatchCollection(Role role, INode firstPatternChild, INode firstOtherChild, Match match) { BacktrackingInfo backtrackingInfo = new BacktrackingInfo(); diff --git a/ICSharpCode.NRefactory/PatternMatching/Repeat.cs b/ICSharpCode.NRefactory/PatternMatching/Repeat.cs index 249075fe3..c0118238b 100644 --- a/ICSharpCode.NRefactory/PatternMatching/Repeat.cs +++ b/ICSharpCode.NRefactory/PatternMatching/Repeat.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -55,10 +70,5 @@ namespace ICSharpCode.NRefactory.PatternMatching else return this.MaxCount >= 1 && childNode.DoMatch(other, match); } - - public override S AcceptVisitor(IPatternAstVisitor visitor, T data) - { - return visitor.VisitRepeat(this, data); - } } } diff --git a/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs b/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs index 28987ead7..41f69eccd 100644 --- a/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs +++ b/ICSharpCode.NRefactory/Properties/AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Runtime.InteropServices; [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("ICSharpCode")] [assembly: AssemblyProduct("SharpDevelop/MonoDevelop")] -[assembly: AssemblyCopyright("Copyright 2010 AlphaSierraPapa")] +[assembly: AssemblyCopyright("Copyright 2010-2011 AlphaSierraPapa")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -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")] diff --git a/ICSharpCode.NRefactory/CSharp/Ast/Role.cs b/ICSharpCode.NRefactory/Role.cs similarity index 58% rename from ICSharpCode.NRefactory/CSharp/Ast/Role.cs rename to ICSharpCode.NRefactory/Role.cs index 675b344a7..012dd2bb1 100644 --- a/ICSharpCode.NRefactory/CSharp/Ast/Role.cs +++ b/ICSharpCode.NRefactory/Role.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs b/ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs new file mode 100644 index 000000000..e2fecf1bb --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/AmbiguousResolveResult.cs @@ -0,0 +1,48 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents an ambiguous type resolve result. + /// + public class AmbiguousTypeResolveResult : TypeResolveResult + { + public AmbiguousTypeResolveResult(IType type) : base(type) + { + } + + public override bool IsError { + get { return true; } + } + } + + public class AmbiguousMemberResolveResult : MemberResolveResult + { + public AmbiguousMemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(targetResult, member, returnType) + { + } + + public override bool IsError { + get { return true; } + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/ArrayAccessResolveResult.cs b/ICSharpCode.NRefactory/Semantics/ArrayAccessResolveResult.cs new file mode 100644 index 000000000..286681eb3 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/ArrayAccessResolveResult.cs @@ -0,0 +1,50 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Resolve result representing an array access. + /// + public class ArrayAccessResolveResult : ResolveResult + { + public readonly ResolveResult Array; + public readonly ResolveResult[] Indices; + + public ArrayAccessResolveResult(IType elementType, ResolveResult array, ResolveResult[] indices) : base(elementType) + { + if (array == null) + throw new ArgumentNullException("array"); + if (indices == null) + throw new ArgumentNullException("indices"); + this.Array = array; + this.Indices = indices; + } + + public override IEnumerable GetChildResults() + { + return new [] { Array }.Concat(Indices); + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/ArrayCreateResolveResult.cs b/ICSharpCode.NRefactory/Semantics/ArrayCreateResolveResult.cs new file mode 100644 index 000000000..7b4a978ea --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/ArrayCreateResolveResult.cs @@ -0,0 +1,58 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Resolve result representing an array creation. + /// + public class ArrayCreateResolveResult : ResolveResult + { + /// + /// Gets the size arguments. + /// + public readonly ResolveResult[] SizeArguments; + + /// + /// Gets the initializer elements. + /// This field may be null if no initializer was specified. + /// + public readonly ResolveResult[] InitializerElements; + + public ArrayCreateResolveResult(IType arrayType, ResolveResult[] sizeArguments, ResolveResult[] initializerElements) + : base(arrayType) + { + this.SizeArguments = sizeArguments; + this.InitializerElements = initializerElements; + } + + public override IEnumerable GetChildResults() + { + if (SizeArguments != null && InitializerElements != null) + return SizeArguments.Concat(InitializerElements); + else + return SizeArguments ?? InitializerElements ?? EmptyList.Instance; + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/ByReferenceResolveResult.cs b/ICSharpCode.NRefactory/Semantics/ByReferenceResolveResult.cs new file mode 100644 index 000000000..5522a0faf --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/ByReferenceResolveResult.cs @@ -0,0 +1,65 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents the resolve result of an 'ref x' or 'out x' expression. + /// + public class ByReferenceResolveResult : ResolveResult + { + public bool IsOut { get; private set; } + public bool IsRef { get { return !IsOut;} } + + public readonly ResolveResult ElementResult; + + public ByReferenceResolveResult(ResolveResult elementResult, bool isOut) + : this(elementResult.Type, isOut) + { + this.ElementResult = elementResult; + } + + public ByReferenceResolveResult(IType elementType, bool isOut) + : base(new ByReferenceType(elementType)) + { + this.IsOut = isOut; + } + + public IType ElementType { + get { return ((ByReferenceType)this.Type).ElementType; } + } + + public override IEnumerable GetChildResults() + { + if (ElementResult != null) + return new[] { ElementResult }; + else + return Enumerable.Empty(); + } + + public override string ToString() + { + return string.Format("[{0} {1} {2}]", GetType().Name, IsOut ? "out" : "ref", ElementType); + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/ConstantResolveResult.cs b/ICSharpCode.NRefactory/Semantics/ConstantResolveResult.cs new file mode 100644 index 000000000..e4dcd1e09 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/ConstantResolveResult.cs @@ -0,0 +1,49 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// ResolveResult representing a compile-time constant. + /// + public class ConstantResolveResult : ResolveResult + { + object constantValue; + + public ConstantResolveResult(IType type, object constantValue) : base(type) + { + this.constantValue = constantValue; + } + + public override bool IsCompileTimeConstant { + get { return true; } + } + + public override object ConstantValue { + get { return constantValue; } + } + + public override string ToString() + { + return string.Format("[{0} {1} = {2}]", GetType().Name, this.Type, constantValue); + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs b/ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs new file mode 100644 index 000000000..9ea541692 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/InvocationResolveResult.cs @@ -0,0 +1,55 @@ +// 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.Collections.Generic; +using System.Linq; + +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents the result of a method invocation. + /// + public abstract class InvocationResolveResult : MemberResolveResult + { + /// + /// Gets the arguments that are being passed to the method. + /// + public readonly IList Arguments; + + public InvocationResolveResult( + ResolveResult targetResult, IParameterizedMember member, IType returnType, + IList arguments) + : base(targetResult, member, returnType) + { + this.Arguments = arguments ?? EmptyList.Instance; + } + + public new IParameterizedMember Member { + get { return (IParameterizedMember)base.Member; } + } + + public override IEnumerable GetChildResults() + { + return base.GetChildResults().Concat(this.Arguments); + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs b/ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs new file mode 100644 index 000000000..58db07360 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/LocalResolveResult.cs @@ -0,0 +1,77 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents a local variable. + /// + public class LocalResolveResult : ResolveResult + { + readonly IVariable variable; + readonly object constantValue; + + public LocalResolveResult(IVariable variable, IType type, object constantValue = null) + : base(UnpackTypeIfByRefParameter(type, variable)) + { + if (variable == null) + throw new ArgumentNullException("variable"); + this.variable = variable; + this.constantValue = constantValue; + } + + static IType UnpackTypeIfByRefParameter(IType type, IVariable v) + { + if (type.Kind == TypeKind.ByReference) { + IParameter p = v as IParameter; + if (p != null && (p.IsRef || p.IsOut)) + return ((ByReferenceType)type).ElementType; + } + return type; + } + + public IVariable Variable { + get { return variable; } + } + + public bool IsParameter { + get { return variable is IParameter; } + } + + public override bool IsCompileTimeConstant { + get { return variable.IsConst; } + } + + public override object ConstantValue { + get { return constantValue; } + } + + public override string ToString() + { + return string.Format("[LocalResolveResult {0}]", variable); + } + + public override DomRegion GetDefinitionRegion() + { + return variable.Region; + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs b/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs new file mode 100644 index 000000000..467e73595 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/MemberResolveResult.cs @@ -0,0 +1,101 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents the result of a member invocation. + /// + public class MemberResolveResult : ResolveResult + { + readonly IMember member; + readonly bool isConstant; + readonly object constantValue; + readonly ResolveResult targetResult; + + public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType) : base(returnType) + { + if (member == null) + throw new ArgumentNullException("member"); + this.targetResult = targetResult; + this.member = member; + } + + public MemberResolveResult(ResolveResult targetResult, IMember member, IType returnType, object constantValue) : base(returnType) + { + if (member == null) + throw new ArgumentNullException("member"); + this.targetResult = targetResult; + this.member = member; + this.isConstant = true; + this.constantValue = constantValue; + } + + public MemberResolveResult(ResolveResult targetResult, IMember member, ITypeResolveContext context) + : base(member.EntityType == EntityType.Constructor ? member.DeclaringType : member.ReturnType.Resolve(context)) + { + this.targetResult = targetResult; + this.member = member; + IField field = member as IField; + if (field != null) { + isConstant = field.IsConst; + if (isConstant) + constantValue = field.ConstantValue.Resolve(context).ConstantValue; + } + } + + public ResolveResult TargetResult { + get { return targetResult; } + } + + public IMember Member { + get { return member; } + } + + public override bool IsCompileTimeConstant { + get { return isConstant; } + } + + public override object ConstantValue { + get { return constantValue; } + } + + public override IEnumerable GetChildResults() + { + if (targetResult != null) + return new[] { targetResult }; + else + return Enumerable.Empty(); + } + + public override string ToString() + { + return string.Format("[{0} {1}]", GetType().Name, member); + } + + public override DomRegion GetDefinitionRegion() + { + return member.Region; + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs b/ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs new file mode 100644 index 000000000..c6e232326 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/NamespaceResolveResult.cs @@ -0,0 +1,45 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents that an expression resolved to a namespace. + /// + public class NamespaceResolveResult : ResolveResult + { + readonly string namespaceName; + + public NamespaceResolveResult(string namespaceName) : base(SharedTypes.UnknownType) + { + this.namespaceName = namespaceName; + } + + public string NamespaceName { + get { return namespaceName; } + } + + public override string ToString() + { + return string.Format("[{0} {1}]", GetType().Name, namespaceName); + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/ResolveResult.cs b/ICSharpCode.NRefactory/Semantics/ResolveResult.cs new file mode 100644 index 000000000..40b3bc055 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/ResolveResult.cs @@ -0,0 +1,72 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.TypeSystem; +using ICSharpCode.NRefactory.TypeSystem.Implementation; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents the result of resolving an expression. + /// + public class ResolveResult + { + IType type; + + public ResolveResult(IType type) + { + if (type == null) + throw new ArgumentNullException("type"); + this.type = type; + } + + public IType Type { + get { return type; } + } + + public virtual bool IsCompileTimeConstant { + get { return false; } + } + + public virtual object ConstantValue { + get { return null; } + } + + public virtual bool IsError { + get { return false; } + } + + public override string ToString() + { + return "[" + GetType().Name + " " + type + "]"; + } + + public virtual IEnumerable GetChildResults() + { + return Enumerable.Empty(); + } + + public virtual DomRegion GetDefinitionRegion() + { + return DomRegion.Empty; + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/TypeOfResolveResult.cs b/ICSharpCode.NRefactory/Semantics/TypeOfResolveResult.cs new file mode 100644 index 000000000..0f1d2e50f --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/TypeOfResolveResult.cs @@ -0,0 +1,44 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// Represents the 'typeof'. + /// + public class TypeOfResolveResult : ResolveResult + { + readonly IType referencedType; + + public TypeOfResolveResult(IType systemType, IType referencedType) + : base(systemType) + { + this.referencedType = referencedType; + } + + /// + /// The type referenced by the 'typeof'. + /// + public IType ReferencedType { + get { return referencedType; } + } + } +} diff --git a/ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs b/ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs new file mode 100644 index 000000000..b66bee211 --- /dev/null +++ b/ICSharpCode.NRefactory/Semantics/TypeResolveResult.cs @@ -0,0 +1,43 @@ +// 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 ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.NRefactory.Semantics +{ + /// + /// The resolved expression refers to a type name. + /// + public class TypeResolveResult : ResolveResult + { + public TypeResolveResult(IType type) + : base(type) + { + } + + public override DomRegion GetDefinitionRegion() + { + ITypeDefinition def = this.Type.GetDefinition(); + if (def != null) + return def.Region; + else + return DomRegion.Empty; + } + } +} diff --git a/ICSharpCode.NRefactory/CSharp/Resolver/UnknownMemberResolveResult.cs b/ICSharpCode.NRefactory/Semantics/UnknownMemberResolveResult.cs similarity index 66% rename from ICSharpCode.NRefactory/CSharp/Resolver/UnknownMemberResolveResult.cs rename to ICSharpCode.NRefactory/Semantics/UnknownMemberResolveResult.cs index 2f6441fc4..180788134 100644 --- a/ICSharpCode.NRefactory/CSharp/Resolver/UnknownMemberResolveResult.cs +++ b/ICSharpCode.NRefactory/Semantics/UnknownMemberResolveResult.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -7,7 +22,7 @@ using System.Collections.ObjectModel; using System.Linq; using ICSharpCode.NRefactory.TypeSystem; -namespace ICSharpCode.NRefactory.CSharp.Resolver +namespace ICSharpCode.NRefactory.Semantics { /// /// Represents an unknown member. diff --git a/ICSharpCode.Editor/TextLocation.cs b/ICSharpCode.NRefactory/TextLocation.cs similarity index 76% rename from ICSharpCode.Editor/TextLocation.cs rename to ICSharpCode.NRefactory/TextLocation.cs index 12bfe354e..4bc7a81e0 100644 --- a/ICSharpCode.Editor/TextLocation.cs +++ b/ICSharpCode.NRefactory/TextLocation.cs @@ -1,10 +1,25 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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.Globalization; -namespace ICSharpCode.Editor +namespace ICSharpCode.NRefactory { /// /// A line/column position. diff --git a/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs b/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs index 7717e6112..c362a93b6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Accessibility.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs index 9f42a2ec8..27566cb3a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ArrayType.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -10,7 +25,8 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents an array type. /// - public class ArrayType : TypeWithElementType + [Serializable] + public sealed class ArrayType : TypeWithElementType, ISupportsInterning { readonly int dimensions; @@ -21,6 +37,10 @@ namespace ICSharpCode.NRefactory.TypeSystem this.dimensions = dimensions; } + public override TypeKind Kind { + get { return TypeKind.Array; } + } + public int Dimensions { get { return dimensions; } } @@ -64,19 +84,21 @@ namespace ICSharpCode.NRefactory.TypeSystem return baseTypes; } - public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - return systemArray.Resolve(context).GetMethods(context, filter); + return systemArray.Resolve(context).GetMethods(context, filter, options); } static readonly DefaultParameter indexerParam = new DefaultParameter(KnownTypeReference.Int32, string.Empty); - public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { ITypeDefinition arrayDef = systemArray.Resolve(context) as ITypeDefinition; if (arrayDef != null) { - foreach (IProperty p in arrayDef.GetProperties(context, filter)) { - yield return p; + if ((options & GetMemberOptions.IgnoreInheritedMembers) == 0) { + foreach (IProperty p in arrayDef.GetProperties(context, filter, options)) { + yield return p; + } } DefaultProperty indexer = new DefaultProperty(arrayDef, "Items") { EntityType = EntityType.Indexer, @@ -112,8 +134,25 @@ namespace ICSharpCode.NRefactory.TypeSystem else return new ArrayType(e, dimensions); } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + elementType = provider.Intern(elementType); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return elementType.GetHashCode() ^ dimensions; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ArrayType o = other as ArrayType; + return o != null && elementType == o.elementType && dimensions == o.dimensions; + } } + [Serializable] public sealed class ArrayTypeReference : ITypeReference, ISupportsInterning { ITypeReference elementType; diff --git a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs index 39288f25f..e8eb17f43 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ByReferenceType.cs @@ -1,15 +1,37 @@ - +// 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 ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { - public class ByReferenceType : TypeWithElementType + [Serializable] + public sealed class ByReferenceType : TypeWithElementType, ISupportsInterning { public ByReferenceType(IType elementType) : base(elementType) { } + public override TypeKind Kind { + get { return TypeKind.ByReference; } + } + public override string NameSuffix { get { return "&"; @@ -45,11 +67,28 @@ namespace ICSharpCode.NRefactory.TypeSystem else return new ByReferenceType(e); } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + elementType = provider.Intern(elementType); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ByReferenceType brt = other as ByReferenceType; + return brt != null && this.elementType == brt.elementType; + } } - public class ByReferenceTypeReference : ITypeReference + [Serializable] + public sealed class ByReferenceTypeReference : ITypeReference, ISupportsInterning { - readonly ITypeReference elementType; + ITypeReference elementType; public ByReferenceTypeReference(ITypeReference elementType) { @@ -79,5 +118,21 @@ namespace ICSharpCode.NRefactory.TypeSystem else return new ByReferenceTypeReference(elementType); } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + elementType = provider.Intern(elementType); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return elementType.GetHashCode() ^ 91725814; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ByReferenceTypeReference brt = other as ByReferenceTypeReference; + return brt != null && this.elementType == brt.elementType; + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs index d7765d938..ab3ae6ca3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs +++ b/ICSharpCode.NRefactory/TypeSystem/CecilLoader.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -8,6 +23,8 @@ 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; @@ -44,6 +61,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public IInterningProvider InterningProvider { get; set; } + /// + /// Gets/Sets the cancellation token used by the cecil loader. + /// + public CancellationToken CancellationToken { get; set; } + /// /// Gets a value indicating whether this instance stores references to the cecil objects. /// @@ -63,6 +85,9 @@ namespace ICSharpCode.NRefactory.TypeSystem { if (createCecilReferences) typeSystemTranslationTable = new Dictionary (); + + // Enable interning by default. + this.InterningProvider = new SimpleInterningProvider(); } #region Load From AssemblyDefinition @@ -76,21 +101,27 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new ArgumentNullException("assemblyDefinition"); ITypeResolveContext oldEarlyBindContext = this.EarlyBindContext; try { + // Read assembly and module attributes IList assemblyAttributes = new List(); - foreach (var attr in assemblyDefinition.CustomAttributes) { - assemblyAttributes.Add(ReadAttribute(attr)); - } - if (this.InterningProvider != null) + IList moduleAttributes = new List(); + AddAttributes(assemblyDefinition, assemblyAttributes); + AddAttributes(assemblyDefinition.MainModule, moduleAttributes); + + if (this.InterningProvider != null) { assemblyAttributes = this.InterningProvider.InternList(assemblyAttributes); - else + moduleAttributes = this.InterningProvider.InternList(moduleAttributes); + } else { assemblyAttributes = new ReadOnlyCollection(assemblyAttributes); + moduleAttributes = new ReadOnlyCollection(moduleAttributes); + } TypeStorage typeStorage = new TypeStorage(); - CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes, this.DocumentationProvider); + CecilProjectContent pc = new CecilProjectContent(typeStorage, assemblyDefinition.Name.FullName, assemblyAttributes, moduleAttributes, this.DocumentationProvider); this.EarlyBindContext = CompositeTypeResolveContext.Combine(pc, this.EarlyBindContext); List types = new List(); foreach (ModuleDefinition module in assemblyDefinition.Modules) { foreach (TypeDefinition td in module.Types) { + this.CancellationToken.ThrowIfCancellationRequested(); if (this.IncludeInternalMembers || (td.Attributes & TypeAttributes.VisibilityMask) == TypeAttributes.Public) { string name = td.FullName; if (name.Length == 0 || name[0] == '<') @@ -137,19 +168,23 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region IProjectContent implementation + [Serializable] sealed class CecilProjectContent : ProxyTypeResolveContext, IProjectContent, ISynchronizedTypeResolveContext, IDocumentationProvider { readonly string assemblyName; readonly IList assemblyAttributes; + readonly IList moduleAttributes; readonly IDocumentationProvider documentationProvider; - public CecilProjectContent(TypeStorage types, string assemblyName, IList assemblyAttributes, IDocumentationProvider documentationProvider) + public CecilProjectContent(TypeStorage types, string assemblyName, IList assemblyAttributes, IList moduleAttributes, IDocumentationProvider documentationProvider) : base(types) { Debug.Assert(assemblyName != null); Debug.Assert(assemblyAttributes != null); + Debug.Assert(moduleAttributes != null); this.assemblyName = assemblyName; this.assemblyAttributes = assemblyAttributes; + this.moduleAttributes = moduleAttributes; this.documentationProvider = documentationProvider; } @@ -157,6 +192,14 @@ namespace ICSharpCode.NRefactory.TypeSystem get { return assemblyAttributes; } } + public IList ModuleAttributes { + get { return moduleAttributes; } + } + + public string AssemblyName { + get { return assemblyName; } + } + public override string ToString() { return "[CecilProjectContent " + assemblyName + "]"; @@ -168,22 +211,27 @@ namespace ICSharpCode.NRefactory.TypeSystem return this; } - public void Dispose() + void IDisposable.Dispose() { // Disposing the synchronization context has no effect } - public IParsedFile GetFile(string fileName) + IParsedFile IProjectContent.GetFile(string fileName) { return null; } - public IEnumerable Files { + IEnumerable IProjectContent.Files { get { return EmptyList.Instance; } } + void IProjectContent.UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) + { + throw new NotSupportedException(); + } + string IDocumentationProvider.GetDocumentation(IEntity entity) { if (documentationProvider != null) @@ -191,6 +239,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 @@ -357,13 +432,50 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region Read Attributes - void AddAttributes(ICustomAttributeProvider customAttributeProvider, IEntity targetEntity) + #region Assembly Attributes + static readonly ITypeReference typeForwardedToAttributeTypeRef = typeof(TypeForwardedToAttribute).ToTypeReference(); + static readonly ITypeReference assemblyVersionAttributeTypeRef = typeof(System.Reflection.AssemblyVersionAttribute).ToTypeReference(); + + void AddAttributes(AssemblyDefinition assembly, IList outputList) + { + if (assembly.HasCustomAttributes) { + AddCustomAttributes(assembly.CustomAttributes, outputList); + } + if (assembly.HasSecurityDeclarations) { + AddSecurityAttributes(assembly.SecurityDeclarations, outputList); + } + + // AssemblyVersionAttribute + if (assembly.Name.Version != null) { + var assemblyVersion = new DefaultAttribute(assemblyVersionAttributeTypeRef, new[] { KnownTypeReference.String }); + assemblyVersion.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, assembly.Name.Version.ToString())); + outputList.Add(assemblyVersion); + } + + // TypeForwardedToAttribute + foreach (ExportedType type in assembly.MainModule.ExportedTypes) { + if (type.IsForwarder) { + int typeParameterCount; + string name = ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); + var typeForwardedTo = new DefaultAttribute(typeForwardedToAttributeTypeRef, new[] { KnownTypeReference.Type }); + var typeRef = new GetClassTypeReference(type.Namespace, name, typeParameterCount); + typeForwardedTo.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Type, typeRef)); + outputList.Add(typeForwardedTo); + } + } + } + #endregion + + #region Module Attributes + void AddAttributes(ModuleDefinition module, IList outputList) { - if (customAttributeProvider.HasCustomAttributes) { - AddCustomAttributes(customAttributeProvider.CustomAttributes, targetEntity.Attributes); + if (module.HasCustomAttributes) { + AddCustomAttributes(module.CustomAttributes, outputList); } } + #endregion + #region Parameter Attributes static readonly IAttribute inAttribute = new DefaultAttribute(typeof(InAttribute).ToTypeReference(), null); static readonly IAttribute outAttribute = new DefaultAttribute(typeof(OutAttribute).ToTypeReference(), null); @@ -378,8 +490,13 @@ namespace ICSharpCode.NRefactory.TypeSystem if (parameter.HasCustomAttributes) { AddCustomAttributes(parameter.CustomAttributes, targetParameter.Attributes); } + if (parameter.HasMarshalInfo) { + targetParameter.Attributes.Add(ConvertMarshalInfo(parameter.MarshalInfo)); + } } + #endregion + #region Method Attributes static readonly ITypeReference dllImportAttributeTypeRef = typeof(DllImportAttribute).ToTypeReference(); static readonly SimpleConstantValue trueValue = new SimpleConstantValue(KnownTypeReference.Boolean, true); static readonly SimpleConstantValue falseValue = new SimpleConstantValue(KnownTypeReference.Boolean, true); @@ -410,9 +527,9 @@ namespace ICSharpCode.NRefactory.TypeSystem dllImport.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.String, info.Module.Name)); if (info.IsBestFitDisabled) - AddNamedArgument(dllImport, "BestFitMapping", falseValue); + dllImport.AddNamedArgument("BestFitMapping", falseValue); if (info.IsBestFitEnabled) - AddNamedArgument(dllImport, "BestFitMapping", trueValue); + dllImport.AddNamedArgument("BestFitMapping", trueValue); CallingConvention callingConvention; switch (info.Attributes & PInvokeAttributes.CallConvMask) { @@ -435,7 +552,7 @@ namespace ICSharpCode.NRefactory.TypeSystem throw new NotSupportedException("unknown calling convention"); } if (callingConvention != CallingConvention.Winapi) - AddNamedArgument(dllImport, "CallingConvention", new SimpleConstantValue(callingConventionTypeRef, (int)callingConvention)); + dllImport.AddNamedArgument("CallingConvention", callingConventionTypeRef, (int)callingConvention); CharSet charSet = CharSet.None; switch (info.Attributes & PInvokeAttributes.CharSetMask) { @@ -450,27 +567,26 @@ namespace ICSharpCode.NRefactory.TypeSystem break; } if (charSet != CharSet.None) - dllImport.NamedArguments.Add(new KeyValuePair( - "CharSet", new SimpleConstantValue(charSetTypeRef, (int)charSet))); + dllImport.AddNamedArgument("CharSet", charSetTypeRef, (int)charSet); if (!string.IsNullOrEmpty(info.EntryPoint) && info.EntryPoint != methodDefinition.Name) - AddNamedArgument(dllImport, "EntryPoint", new SimpleConstantValue(KnownTypeReference.String, info.EntryPoint)); + dllImport.AddNamedArgument("EntryPoint", KnownTypeReference.String, info.EntryPoint); if (info.IsNoMangle) - AddNamedArgument(dllImport, "ExactSpelling", trueValue); + dllImport.AddNamedArgument("ExactSpelling", trueValue); if ((implAttributes & MethodImplAttributes.PreserveSig) == MethodImplAttributes.PreserveSig) implAttributes &= ~MethodImplAttributes.PreserveSig; else - AddNamedArgument(dllImport, "PreserveSig", falseValue); + dllImport.AddNamedArgument("PreserveSig", falseValue); if (info.SupportsLastError) - AddNamedArgument(dllImport, "SetLastError", trueValue); + dllImport.AddNamedArgument("SetLastError", trueValue); if (info.IsThrowOnUnmappableCharDisabled) - AddNamedArgument(dllImport, "ThrowOnUnmappableChar", falseValue); + dllImport.AddNamedArgument("ThrowOnUnmappableChar", falseValue); if (info.IsThrowOnUnmappableCharEnabled) - AddNamedArgument(dllImport, "ThrowOnUnmappableChar", trueValue); + dllImport.AddNamedArgument("ThrowOnUnmappableChar", trueValue); attributes.Add(dllImport); } @@ -494,6 +610,9 @@ namespace ICSharpCode.NRefactory.TypeSystem if (methodDefinition.HasCustomAttributes) { AddCustomAttributes(methodDefinition.CustomAttributes, attributes); } + if (methodDefinition.HasSecurityDeclarations) { + AddSecurityAttributes(methodDefinition.SecurityDeclarations, attributes); + } if (methodDefinition.MethodReturnType.HasMarshalInfo) { returnTypeAttributes.Add(ConvertMarshalInfo(methodDefinition.MethodReturnType.MarshalInfo)); } @@ -501,23 +620,24 @@ namespace ICSharpCode.NRefactory.TypeSystem AddCustomAttributes(methodDefinition.MethodReturnType.CustomAttributes, returnTypeAttributes); } } + #endregion - static void AddNamedArgument(DefaultAttribute attribute, string name, IConstantValue value) - { - attribute.NamedArguments.Add(new KeyValuePair(name, value)); - } - + #region Type Attributes static readonly DefaultAttribute serializableAttribute = new DefaultAttribute(typeof(SerializableAttribute).ToTypeReference(), null); + static readonly DefaultAttribute comImportAttribute = new DefaultAttribute(typeof(ComImportAttribute).ToTypeReference(), null); static readonly ITypeReference structLayoutAttributeTypeRef = typeof(StructLayoutAttribute).ToTypeReference(); static readonly ITypeReference layoutKindTypeRef = typeof(LayoutKind).ToTypeReference(); static readonly ITypeReference charSetTypeRef = typeof(CharSet).ToTypeReference(); void AddAttributes(TypeDefinition typeDefinition, ITypeDefinition targetEntity) { - #region SerializableAttribute + // SerializableAttribute if (typeDefinition.IsSerializable) targetEntity.Attributes.Add(serializableAttribute); - #endregion + + // ComImportAttribute + if (typeDefinition.IsImport) + targetEntity.Attributes.Add(comImportAttribute); #region StructLayoutAttribute LayoutKind layoutKind = LayoutKind.Auto; @@ -546,19 +666,13 @@ namespace ICSharpCode.NRefactory.TypeSystem DefaultAttribute structLayout = new DefaultAttribute(structLayoutAttributeTypeRef, new[] { layoutKindTypeRef }); structLayout.PositionalArguments.Add(new SimpleConstantValue(layoutKindTypeRef, (int)layoutKind)); if (charSet != CharSet.Ansi) { - structLayout.NamedArguments.Add(new KeyValuePair( - "CharSet", - new SimpleConstantValue(charSetTypeRef, (int)charSet))); + structLayout.AddNamedArgument("CharSet", charSetTypeRef, (int)charSet); } if (typeDefinition.PackingSize > 0) { - structLayout.NamedArguments.Add(new KeyValuePair( - "Pack", - new SimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.PackingSize))); + structLayout.AddNamedArgument("Pack", KnownTypeReference.Int32, (int)typeDefinition.PackingSize); } if (typeDefinition.ClassSize > 0) { - structLayout.NamedArguments.Add(new KeyValuePair( - "Size", - new SimpleConstantValue(KnownTypeReference.Int32, (int)typeDefinition.ClassSize))); + structLayout.AddNamedArgument("Size", KnownTypeReference.Int32, (int)typeDefinition.ClassSize); } targetEntity.Attributes.Add(structLayout); } @@ -567,26 +681,29 @@ namespace ICSharpCode.NRefactory.TypeSystem if (typeDefinition.HasCustomAttributes) { AddCustomAttributes(typeDefinition.CustomAttributes, targetEntity.Attributes); } + if (typeDefinition.HasSecurityDeclarations) { + AddSecurityAttributes(typeDefinition.SecurityDeclarations, targetEntity.Attributes); + } } + #endregion + #region Field Attributes static readonly ITypeReference fieldOffsetAttributeTypeRef = typeof(FieldOffsetAttribute).ToTypeReference(); static readonly DefaultAttribute nonSerializedAttribute = new DefaultAttribute(typeof(NonSerializedAttribute).ToTypeReference(), null); void AddAttributes(FieldDefinition fieldDefinition, IEntity targetEntity) { - #region FieldOffsetAttribute + // FieldOffsetAttribute if (fieldDefinition.HasLayoutInfo) { DefaultAttribute fieldOffset = new DefaultAttribute(fieldOffsetAttributeTypeRef, new[] { KnownTypeReference.Int32 }); fieldOffset.PositionalArguments.Add(new SimpleConstantValue(KnownTypeReference.Int32, fieldDefinition.Offset)); targetEntity.Attributes.Add(fieldOffset); } - #endregion - #region NonSerializedAttribute + // NonSerializedAttribute if (fieldDefinition.IsNotSerialized) { targetEntity.Attributes.Add(nonSerializedAttribute); } - #endregion if (fieldDefinition.HasMarshalInfo) { targetEntity.Attributes.Add(ConvertMarshalInfo(fieldDefinition.MarshalInfo)); @@ -596,6 +713,25 @@ namespace ICSharpCode.NRefactory.TypeSystem AddCustomAttributes(fieldDefinition.CustomAttributes, targetEntity.Attributes); } } + #endregion + + #region Event Attributes + void AddAttributes(EventDefinition eventDefinition, IEntity targetEntity) + { + if (eventDefinition.HasCustomAttributes) { + AddCustomAttributes(eventDefinition.CustomAttributes, targetEntity.Attributes); + } + } + #endregion + + #region Property Attributes + void AddAttributes(PropertyDefinition propertyDefinition, IEntity targetEntity) + { + if (propertyDefinition.HasCustomAttributes) { + AddCustomAttributes(propertyDefinition.CustomAttributes, targetEntity.Attributes); + } + } + #endregion #region MarshalAsAttribute (ConvertMarshalInfo) static readonly ITypeReference marshalAsAttributeTypeRef = typeof(MarshalAsAttribute).ToTypeReference(); @@ -605,11 +741,42 @@ namespace ICSharpCode.NRefactory.TypeSystem { DefaultAttribute attr = new DefaultAttribute(marshalAsAttributeTypeRef, new[] { unmanagedTypeTypeRef }); attr.PositionalArguments.Add(new SimpleConstantValue(unmanagedTypeTypeRef, (int)marshalInfo.NativeType)); - // TODO: handle classes derived from MarshalInfo + + FixedArrayMarshalInfo fami = marshalInfo as FixedArrayMarshalInfo; + if (fami != null) { + attr.AddNamedArgument("SizeConst", KnownTypeReference.Int32, (int)fami.Size); + if (fami.ElementType != NativeType.None) + attr.AddNamedArgument("ArraySubType", unmanagedTypeTypeRef, (int)fami.ElementType); + } + SafeArrayMarshalInfo sami = marshalInfo as SafeArrayMarshalInfo; + if (sami != null && sami.ElementType != VariantType.None) { + attr.AddNamedArgument("SafeArraySubType", typeof(VarEnum).ToTypeReference(), (int)sami.ElementType); + } + ArrayMarshalInfo ami = marshalInfo as ArrayMarshalInfo; + if (ami != null) { + if (ami.ElementType != NativeType.Max) + attr.AddNamedArgument("ArraySubType", unmanagedTypeTypeRef, (int)ami.ElementType); + if (ami.Size >= 0) + attr.AddNamedArgument("SizeConst", KnownTypeReference.Int32, (int)ami.Size); + if (ami.SizeParameterMultiplier != 0 && ami.SizeParameterIndex >= 0) + attr.AddNamedArgument("SizeParamIndex", KnownTypeReference.Int16, (short)ami.SizeParameterIndex); + } + CustomMarshalInfo cmi = marshalInfo as CustomMarshalInfo; + if (cmi != null) { + attr.AddNamedArgument("MarshalType", KnownTypeReference.String, cmi.ManagedType.FullName); + if (!string.IsNullOrEmpty(cmi.Cookie)) + attr.AddNamedArgument("MarshalCookie", KnownTypeReference.String, cmi.Cookie); + } + FixedSysStringMarshalInfo fssmi = marshalInfo as FixedSysStringMarshalInfo; + if (fssmi != null) { + attr.AddNamedArgument("SizeConst", KnownTypeReference.Int32, (int)fssmi.Size); + } + return attr; } #endregion + #region Custom Attributes (ReadAttribute) void AddCustomAttributes(Mono.Collections.Generic.Collection attributes, IList targetCollection) { foreach (var cecilAttribute in attributes) { @@ -637,31 +804,53 @@ namespace ICSharpCode.NRefactory.TypeSystem } } DefaultAttribute a = new DefaultAttribute(ReadTypeReference(attribute.AttributeType), ctorParameters); - try { - if (attribute.HasConstructorArguments) { - foreach (var arg in attribute.ConstructorArguments) { - a.PositionalArguments.Add(ReadConstantValue(arg)); - } + if (attribute.HasConstructorArguments) { + foreach (var arg in attribute.ConstructorArguments) { + a.PositionalArguments.Add(ReadConstantValue(arg)); } - } catch (InvalidOperationException) { - // occurs when Cecil can't decode an argument } - try { - if (attribute.HasFields || attribute.HasProperties) { - foreach (var arg in attribute.Fields) { - a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); - } - foreach (var arg in attribute.Properties) { - a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); - } + if (attribute.HasFields || attribute.HasProperties) { + foreach (var arg in attribute.Fields) { + a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); + } + foreach (var arg in attribute.Properties) { + a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); } - } catch (InvalidOperationException) { - // occurs when Cecil can't decode an argument } return a; } #endregion + #region Security Attributes + static readonly ITypeReference securityActionTypeReference = typeof(SecurityAction).ToTypeReference(); + + void AddSecurityAttributes(Mono.Collections.Generic.Collection securityDeclarations, IList targetCollection) + { + foreach (var secDecl in securityDeclarations) { + try { + foreach (var secAttribute in secDecl.SecurityAttributes) { + ITypeReference attributeType = ReadTypeReference(secAttribute.AttributeType); + var a = new DefaultAttribute(attributeType, new[] { securityActionTypeReference }); + a.PositionalArguments.Add(new SimpleConstantValue(securityActionTypeReference, (ushort)secDecl.Action)); + + if (secAttribute.HasFields || secAttribute.HasProperties) { + foreach (var arg in secAttribute.Fields) { + a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); + } + foreach (var arg in secAttribute.Properties) { + a.NamedArguments.Add(new KeyValuePair(arg.Name, ReadConstantValue(arg.Argument))); + } + } + targetCollection.Add(a); + } + } catch (ResolutionException) { + // occurs when Cecil can't decode an argument + } + } + } + #endregion + #endregion + #region Read Constant Value public IConstantValue ReadConstantValue(CustomAttributeArgument arg) { @@ -687,8 +876,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) @@ -719,6 +910,7 @@ namespace ICSharpCode.NRefactory.TypeSystem public void Init(CecilLoader loader) { + loader.CancellationToken.ThrowIfCancellationRequested(); InitModifiers(); if (typeDefinition.HasGenericParameters) { @@ -790,17 +982,17 @@ namespace ICSharpCode.NRefactory.TypeSystem TypeDefinition td = this.typeDefinition; // set classtype if (td.IsInterface) { - this.ClassType = ClassType.Interface; + this.Kind = TypeKind.Interface; } else if (td.IsEnum) { - this.ClassType = ClassType.Enum; + this.Kind = TypeKind.Enum; } else if (td.IsValueType) { - this.ClassType = ClassType.Struct; + this.Kind = TypeKind.Struct; } else if (IsDelegate(td)) { - this.ClassType = ClassType.Delegate; + this.Kind = TypeKind.Delegate; } else if (IsModule(td)) { - this.ClassType = ClassType.Module; + this.Kind = TypeKind.Module; } else { - this.ClassType = ClassType.Class; + this.Kind = TypeKind.Class; } this.IsSealed = td.IsSealed; this.IsAbstract = td.IsAbstract; @@ -856,7 +1048,7 @@ namespace ICSharpCode.NRefactory.TypeSystem void InitMembers(CecilLoader loader) { - this.AddDefaultConstructorIfRequired = (this.ClassType == ClassType.Struct || this.ClassType == ClassType.Enum); + this.AddDefaultConstructorIfRequired = (this.Kind == TypeKind.Struct || this.Kind == TypeKind.Enum); if (typeDefinition.HasMethods) { foreach (MethodDefinition method in typeDefinition.Methods) { if (loader.IsVisible(method.Attributes)) { @@ -988,7 +1180,7 @@ namespace ICSharpCode.NRefactory.TypeSystem void TranslateModifiers(MethodDefinition method, AbstractMember m) { - if (m.DeclaringTypeDefinition.ClassType == ClassType.Interface) { + if (m.DeclaringTypeDefinition.Kind == TypeKind.Interface) { // interface members don't have modifiers, but we want to handle them as "public abstract" m.Accessibility = Accessibility.Public; m.IsAbstract = true; diff --git a/ICSharpCode.NRefactory/TypeSystem/ClassType.cs b/ICSharpCode.NRefactory/TypeSystem/ClassType.cs deleted file mode 100644 index 4440264ed..000000000 --- a/ICSharpCode.NRefactory/TypeSystem/ClassType.cs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.NRefactory.TypeSystem -{ - public enum ClassType : byte - { - Class, - Enum, - Interface, - Struct, - Delegate, - Module, - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs b/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs index 851b97e90..523b60ed9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs +++ b/ICSharpCode.NRefactory/TypeSystem/DomRegion.cs @@ -1,9 +1,23 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Globalization; -using ICSharpCode.NRefactory.CSharp; namespace ICSharpCode.NRefactory.TypeSystem { @@ -60,15 +74,15 @@ namespace ICSharpCode.NRefactory.TypeSystem } } - public AstLocation Begin { + public TextLocation Begin { get { - return new AstLocation (beginLine, beginColumn); + return new TextLocation (beginLine, beginColumn); } } - public AstLocation End { + public TextLocation End { get { - return new AstLocation (endLine, endColumn); + return new TextLocation (endLine, endColumn); } } @@ -98,11 +112,11 @@ namespace ICSharpCode.NRefactory.TypeSystem this.endColumn = -1; } - public DomRegion (AstLocation begin, AstLocation end) : this (null, begin, end) + public DomRegion (TextLocation begin, TextLocation end) : this (null, begin, end) { } - public DomRegion (string fileName, AstLocation begin, AstLocation end) + public DomRegion (string fileName, TextLocation begin, TextLocation end) { this.fileName = fileName; this.beginLine = begin.Line; @@ -111,11 +125,11 @@ namespace ICSharpCode.NRefactory.TypeSystem this.endColumn = end.Column; } - public DomRegion (AstLocation begin) : this (null, begin) + public DomRegion (TextLocation begin) : this (null, begin) { } - public DomRegion (string fileName, AstLocation begin) + public DomRegion (string fileName, TextLocation begin) { this.fileName = fileName; this.beginLine = begin.Line; @@ -138,7 +152,7 @@ namespace ICSharpCode.NRefactory.TypeSystem (line != EndLine || column <= EndColumn); } - public bool IsInside(AstLocation location) + public bool IsInside(TextLocation location) { return IsInside(location.Line, location.Column); } diff --git a/ICSharpCode.NRefactory/TypeSystem/EntityType.cs b/ICSharpCode.NRefactory/TypeSystem/EntityType.cs index 86cb04616..efc74910e 100644 --- a/ICSharpCode.NRefactory/TypeSystem/EntityType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/EntityType.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/TypeSystem/Error.cs b/ICSharpCode.NRefactory/TypeSystem/Error.cs index 1684e8d81..ade3d45c8 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Error.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Error.cs @@ -1,4 +1,4 @@ -// +// // Error.cs // // Author: @@ -25,7 +25,6 @@ // THE SOFTWARE. using System; -using ICSharpCode.NRefactory.CSharp; namespace ICSharpCode.NRefactory.TypeSystem { @@ -42,22 +41,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 +77,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; } /// @@ -90,11 +94,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// The location of the error. /// - public Error (ErrorType errorType, string message, AstLocation location) + public Error (ErrorType errorType, string message, TextLocation 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); } /// @@ -112,7 +116,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// The column of the error. /// - public Error (ErrorType errorType, string message, int line, int col) : this (errorType, message, new AstLocation (line, col)) + public Error (ErrorType errorType, string message, int line, int col) : this (errorType, message, new TextLocation (line, col)) { } @@ -127,9 +131,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/ExtensionMethods.cs b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs index e2608b812..f1ed305f7 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ExtensionMethods.cs @@ -1,13 +1,26 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.TypeSystem.Implementation; using ICSharpCode.NRefactory.Utils; -using ICSharpCode.NRefactory.CSharp.Refactoring; -using ICSharpCode.NRefactory.CSharp; namespace ICSharpCode.NRefactory.TypeSystem { @@ -23,38 +36,30 @@ namespace ICSharpCode.NRefactory.TypeSystem /// This is the reflexive and transitive closure of . /// Note that this method does not return all supertypes - doing so is impossible due to contravariance /// (and undesirable for covariance as the list could become very large). + /// + /// The output is ordered so that base types occur in before derived types. /// public static IEnumerable GetAllBaseTypes(this IType type, ITypeResolveContext context) { - List output = new List(); - Stack activeTypeDefinitions = new Stack(); - CollectAllBaseTypes(type, context, activeTypeDefinitions, output); - return output; + BaseTypeCollector collector = new BaseTypeCollector(context); + collector.CollectBaseTypes(type); + return collector; } - static void CollectAllBaseTypes(IType type, ITypeResolveContext context, Stack activeTypeDefinitions, List output) + /// + /// Gets the non-interface base types. + /// + /// + /// When is an interface, this method will also return base interfaces. + /// + /// The output is ordered so that base types occur in before derived types. + /// + public static IEnumerable GetNonInterfaceBaseTypes(this IType type, ITypeResolveContext context) { - ITypeDefinition def = type.GetDefinition(); - if (def != null) { - // Maintain a stack of currently active type definitions, and avoid having one definition - // multiple times on that stack. - // This is necessary to ensure the output is finite in the presence of cyclic inheritance: - // class C : C> {} would not be caught by the 'no duplicate output' check, yet would - // produce infinite output. - if (activeTypeDefinitions.Contains(def)) - return; - activeTypeDefinitions.Push(def); - } - // Avoid outputting a type more than once - necessary for "diamond" multiple inheritance - // (e.g. C implements I1 and I2, and both interfaces derive from Object) - if (!output.Contains(type)) { - output.Add(type); - foreach (IType baseType in type.GetBaseTypes(context)) { - CollectAllBaseTypes(baseType, context, activeTypeDefinitions, output); - } - } - if (def != null) - activeTypeDefinitions.Pop(); + BaseTypeCollector collector = new BaseTypeCollector(context); + collector.SkipImplementedInterfaces = true; + collector.CollectBaseTypes(type); + return collector; } #endregion @@ -111,6 +116,16 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets whether the type is an open type (contains type parameters). /// + /// + /// + /// class X<T> { + /// List<T> open; + /// X<X<T[]>> open; + /// X<string> closed; + /// int closed; + /// } + /// + /// public static bool IsOpen(this IType type) { if (type == null) @@ -121,8 +136,13 @@ namespace ICSharpCode.NRefactory.TypeSystem } /// - /// Gets whether the type is unbound. + /// Gets whether the type is unbound (is a generic type, but no type arguments were provided). /// + /// + /// In "typeof(List<Dictionary<,>>)", only the Dictionary is unbound, the List is considered + /// bound despite containing an unbound type. + /// This method returns false for partially parameterized types (Dictionary<string, >). + /// public static bool IsUnbound(this IType type) { if (type == null) @@ -135,12 +155,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets whether the type is an enumeration type. /// + [Obsolete("Use type.Kind == TypeKind.Enum instead")] public static bool IsEnum(this IType type) { if (type == null) throw new ArgumentNullException("type"); - ITypeDefinition def = type.GetDefinition(); - return def != null && def.ClassType == ClassType.Enum; + return type.Kind == TypeKind.Enum; } /// @@ -153,13 +173,13 @@ namespace ICSharpCode.NRefactory.TypeSystem if (context == null) throw new ArgumentNullException("context"); ITypeDefinition def = enumType.GetDefinition(); - if (def != null && def.ClassType == ClassType.Enum) { + if (def != null && def.Kind == TypeKind.Enum) { if (def.BaseTypes.Count == 1) return def.BaseTypes[0].Resolve(context); else return KnownTypeReference.Int32.Resolve(context); } else { - throw new ArgumentException("enumType must be an enum"); + return SharedTypes.UnknownType; } } @@ -167,12 +187,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets whether the type is an delegate type. /// /// This method returns false for System.Delegate itself + [Obsolete("Use type.Kind == TypeKind.Delegate instead")] public static bool IsDelegate(this IType type) { if (type == null) throw new ArgumentNullException("type"); - ITypeDefinition def = type.GetDefinition(); - return def != null && def.ClassType == ClassType.Delegate; + return type.Kind == TypeKind.Delegate; } /// @@ -186,16 +206,12 @@ namespace ICSharpCode.NRefactory.TypeSystem if (type == null) throw new ArgumentNullException("type"); ITypeDefinition def = type.GetDefinition(); - if (def != null && def.ClassType == ClassType.Delegate) { + if (def != null && def.Kind == TypeKind.Delegate) { foreach (IMethod method in def.Methods) { if (method.Name == "Invoke") { ParameterizedType pt = type as ParameterizedType; if (pt != null) { - SpecializedMethod m = new SpecializedMethod(method); - m.SetDeclaringType(pt); - var substitution = pt.GetSubstitution(); - m.SubstituteTypes(t => new SubstitutionTypeReference(t, substitution)); - return m; + return new SpecializedMethod(pt, method); } return method; } @@ -235,9 +251,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets the type (potentially a nested type) defined at the specified location. /// Returns null if no type is defined at that location. /// - public static ITypeDefinition GetTypeDefinition (this IParsedFile file, int line, int column) + public static ITypeDefinition GetInnermostTypeDefinition (this IParsedFile file, int line, int column) { - return file.GetTypeDefinition (new AstLocation (line, column)); + return file.GetInnermostTypeDefinition (new TextLocation (line, column)); } /// @@ -246,7 +262,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public static IMember GetMember (this IParsedFile file, int line, int column) { - return file.GetMember (new AstLocation (line, column)); + return file.GetMember (new TextLocation (line, column)); } #endregion diff --git a/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs b/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs index 9c33b586e..bc7d8dabb 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAccessor.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs index c7f8e7c23..a62262255 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAnnotatable.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -63,11 +78,13 @@ namespace ICSharpCode.NRefactory void RemoveAnnotations(Type type); } + [Serializable] public abstract class AbstractAnnotatable : IAnnotatable { // Annotations: points either null (no annotations), to the single annotation, // or to an AnnotationList. // Once it is pointed at an AnnotationList, it will never change (this allows thread-safety support by locking the list) + [NonSerialized] protected object annotations; sealed class AnnotationList : List, ICloneable diff --git a/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs b/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs index ff6abe9eb..5743278bd 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IAttribute.cs @@ -1,10 +1,27 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Diagnostics.Contracts; +using ICSharpCode.NRefactory.Semantics; + namespace ICSharpCode.NRefactory.TypeSystem { /// @@ -29,12 +46,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the positional arguments passed to the attribute. /// - IList GetPositionalArguments(ITypeResolveContext context); + IList GetPositionalArguments(ITypeResolveContext context); /// /// Gets the named arguments passed to the attribute. /// - IList> GetNamedArguments(ITypeResolveContext context); + IList> GetNamedArguments(ITypeResolveContext context); /// /// Resolves the constructor method used for this attribute invocation. diff --git a/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs b/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs index 8ea9a8f3d..342ec2c4d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IConstantValue.cs @@ -1,8 +1,24 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Diagnostics.Contracts; +using ICSharpCode.NRefactory.Semantics; namespace ICSharpCode.NRefactory.TypeSystem { @@ -12,40 +28,21 @@ namespace ICSharpCode.NRefactory.TypeSystem public interface IConstantValue : IFreezable { /// - /// Gets the type of the constant value. + /// Resolves the value of this constant. /// - IType GetValueType(ITypeResolveContext context); - - /// - /// Gets the .NET value of the constant value. - /// Possible return values are: - /// - null - /// - primitive integers - /// - float/double - /// - bool - /// - string - /// - IType (for typeof-expressions) - /// and arrays of these values. Enum values are returned using the underlying primitive integer. - /// - /// TODO: how do we represent errors (value not available?) - /// - object GetValue(ITypeResolveContext context); + /// Type resolve context where the constant value will be used. + /// Resolve result representing the constant value. + ResolveResult Resolve(ITypeResolveContext context); } #if WITH_CONTRACTS [ContractClassFor(typeof(IConstantValue))] abstract class IConstantValueContract : IFreezableContract, IConstantValue { - IType IConstantValue.GetValueType(ITypeResolveContext context) - { - Contract.Requires(context != null); - Contract.Ensures(Contract.Result() != null); - return null; - } - - object IConstantValue.GetValue(ITypeResolveContext context) + ResolveResult IConstantValue.Resolve(ITypeResolveContext context) { Contract.Requires(context != null); + Contract.Ensures(Contract.Result() != null); return null; } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IConversions.cs b/ICSharpCode.NRefactory/TypeSystem/IConversions.cs deleted file mode 100644 index 5495a78b7..000000000 --- a/ICSharpCode.NRefactory/TypeSystem/IConversions.cs +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; - -namespace ICSharpCode.NRefactory.TypeSystem -{ - /// - /// Interface used to check whether types are convertible. - /// - public interface IConversions - { - bool ImplicitConversion(IType fromType, IType toType); - bool ImplicitReferenceConversion(IType fromType, IType toType); - } -} diff --git a/ICSharpCode.NRefactory/TypeSystem/IDocumentationProvider.cs b/ICSharpCode.NRefactory/TypeSystem/IDocumentationProvider.cs index fbd74b75c..4e2985aff 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IDocumentationProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IDocumentationProvider.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/TypeSystem/IEntity.cs b/ICSharpCode.NRefactory/TypeSystem/IEntity.cs index 74bdec380..ebc2349b9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IEntity.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IEntity.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -122,6 +137,12 @@ namespace ICSharpCode.NRefactory.TypeSystem /// IProjectContent ProjectContent { get; } + /// + /// Gets the parsed file in which this entity is defined. + /// Returns null if this entity wasn't parsed (loaded with CecilLoader). + /// + IParsedFile ParsedFile { get; } + //bool IsAccessible(IClass callingClass, bool isAccessThoughReferenceOfCurrentClass); } diff --git a/ICSharpCode.NRefactory/TypeSystem/IEvent.cs b/ICSharpCode.NRefactory/TypeSystem/IEvent.cs index 8a3d6cbfd..7b709632a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IEvent.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Diagnostics.Contracts; diff --git a/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs b/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs index 60452a670..1e8145f0b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IExplicitInterfaceImplementation.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Diagnostics.Contracts; diff --git a/ICSharpCode.NRefactory/TypeSystem/IField.cs b/ICSharpCode.NRefactory/TypeSystem/IField.cs index c5c015299..2c0ec17e8 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IField.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Diagnostics.Contracts; @@ -19,6 +34,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// new string Name { get; } // solve ambiguity between INamedElement.Name and IVariable.Name + /// + /// Gets the region where the field is declared. + /// + new DomRegion Region { get; } // solve ambiguity between IEntity.Region and IVariable.Region + /// /// Gets whether this field is readonly. /// diff --git a/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs b/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs index baa35f42d..e0b63a28a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IFreezable.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Diagnostics.Contracts; diff --git a/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs index 16b23d063..dc20e18ef 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IInterningProvider.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/TypeSystem/IMember.cs b/ICSharpCode.NRefactory/TypeSystem/IMember.cs index 4a51074bf..60076eae8 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IMember.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/TypeSystem/IMethod.cs b/ICSharpCode.NRefactory/TypeSystem/IMethod.cs index 7f6241b3d..028387e40 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IMethod.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs b/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs index 789108543..cb48e0de4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs +++ b/ICSharpCode.NRefactory/TypeSystem/INamedElement.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Diagnostics.Contracts; diff --git a/ICSharpCode.NRefactory/TypeSystem/IParameter.cs b/ICSharpCode.NRefactory/TypeSystem/IParameter.cs index 3f7d9b082..b76413d43 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParameter.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -22,11 +37,6 @@ namespace ICSharpCode.NRefactory.TypeSystem /// IConstantValue DefaultValue { get; } - /// - /// Gets the code region where the parameter is defined. - /// - DomRegion Region { get; } - /// /// Gets whether this parameter is a C# 'ref' parameter. /// diff --git a/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs b/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs index a60c75133..95333b297 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParameterizedMember.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs b/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs index 0852028f2..625d76944 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IParsedFile.cs @@ -1,9 +1,23 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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.Collections.Generic; -using ICSharpCode.NRefactory.CSharp; namespace ICSharpCode.NRefactory.TypeSystem { @@ -23,9 +37,9 @@ namespace ICSharpCode.NRefactory.TypeSystem string FileName { get; } /// - /// Gets the time of object creation. + /// Gets the time when the file was last written. /// - DateTime ParseTime { get; } + DateTime LastWriteTime { get; } /// /// Gets all top-level type definitions. @@ -37,23 +51,28 @@ namespace ICSharpCode.NRefactory.TypeSystem /// IList AssemblyAttributes { get; } + /// + /// Gets all module attributes that are defined in this file. + /// + IList ModuleAttributes { get; } + /// /// Gets the top-level type defined at the specified location. /// Returns null if no type is defined at that location. /// - ITypeDefinition GetTopLevelTypeDefinition(AstLocation location); + ITypeDefinition GetTopLevelTypeDefinition(TextLocation location); /// /// Gets the type (potentially a nested type) defined at the specified location. /// Returns null if no type is defined at that location. /// - ITypeDefinition GetTypeDefinition(AstLocation location); + ITypeDefinition GetInnermostTypeDefinition(TextLocation location); /// /// Gets the member defined at the specified location. /// Returns null if no member is defined at that location. /// - IMember GetMember(AstLocation location); + IMember GetMember(TextLocation location); /// /// Gets the parser errors. diff --git a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs index 848553114..e2d6ea5a5 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IProjectContent.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -15,11 +30,21 @@ namespace ICSharpCode.NRefactory.TypeSystem #endif public interface IProjectContent : ITypeResolveContext, IAnnotatable { + /// + /// Gets the assembly name (short name). + /// + string AssemblyName { get; } + /// /// Gets the list of all assembly attributes in the project. /// IList AssemblyAttributes { get; } + /// + /// Gets the list of all module attributes in the project. + /// + IList ModuleAttributes { get; } + /// /// Gets a parsed file by its file name. /// @@ -29,6 +54,16 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets the list of all parsed files in the project content. /// IEnumerable Files { get; } + + /// + /// Removes types and attributes from oldFile from the project, and adds those from newFile. + /// + /// + /// It is not allowed to call this method from within a using (var ctx = context.Synchronize()) block + /// that involves this project content: this method is a write operation and might (if implemented using locks) + /// wait until all read operations have finished, causing deadlocks within Synchronize blocks. + /// + void UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile); } #if WITH_CONTRACTS diff --git a/ICSharpCode.NRefactory/TypeSystem/IProperty.cs b/ICSharpCode.NRefactory/TypeSystem/IProperty.cs index 23cbd573c..9155e5cd9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IProperty.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs b/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs index 86de1c379..43573ade4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ISupportsInterning.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs index 085cb25cb..c3f02b1c3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ISynchronizedTypeResolveContext.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/TypeSystem/IType.cs b/ICSharpCode.NRefactory/TypeSystem/IType.cs index 6e64bf120..a4ec551e0 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IType.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -7,11 +22,42 @@ using System.Diagnostics.Contracts; namespace ICSharpCode.NRefactory.TypeSystem { + /// + /// This interface represents a resolved type in the type system. + /// + /// + /// + /// A type is potentially + /// - a type definition (, i.e. a class, struct, interface, delegate, or built-in primitive type) + /// - a parameterized type (, e.g. List<int>) + /// - a type parameter (, e.g. T) + /// - an array () + /// - a pointer () + /// - a managed reference () + /// - one of the special types (, , + /// , ) + /// + /// The property can be used to switch on the kind of a type. + /// + /// + /// IType uses the null object pattern: serves as the null object. + /// Methods or properties returning IType never return null unless documented otherwise. + /// + /// + /// Types should be compared for equality using the method. + /// Identical types do not necessarily use the same object reference. + /// + /// #if WITH_CONTRACTS [ContractClass(typeof(ITypeContract))] #endif public interface IType : ITypeReference, INamedElement, IEquatable { + /// + /// Gets the type kind. + /// + TypeKind Kind { get; } + /// /// Gets whether the type is a reference type or value type. /// @@ -28,7 +74,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the underlying type definition. - /// Can return null for types which do not have a type definition (for example arrays, pointers, type parameters) + /// Can return null for types which do not have a type definition (for example arrays, pointers, type parameters). + /// + /// For partial classes, this method always returns the . /// ITypeDefinition GetDefinition(); @@ -61,45 +109,204 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the direct base types. /// + /// The context used for resolving type references + /// Returns the direct base types including interfaces IEnumerable GetBaseTypes(ITypeResolveContext context); /// /// Gets inner classes (including inherited inner classes). /// - IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null); + /// The context used for resolving type references + /// The filter used to select which types to return. + /// The filter is tested on the original type definitions (before parameterization). + /// + /// + /// If the nested type is generic (and has more type parameters than the outer class), + /// this method will return a parameterized type, + /// where the additional type parameters are set to . + /// + /// + /// Type parameters belonging to the outer class will have the value copied from the outer type + /// if it is a parameterized type. Otherwise, those existing type parameters will be self-parameterized, + /// and thus 'leaked' to the caller in the same way the GetMembers() method does not specialize members + /// from an and 'leaks' type parameters in member signatures. + /// + /// + /// + /// + /// class Base<T> { + /// class Nested<X> {} + /// } + /// class Derived<A, B> : Base<B> {} + /// + /// Derived[string,int].GetNestedTypes() = { Base`1+Nested`1[int, unbound] } + /// Derived.GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } + /// Base[`1].GetNestedTypes() = { Base`1+Nested`1[`1, unbound] } + /// Base.GetNestedTypes() = { Base`1+Nested`1[`0, unbound] } + /// + /// + IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + + // Note that we cannot 'leak' the additional type parameter as we leak the normal type parameters, because + // the index might collide. For example, + // class Base { class Nested {} } + // class Derived : Base { } + // + // Derived.GetNestedTypes() = Base+Nested + // Derived.GetNestedTypes() = Base+Nested<`1, > + // Here `1 refers to B, and there's no way to return X as it would collide with B. /// - /// Gets all methods that can be called on this return type. + /// Gets inner classes (including inherited inner classes) + /// that have typeArguments.Count additional type parameters. /// - /// The list does not include constructors. - IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null); + /// The type arguments passed to the inner class + /// The context used for resolving type references + /// The filter used to select which types to return. + /// The filter is tested on the original type definitions (before parameterization). + /// + /// Type parameters belonging to the outer class will have the value copied from the outer type + /// if it is a parameterized type. Otherwise, those existing type parameters will be self-parameterized, + /// and thus 'leaked' to the caller in the same way the GetMembers() method does not specialize members + /// from an and 'leaks' type parameters in member signatures. + /// + IEnumerable GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// /// Gets all instance constructors for this type. /// - /// This list does not include constructors in base classes or static constructors. - IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null); + /// The context used for resolving type references + /// The filter used to select which constructors to return. + /// The filter is tested on the original method definitions (before specialization). + /// + /// The result does not include constructors in base classes or static constructors. + /// + /// For methods on parameterized types, type substitution will be performed on the method signature, + /// and the appropriate will be returned. + /// + /// + IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers); /// - /// Gets all properties that can be called on this return type. + /// Gets all methods that can be called on this type. /// - IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null); + /// The context used for resolving type references + /// The filter used to select which methods to return. + /// The filter is tested on the original method definitions (before specialization). + /// + /// + /// The result does not include constructors. + /// + /// + /// For methods on parameterized types, type substitution will be performed on the method signature, + /// and the appropriate will be returned. + /// + /// + /// If the method being returned is generic, and this type is a parameterized type where the type + /// arguments involve another method's type parameters, the resulting specialized signature + /// will be ambiguous as to which method a type parameter belongs to. + /// For example, "List[[``0]].GetMethods()" will return "ConvertAll(Converter`2[[``0, ``0]])". + /// + /// If possible, use the other GetMethods() overload to supply type arguments to the method, + /// so that both class and method type parameter can be substituted at the same time, so that + /// the ambiguity can be avoided. + /// + /// + IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// - /// Gets all fields that can be called on this return type. + /// Gets all generic methods that can be called on this type with the specified type arguments. /// - IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null); + /// The type arguments used for the method call. + /// The context used for resolving type references + /// The filter used to select which methods to return. + /// The filter is tested on the original method definitions (before specialization). + /// + /// The result does not include constructors. + /// + /// Type substitution will be performed on the method signature, creating a + /// with the specified type arguments. + /// + /// + /// When the list of type arguments is empty, this method acts like the GetMethods() overload without + /// the type arguments parameter - that is, it also returns generic methods, + /// and the other overload's remarks about ambiguous signatures apply here as well. + /// + /// + IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// - /// Gets all events that can be called on this return type. + /// Gets all properties that can be called on this type. /// - IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null); + /// The context used for resolving type references + /// The filter used to select which properties to return. + /// The filter is tested on the original property definitions (before specialization). + /// + /// For properties on parameterized types, type substitution will be performed on the property signature, + /// and the appropriate will be returned. + /// + IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); /// - /// Gets all members that can be called on this return type. - /// This is the union of GetFields(),GetProperties(),GetMethods() and GetEvents(). This does not include constructors. + /// Gets all fields that can be accessed on this type. + /// + /// The context used for resolving type references + /// The filter used to select which constructors to return. + /// The filter is tested on the original field definitions (before specialization). + /// + /// For fields on parameterized types, type substitution will be performed on the field's return type, + /// and the appropriate will be returned. + /// + IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + + /// + /// Gets all events that can be accessed on this type. + /// + /// The context used for resolving type references + /// The filter used to select which events to return. + /// The filter is tested on the original event definitions (before specialization). + /// + /// For fields on parameterized types, type substitution will be performed on the event's return type, + /// and the appropriate will be returned. + /// + IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + + /// + /// Gets all members that can be called on this type. + /// + /// The context used for resolving type references + /// The filter used to select which members to return. + /// The filter is tested on the original member definitions (before specialization). + /// + /// + /// The resulting list is the union of GetFields(), GetProperties(), GetMethods() and GetEvents(). + /// It does not include constructors. + /// For parameterized types, type substitution will be performed. + /// + /// + /// For generic methods, the remarks about ambiguous signatures from the + /// method apply here as well. + /// + /// + IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None); + } + + [Flags] + public enum GetMemberOptions + { + /// + /// No options specified - this is the default. + /// Members will be specialized, and inherited members will be included. + /// + None = 0x00, + /// + /// Do not specialize the returned members - directly return the definitions. + /// + ReturnMemberDefinitions = 0x01, + /// + /// Do not list inherited members - only list members defined directly on this type. /// - IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null); + IgnoreInheritedMembers = 0x02 } #if WITH_CONTRACTS @@ -130,49 +337,49 @@ namespace ICSharpCode.NRefactory.TypeSystem return null; } - IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { Contract.Requires(context != null); Contract.Ensures(Contract.Result>() != null); return null; } - IEnumerable IType.GetMethods(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetMethods(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { Contract.Requires(context != null); Contract.Ensures(Contract.Result>() != null); return null; } - IEnumerable IType.GetConstructors(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetConstructors(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { Contract.Requires(context != null); Contract.Ensures(Contract.Result>() != null); return null; } - IEnumerable IType.GetProperties(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetProperties(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { Contract.Requires(context != null); Contract.Ensures(Contract.Result>() != null); return null; } - IEnumerable IType.GetFields(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetFields(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { Contract.Requires(context != null); Contract.Ensures(Contract.Result>() != null); return null; } - IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { Contract.Requires(context != null); Contract.Ensures(Contract.Result>() != null); return null; } - IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { Contract.Requires(context != null); Contract.Ensures(Contract.Result>() != null); diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs index 507d5420d..3cc733fce 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeDefinition.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -9,25 +24,16 @@ namespace ICSharpCode.NRefactory.TypeSystem { /// /// Represents a class, enum, interface, struct, delegate or VB module. + /// Also used to represent a part of a partial class. /// #if WITH_CONTRACTS [ContractClass(typeof(ITypeDefinitionContract))] #endif public interface ITypeDefinition : IType, IEntity { - ClassType ClassType { get; } - IList BaseTypes { get; } IList TypeParameters { get; } - /// - /// If this is a partial class, gets the compound class containing information from all parts. - /// If this is not a partial class, a reference to this class is returned. - /// - /// This method will always retrieve the latest version of the class, which might not contain this class as a part. - /// - ITypeDefinition GetCompoundClass(); - /// /// If this is a compound class (combination of class parts), this method retrieves all individual class parts. /// Otherwise, a list containing this is returned. diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs index f9a0cc3cd..6712b7d59 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeParameter.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -57,18 +72,6 @@ namespace ICSharpCode.NRefactory.TypeSystem /// VarianceModifier Variance { get; } - /// - /// Gets the type that was used to bind this type parameter. - /// This property returns null for generic methods/classes, it - /// is non-null only for constructed versions of generic methods. - /// - IType BoundTo { get; } - - /// - /// If this type parameter was bound, returns the unbound version of it. - /// - ITypeParameter UnboundTypeParameter { get; } - /// /// Gets the region where the type parameter is defined. /// diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs index 50795311b..c5655da9b 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeReference.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -25,6 +40,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Resolves this type reference. /// + /// + /// Returns the resolved type. + /// In case of an error, returns . + /// Never returns null. + /// IType Resolve(ITypeResolveContext context); } diff --git a/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs index b1490a653..6da0ef7fe 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ITypeResolveContext.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -17,6 +32,16 @@ namespace ICSharpCode.NRefactory.TypeSystem #endif public interface ITypeResolveContext { + /// + /// Gets the definition for a known type. + /// + /// Returns the type definition; or null if the type was not found + /// + /// This method will may only be called with the 'known types' (see members of KnownTypeReference). + /// As a special case, TypeCode.Empty is used to represent System.Void. + /// + ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode); + /// /// Retrieves a type. /// diff --git a/ICSharpCode.NRefactory/TypeSystem/IVariable.cs b/ICSharpCode.NRefactory/TypeSystem/IVariable.cs index b5a0bad88..4adab34c4 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IVariable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IVariable.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Diagnostics.Contracts; @@ -22,7 +37,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Gets the declaration region of the variable. /// - DomRegion DeclarationRegion { get; } + DomRegion Region { get; } /// /// Gets the type of the variable. diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs index 10ca6ee6e..7cc8cf63a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractFreezable.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -12,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 { @@ -23,6 +39,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } + [Serializable] public abstract class AbstractFreezable : IFreezable { bool isFrozen; @@ -63,7 +80,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return new List(inputList); } - protected static ReadOnlyCollection FreezeList(IList list) where T : IFreezable + protected static IList FreezeList(IList list) where T : IFreezable { if (list == null || list.Count == 0) return EmptyList.Instance; @@ -74,7 +91,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return result; } - protected static ReadOnlyCollection FreezeList(IList list) + protected static IList FreezeList(IList list) { if (list == null || list.Count == 0) return EmptyList.Instance; @@ -82,7 +99,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return new ReadOnlyCollection(list.ToArray()); } - protected static ReadOnlyCollection FreezeList(IList list) + protected static IList FreezeList(IList list) { if (list == null || list.Count == 0) return EmptyList.Instance; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs index 7d5961b9c..15a0d63ea 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractMember.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -10,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: @@ -255,6 +271,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return declaringTypeDefinition.ProjectContent; } } + public IParsedFile ParsedFile { + get { return declaringTypeDefinition.ParsedFile; } + } + public string Name { get { return name; } set { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs index 76cc4db1d..d05baba10 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/AbstractType.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -11,6 +26,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation for IType interface. /// + [Serializable] public abstract class AbstractType : IType { public virtual string FullName { @@ -37,6 +53,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public abstract bool? IsReferenceType(ITypeResolveContext context); + public abstract TypeKind Kind { get; } + public virtual int TypeParameterCount { get { return 0; } } @@ -60,42 +78,53 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return EmptyList.Instance; } - public virtual IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + return EmptyList.Instance; + } + + public virtual IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { return EmptyList.Instance; } - public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { return EmptyList.Instance; } - public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - return GetMethods(context, filter).SafeCast() - .Concat(GetProperties(context, filter).SafeCast()) - .Concat(GetFields(context, filter).SafeCast()) - .Concat(GetEvents(context, filter).SafeCast()); + IEnumerable members = GetMethods(context, filter, options); + return members + .Concat(GetProperties(context, filter, options)) + .Concat(GetFields(context, filter, options)) + .Concat(GetEvents(context, filter, options)); } public override bool Equals(object obj) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs new file mode 100644 index 000000000..38a6c0e5c --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/BaseTypeCollector.cs @@ -0,0 +1,81 @@ +// 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.Collections.Generic; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Helper class for the GetAllBaseTypes() implementation. + /// + sealed class BaseTypeCollector : List + { + readonly ITypeResolveContext context; + readonly Stack activeTypes = new Stack(); + + /// + /// If this option is enabled, the list will not contain interfaces when retrieving the base types + /// of a class. + /// + internal bool SkipImplementedInterfaces; + + public BaseTypeCollector(ITypeResolveContext context) + { + this.context = context; + } + + public void CollectBaseTypes(IType type) + { + IType def = type.GetDefinition() ?? type; + + // Maintain a stack of currently active type definitions, and avoid having one definition + // multiple times on that stack. + // This is necessary to ensure the output is finite in the presence of cyclic inheritance: + // class C : C> {} would not be caught by the 'no duplicate output' check, yet would + // produce infinite output. + if (activeTypes.Contains(def)) + return; + activeTypes.Push(def); + // Note that we also need to push non-type definitions, e.g. for protecting against + // cyclic inheritance in type parameters (where T : S where S : T). + // The output check doesn't help there because we call Add(type) only at the end. + // We can't simply call this.Add(type); at the start because that would return in an incorrect order. + + // Avoid outputting a type more than once - necessary for "diamond" multiple inheritance + // (e.g. C implements I1 and I2, and both interfaces derive from Object) + if (!this.Contains(type)) { + foreach (IType baseType in type.GetBaseTypes(context)) { + if (SkipImplementedInterfaces && def != null && def.Kind != TypeKind.Interface) { + if (baseType.Kind == TypeKind.Interface) { + // skip the interface + continue; + } + } + CollectBaseTypes(baseType); + } + // Add(type) at the end - we want a type to be output only after all its base types were added. + this.Add(type); + // Note that this is not the same as putting the this.Add() call in front and then reversing the list. + // For the diamond inheritance, Add() at the start produces "C, I1, Object, I2", + // while Add() at the end produces "Object, I1, I2, C". + } + activeTypes.Pop(); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs index d8d9d2319..77b71e6b1 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/CompositeTypeResolveContext.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -51,6 +66,17 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.children = children; } + /// + public virtual ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) + { + foreach (ITypeResolveContext context in children) { + ITypeDefinition d = context.GetKnownTypeDefinition(typeCode); + if (d != null) + return d; + } + return null; + } + /// public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { @@ -100,9 +126,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation for (int i = 0; i < sync.Length; i++) { sync[i] = children[i].Synchronize(); if (sync[i] == null) - throw new InvalidOperationException(children[i] + ".ToString() returned null"); + throw new InvalidOperationException(children[i] + ".Synchronize() returned null"); } - ISynchronizedTypeResolveContext r = new CompositeSynchronizedTypeResolveContext(sync, new CacheManager(), true); + var knownTypeDefinitions = new ITypeDefinition[ReflectionHelper.ByTypeCodeArraySize]; + var r = new CompositeSynchronizedTypeResolveContext(sync, knownTypeDefinitions, new CacheManager(), true); success = true; return r; } finally { @@ -126,12 +153,14 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { readonly CacheManager cacheManager; readonly bool isTopLevel; + readonly ITypeDefinition[] knownTypeDefinitions; - public CompositeSynchronizedTypeResolveContext(ITypeResolveContext[] children, CacheManager cacheManager, bool isTopLevel) + public CompositeSynchronizedTypeResolveContext(ITypeResolveContext[] children, ITypeDefinition[] knownTypeDefinitions, CacheManager cacheManager, bool isTopLevel) : base(children) { Debug.Assert(cacheManager != null); this.cacheManager = cacheManager; + this.knownTypeDefinitions = knownTypeDefinitions; this.isTopLevel = isTopLevel; } @@ -152,11 +181,21 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return cacheManager; } } + public override ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) + { + ITypeDefinition typeDef = knownTypeDefinitions[(int)typeCode]; + if (typeDef != null) + return typeDef; + typeDef = base.GetKnownTypeDefinition(typeCode); + knownTypeDefinitions[(int)typeCode] = typeDef; + return typeDef; + } + public override ISynchronizedTypeResolveContext Synchronize() { // re-use the same cache manager for nested synchronized contexts if (isTopLevel) - return new CompositeSynchronizedTypeResolveContext(children, cacheManager, false); + return new CompositeSynchronizedTypeResolveContext(children, knownTypeDefinitions, cacheManager, false); else return this; } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs new file mode 100644 index 000000000..0d9171d76 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/CompoundTypeDefinition.cs @@ -0,0 +1,151 @@ +// 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.Collections.Generic; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Type definition that represents a partial class with multiple parts. + /// + [Serializable] + public class CompoundTypeDefinition : DefaultTypeDefinition + { + IList parts; + + private CompoundTypeDefinition(ITypeDefinition declaringTypeDefinition, string name) + : base(declaringTypeDefinition, name) + { + } + + private CompoundTypeDefinition(IParsedFile parsedFile, string ns, string name) + : base(parsedFile, ns, name) + { + } + + private CompoundTypeDefinition(IProjectContent projectContent, string ns, string name) + : base(projectContent, ns, name) + { + } + + protected override void FreezeInternal() + { + parts = FreezeList(parts); + base.FreezeInternal(); + } + + public override IList GetParts() + { + return parts; + } + + public override string Documentation { + get { return parts[0].Documentation; } + } + + public static ITypeDefinition Create(IList parts) + { + if (parts == null || parts.Count == 0) + throw new ArgumentException("parts"); + + ITypeDefinition mainPart = parts[0]; + for (int i = 1; i < parts.Count; i++) { + if (PreferAsMainPart(parts[i], mainPart)) + mainPart = parts[i]; + } + if (parts.Count == 1) { + ((DefaultTypeDefinition)mainPart).SetCompoundTypeDefinition(mainPart); + return mainPart; + } + + CompoundTypeDefinition compound; + if (mainPart.DeclaringTypeDefinition != null) { + throw new NotImplementedException("nested compound types not implemented"); + } else { + if (mainPart.ParsedFile != null) + compound = new CompoundTypeDefinition(mainPart.ParsedFile, mainPart.Namespace, mainPart.Name); + else + compound = new CompoundTypeDefinition(mainPart.ProjectContent, mainPart.Namespace, mainPart.Name); + } + compound.parts = parts; + compound.Region = mainPart.Region; + compound.BodyRegion = mainPart.BodyRegion; + compound.TypeParameters.AddRange(mainPart.TypeParameters); + compound.IsSynthetic = mainPart.IsSynthetic; + compound.Accessibility = mainPart.Accessibility; + + bool allPartsFrozen = true; + foreach (DefaultTypeDefinition part in parts) { + compound.BaseTypes.AddRange(part.BaseTypes); + compound.Attributes.AddRange(part.Attributes); + compound.NestedTypes.AddRange(part.NestedTypes); + compound.Methods.AddRange(part.Methods); + compound.Properties.AddRange(part.Properties); + compound.Events.AddRange(part.Events); + compound.Fields.AddRange(part.Fields); + + if (part.IsAbstract) + compound.IsAbstract = true; + if (part.IsSealed) + compound.IsSealed = true; + if (part.IsShadowing) + compound.IsShadowing = true; + if (part.HasExtensionMethods) + compound.HasExtensionMethods = true; + if (part.AddDefaultConstructorIfRequired) + compound.AddDefaultConstructorIfRequired = true; + + // internal is the default, so use another part's accessibility until we find a non-internal accessibility + if (compound.Accessibility == Accessibility.Internal) + compound.Accessibility = part.Accessibility; + + allPartsFrozen &= part.IsFrozen; + } + + if (allPartsFrozen) { + // If all parts are frozen, also freeze the compound typedef. + compound.Freeze(); + } + // Publish the compound class via part.compoundTypeDefinition only after it has been frozen. + foreach (DefaultTypeDefinition part in parts) { + part.SetCompoundTypeDefinition(compound); + } + + return compound; + } + + /// + /// Gets whether part1 should be preferred as main part over part2. + /// + static bool PreferAsMainPart(ITypeDefinition part1, ITypeDefinition part2) + { + if (part1.IsSynthetic != part2.IsSynthetic) + return part2.IsSynthetic; // prefer non-synthetic part + string file1 = part1.Region.FileName; + string file2 = part2.Region.FileName; + if ((file1 != null) != (file2 != null)) + return file1 != null; // prefer part with file name + if (file1 != null && file2 != null) { + return file1.Length < file2.Length; // prefer shorter file name (file without Designer suffix) + } + return false; + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs index 917b1f473..3be4ba66d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAccessor.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -10,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 15f8a1815..a779f314f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultAttribute.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -7,11 +22,14 @@ using System.Collections.ObjectModel; using System.Linq; using System.Text; +using ICSharpCode.NRefactory.Semantics; + namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// /// Default implementation of . /// + [Serializable] public sealed class DefaultAttribute : AbstractFreezable, IAttribute, ISupportsInterning { ITypeReference attributeType; @@ -68,9 +86,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - IList IAttribute.GetPositionalArguments(ITypeResolveContext context) + public IList GetPositionalArguments(ITypeResolveContext context) { - return this.PositionalArguments; + return this.PositionalArguments.Select(a => a.Resolve(context)).ToList(); } public IList> NamedArguments { @@ -81,9 +99,9 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - IList> IAttribute.GetNamedArguments(ITypeResolveContext context) + public IList> GetNamedArguments(ITypeResolveContext context) { - return this.NamedArguments; + return this.NamedArguments.Select(p => new KeyValuePair(p.Key, p.Value.Resolve(context))).ToList(); } public IMethod ResolveConstructor(ITypeResolveContext context) @@ -163,5 +181,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation DefaultAttribute a = other as DefaultAttribute; return a != null && attributeType == a.attributeType && positionalArguments == a.positionalArguments && namedArguments == a.namedArguments && region == a.region; } + + public void AddNamedArgument(string name, ITypeReference type, object value) + { + AddNamedArgument(name, new SimpleConstantValue(type, value)); + } + + public void AddNamedArgument(string name, IConstantValue value) + { + CheckBeforeMutation(); + this.NamedArguments.Add(new KeyValuePair(name, value)); + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs index c5c35ea1f..bea77a960 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultEvent.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -8,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/DefaultExplicitInterfaceImplementation.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs index 1cf12df69..aa857f000 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultExplicitInterfaceImplementation.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -8,6 +23,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation for IExplicitInterfaceImplementation. /// + [Serializable] public sealed class DefaultExplicitInterfaceImplementation : Immutable, IExplicitInterfaceImplementation, ISupportsInterning { public ITypeReference InterfaceType { get; private set; } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs index c4fd96b3e..22c33d980 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultField.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -8,6 +23,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public class DefaultField : AbstractMember, IField { IConstantValue constantValue; @@ -41,12 +57,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation constantValue = provider.Intern(constantValue); } - DomRegion IVariable.DeclarationRegion { - get { - return Region; - } - } - public bool IsConst { get { return constantValue != null; } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs index a0c57feda..203cd31ff 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultMethod.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -10,6 +25,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of interface. /// + [Serializable] public class DefaultMethod : AbstractMember, IMethod { IList returnTypeAttributes; @@ -108,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 08455723e..97818b4a6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultParameter.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -11,6 +26,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation for IParameter. /// + [Serializable] public sealed class DefaultParameter : AbstractFreezable, IParameter, ISupportsInterning { string name = string.Empty; @@ -89,14 +105,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - public object GetDefaultValue(ITypeResolveContext context) - { - if (defaultValue == null) - throw new InvalidOperationException(); - else - return defaultValue.GetValue(context); - } - public DomRegion Region { get { return region; } set { @@ -105,12 +113,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - DomRegion IVariable.DeclarationRegion { - get { - return Region; - } - } - bool HasFlag(byte flag) { return (this.flags & flag) != 0; @@ -153,13 +155,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation int ISupportsInterning.GetHashCodeForInterning() { - return type.GetHashCode() ^ (attributes != null ? attributes.GetHashCode() : 0) ^ (defaultValue != null ? defaultValue.GetHashCode() : 0); + return type.GetHashCode() ^ name.GetHashCode() + ^ (attributes != null ? attributes.GetHashCode() : 0) + ^ (defaultValue != null ? defaultValue.GetHashCode() : 0); } bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) { DefaultParameter p = other as DefaultParameter; - return p != null && type == p.type && attributes == p.attributes + return p != null && type == p.type && attributes == p.attributes && name == p.name && defaultValue == p.defaultValue && region == p.region && flags == p.flags; } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs index 558dc6eb3..8e3ec666f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultProperty.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -9,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 f9ee9a45e..e05d7f079 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeDefinition.cs @@ -1,21 +1,39 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; -using System.Diagnostics.Contracts; using System.Globalization; using System.Linq; - +using System.Runtime.CompilerServices; using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + [Serializable] public class DefaultTypeDefinition : AbstractFreezable, ITypeDefinition { readonly IProjectContent projectContent; + readonly IParsedFile parsedFile; readonly ITypeDefinition declaringTypeDefinition; + volatile ITypeDefinition compoundTypeDefinition; + string ns; string name; @@ -32,7 +50,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation DomRegion bodyRegion; // 1 byte per enum + 2 bytes for flags - ClassType classType; + TypeKind kind = TypeKind.Class; Accessibility accessibility; BitVector16 flags; const ushort FlagSealed = 0x0001; @@ -62,9 +80,27 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (string.IsNullOrEmpty(name)) throw new ArgumentException("name"); this.projectContent = declaringTypeDefinition.ProjectContent; + this.parsedFile = declaringTypeDefinition.ParsedFile; this.declaringTypeDefinition = declaringTypeDefinition; + this.name = name; this.ns = declaringTypeDefinition.Namespace; + + this.compoundTypeDefinition = this; + } + + public DefaultTypeDefinition(IParsedFile parsedFile, string ns, string name) + { + if (parsedFile == null) + throw new ArgumentNullException("parsedFile"); + if (string.IsNullOrEmpty(name)) + throw new ArgumentException("name"); + this.parsedFile = parsedFile; + this.projectContent = parsedFile.ProjectContent; + this.ns = ns ?? string.Empty; + this.name = name; + + this.compoundTypeDefinition = this; } public DefaultTypeDefinition(IProjectContent projectContent, string ns, string name) @@ -76,13 +112,30 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.projectContent = projectContent; this.ns = ns ?? string.Empty; this.name = name; + + this.compoundTypeDefinition = this; } - public ClassType ClassType { - get { return classType; } + public TypeKind Kind { + get { return kind; } set { CheckBeforeMutation(); - classType = value; + kind = value; + } + } + + public bool? IsReferenceType(ITypeResolveContext context) + { + switch (kind) { + case TypeKind.Class: + case TypeKind.Interface: + case TypeKind.Delegate: + return true; + case TypeKind.Enum: + case TypeKind.Struct: + return false; + default: + return null; } } @@ -155,25 +208,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public IEnumerable Members { get { - return this.Fields.SafeCast() - .Concat(this.Properties.SafeCast()) - .Concat(this.Methods.SafeCast()) - .Concat(this.Events.SafeCast()); - } - } - - public bool? IsReferenceType(ITypeResolveContext context) - { - switch (this.ClassType) { - case ClassType.Class: - case ClassType.Interface: - case ClassType.Delegate: - return true; - case ClassType.Enum: - case ClassType.Struct: - return false; - default: - return null; + IEnumerable members = this.Fields; + return members + .Concat(this.Properties) + .Concat(this.Methods) + .Concat(this.Events); } } @@ -265,7 +304,15 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } public virtual string Documentation { - get { return null; } + get { + // To save memory, we don't store the documentation provider within the type, + // but use our the project content as a documentation provider: + IDocumentationProvider provider = projectContent as IDocumentationProvider; + if (provider != null) + return provider.GetDocumentation(this); + else + return null; + } } public Accessibility Accessibility { @@ -348,43 +395,56 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation get { return projectContent; } } + public IParsedFile ParsedFile { + get { return parsedFile; } + } + public IEnumerable GetBaseTypes(ITypeResolveContext context) + { + ITypeDefinition compound = this.compoundTypeDefinition; + if (compound != this) + return compound.GetBaseTypes(context); + else + return GetBaseTypesImpl(context); + } + + IEnumerable GetBaseTypesImpl(ITypeResolveContext context) { bool hasNonInterface = false; - if (baseTypes != null && this.ClassType != ClassType.Enum) { + if (baseTypes != null && kind != TypeKind.Enum) { foreach (ITypeReference baseTypeRef in baseTypes) { IType baseType = baseTypeRef.Resolve(context); - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef == null || baseTypeDef.ClassType != ClassType.Interface) + if (baseType.Kind != TypeKind.Interface) hasNonInterface = true; yield return baseType; } } if (!hasNonInterface && !(this.Name == "Object" && this.Namespace == "System" && this.TypeParameterCount == 0)) { - Type primitiveBaseType; - switch (classType) { - case ClassType.Enum: - primitiveBaseType = typeof(Enum); + string primitiveBaseType; + switch (kind) { + case TypeKind.Enum: + primitiveBaseType = "Enum"; break; - case ClassType.Struct: - primitiveBaseType = typeof(ValueType); + case TypeKind.Struct: + case TypeKind.Void: + primitiveBaseType = "ValueType"; break; - case ClassType.Delegate: - primitiveBaseType = typeof(Delegate); + case TypeKind.Delegate: + primitiveBaseType = "Delegate"; break; default: - primitiveBaseType = typeof(object); + primitiveBaseType = "Object"; break; } - IType t = context.GetTypeDefinition(primitiveBaseType); + IType t = context.GetTypeDefinition("System", primitiveBaseType, 0, StringComparer.Ordinal); if (t != null) yield return t; } } - public virtual ITypeDefinition GetCompoundClass() + internal void SetCompoundTypeDefinition(ITypeDefinition compoundTypeDefinition) { - return this; + this.compoundTypeDefinition = compoundTypeDefinition; } public virtual IList GetParts() @@ -394,222 +454,171 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public ITypeDefinition GetDefinition() { - return this; + return compoundTypeDefinition; } - public IType Resolve(ITypeResolveContext context) + IType ITypeReference.Resolve(ITypeResolveContext context) { if (context == null) throw new ArgumentNullException("context"); return this; } - public virtual IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null) + #region GetMembers + public IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetNestedTypes(context, filter); - - List nestedTypes = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - foreach (var baseTypeRef in this.BaseTypes) { - IType baseType = baseTypeRef.Resolve(context); - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && baseTypeDef.ClassType != ClassType.Interface) { - // get nested types from baseType (not baseTypeDef) so that generics work correctly - nestedTypes.AddRange(baseType.GetNestedTypes(context, filter)); - break; // there is at most 1 non-interface base - } - } - foreach (ITypeDefinition nestedType in this.NestedTypes) { - if (filter == null || filter(nestedType)) { - nestedTypes.Add(nestedType); - } - } - } + const GetMemberOptions opt = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions; + if ((options & opt) == opt) { + ITypeDefinition compound = this.compoundTypeDefinition; + if (compound != this) + return compound.GetNestedTypes(context, filter, options); + + return ApplyFilter(this.NestedTypes, filter); + } else { + return GetMembersHelper.GetNestedTypes(this, context, filter, options); } - return nestedTypes; } - public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetMethods(context, filter); - - List methods = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - methods.AddRange(baseType.GetMethods(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(methods); - AddFilteredRange(methods, this.Methods.Where(m => !m.IsConstructor), filter); - } + return GetMembersHelper.GetNestedTypes(this, typeArguments, context, filter, options); + } + + public virtual IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + ITypeDefinition compound = this.compoundTypeDefinition; + if (compound != this) + return compound.GetMethods(context, filter, options); + + return ApplyFilter(this.Methods, Utils.ExtensionMethods.And(m => !m.IsConstructor, filter)); + } else { + return GetMembersHelper.GetMethods(this, context, filter, options); } - return methods; } - public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetConstructors(context, filter); - - List methods = new List(); - AddFilteredRange(methods, this.Methods.Where(m => m.IsConstructor && !m.IsStatic), filter); + return GetMembersHelper.GetMethods(this, typeArguments, context, filter, options); + } + + public virtual IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + ITypeDefinition compound = this.compoundTypeDefinition; + if (compound != this) + return compound.GetConstructors(context, filter, options); + + return GetConstructorsImpl(filter); + } else { + return GetMembersHelper.GetConstructors(this, context, filter, options); + } + } + + IEnumerable GetConstructorsImpl(Predicate filter) + { + bool foundCtor = false; + foreach (IMethod m in this.Methods) { + if (m.IsConstructor && !m.IsStatic) { + foundCtor = true; + if (filter == null || filter(m)) { + yield return m; + } + } + } if (this.AddDefaultConstructorIfRequired) { - if (this.ClassType == ClassType.Class && methods.Count == 0 - || this.ClassType == ClassType.Enum || this.ClassType == ClassType.Struct) + if (kind == TypeKind.Class && !foundCtor && !this.IsStatic + || kind == TypeKind.Enum || kind == TypeKind.Struct) { var m = DefaultMethod.CreateDefaultConstructor(this); if (filter == null || filter(m)) - methods.Add(m); + yield return m; } } - return methods; } - public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetProperties(context, filter); - - List properties = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - properties.AddRange(baseType.GetProperties(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(properties); - AddFilteredRange(properties, this.Properties, filter); - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + ITypeDefinition compound = this.compoundTypeDefinition; + if (compound != this) + return compound.GetProperties(context, filter, options); + + return ApplyFilter(this.Properties, filter); + } else { + return GetMembersHelper.GetProperties(this, context, filter, options); } - return properties; } - public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetFields(context, filter); - - List fields = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - fields.AddRange(baseType.GetFields(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(fields); - AddFilteredRange(fields, this.Fields, filter); - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + ITypeDefinition compound = this.compoundTypeDefinition; + if (compound != this) + return compound.GetFields(context, filter, options); + + return ApplyFilter(this.Fields, filter); + } else { + return GetMembersHelper.GetFields(this, context, filter, options); } - return fields; } - public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetEvents(context, filter); - - List events = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - events.AddRange(baseType.GetEvents(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(events); - AddFilteredRange(events, this.Events, filter); - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + ITypeDefinition compound = this.compoundTypeDefinition; + if (compound != this) + return compound.GetEvents(context, filter, options); + + return ApplyFilter(this.Events, filter); + } else { + return GetMembersHelper.GetEvents(this, context, filter, options); } - return events; } - public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + public virtual IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - ITypeDefinition compound = GetCompoundClass(); - if (compound != this) - return compound.GetMembers(context, filter); - - List members = new List(); - using (var busyLock = BusyManager.Enter(this)) { - if (busyLock.Success) { - int baseCount = 0; - foreach (var baseType in GetBaseTypes(context)) { - ITypeDefinition baseTypeDef = baseType.GetDefinition(); - if (baseTypeDef != null && (baseTypeDef.ClassType != ClassType.Interface || this.ClassType == ClassType.Interface)) { - members.AddRange(baseType.GetMembers(context, filter)); - baseCount++; - } - } - if (baseCount > 1) - RemoveDuplicates(members); - AddFilteredRange(members, this.Methods.Where(m => !m.IsConstructor), filter); - AddFilteredRange(members, this.Properties, filter); - AddFilteredRange(members, this.Fields, filter); - AddFilteredRange(members, this.Events, filter); - } - } - return members; + return GetMembersHelper.GetMembers(this, context, filter, options); } - static void AddFilteredRange(List targetList, IEnumerable sourceList, Predicate filter) where T : class + static IEnumerable ApplyFilter(IList enumerable, Predicate filter) where T : class { - if (filter == null) { - targetList.AddRange(sourceList); - } else { - foreach (T element in sourceList) { - if (filter(element)) - targetList.Add(element); - } - } + if (enumerable.Count == 0) + return EmptyList.Instance; + if (filter == null) + return enumerable; + else + return ApplyFilterImpl(enumerable, filter); } - /// - /// Removes duplicate members from the list. - /// This is necessary when the same member can be inherited twice due to multiple inheritance. - /// - static void RemoveDuplicates(List list) where T : class + static IEnumerable ApplyFilterImpl(IList enumerable, Predicate filter) where T : class { - if (list.Count > 1) { - HashSet hash = new HashSet(); - list.RemoveAll(m => !hash.Add(m)); - } + foreach (T item in enumerable) + if (filter(item)) + yield return item; } + #endregion - // we use reference equality + #region Equals / GetHashCode bool IEquatable.Equals(IType other) { - return this == other; + // Two ITypeDefinitions are considered to be equal if they have the same compound class. + ITypeDefinition typeDef = other as ITypeDefinition; + return typeDef != null && this.GetDefinition() == typeDef.GetDefinition(); + } + + public override bool Equals(object obj) + { + ITypeDefinition typeDef = obj as ITypeDefinition; + return typeDef != null && this.GetDefinition() == typeDef.GetDefinition(); + } + + public override int GetHashCode() + { + return RuntimeHelpers.GetHashCode(compoundTypeDefinition); } + #endregion public override string ToString() { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs index ec8ce7007..424c55cdb 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/DefaultTypeParameter.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -12,6 +27,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Default implementation of . /// + [Serializable] public sealed class DefaultTypeParameter : AbstractFreezable, ITypeParameter, ISupportsInterning { string name; @@ -50,6 +66,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.name = name; } + public TypeKind Kind { + get { return TypeKind.TypeParameter; } + } + public string Name { get { return name; } } @@ -87,7 +107,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation ITypeDefinition constraintDef = constraint.GetDefinition(); // While interfaces are reference types, an interface constraint does not // force the type parameter to be a reference type; so we need to explicitly look for classes here. - if (constraintDef != null && constraintDef.ClassType == ClassType.Class) + if (constraintDef != null && constraintDef.Kind == TypeKind.Class) return true; if (constraint is ITypeParameter) { bool? isReferenceType = constraint.IsReferenceType(context); @@ -118,24 +138,27 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return this; } - public override int GetHashCode() - { - unchecked { - return (int)ownerType * 178256151 + index; - } - } - - public override bool Equals(object obj) - { - return Equals(obj as IType); - } +// public override int GetHashCode() +// { +// unchecked { +// return (int)ownerType * 178256151 + index; +// } +// } +// +// public override bool Equals(object obj) +// { +// return Equals(obj as IType); +// } public bool Equals(IType other) { - DefaultTypeParameter p = other as DefaultTypeParameter; - if (p == null) - return false; - return ownerType == p.ownerType && index == p.index; + // Use reference equality for type parameters. While we could consider any types with same + // ownerType + index as equal for the type system, doing so makes it difficult to cache calculation + // results based on types - e.g. the cache in the Conversions class. + return this == other; + // We can still consider type parameters of different methods/classes to be equal to each other, + // if they have been interned. But then also all constraints are equal, so caching conversions + // is valid in that case. } public EntityType OwnerType { @@ -204,14 +227,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } - IType ITypeParameter.BoundTo { - get { return null; } - } - - ITypeParameter ITypeParameter.UnboundTypeParameter { - get { return null; } - } - public IType AcceptVisitor(TypeVisitor visitor) { return visitor.VisitTypeParameter(this); @@ -229,110 +244,91 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation DefaultTypeDefinition c = new DefaultTypeDefinition(dummyProjectContent, string.Empty, this.Name); c.Region = this.Region; if (HasValueTypeConstraint) { - c.ClassType = ClassType.Struct; + c.Kind = TypeKind.Struct; } else if (HasDefaultConstructorConstraint) { - c.ClassType = ClassType.Class; + c.Kind = TypeKind.Class; } else { - c.ClassType = ClassType.Interface; + c.Kind = TypeKind.Interface; } return c; } - public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { - if (HasDefaultConstructorConstraint || HasValueTypeConstraint) { - DefaultMethod m = DefaultMethod.CreateDefaultConstructor(GetDummyClassForTypeParameter()); - if (filter(m)) - return new [] { m }; + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + if (HasDefaultConstructorConstraint || HasValueTypeConstraint) { + DefaultMethod m = DefaultMethod.CreateDefaultConstructor(GetDummyClassForTypeParameter()); + if (filter(m)) + return new [] { m }; + } + return EmptyList.Instance; + } else { + return GetMembersHelper.GetConstructors(this, context, filter, options); } - return EmptyList.Instance; } - public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - foreach (var baseType in GetNonCircularBaseTypes(context)) { - foreach (var m in baseType.GetMethods(context, filter)) { - if (!m.IsStatic) - yield return m; - } - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetMethods(this, context, FilterNonStatic(filter), options); } - public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - foreach (var baseType in GetNonCircularBaseTypes(context)) { - foreach (var m in baseType.GetProperties(context, filter)) { - if (!m.IsStatic) - yield return m; - } - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetMethods(this, typeArguments, context, FilterNonStatic(filter), options); } - public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - foreach (var baseType in GetNonCircularBaseTypes(context)) { - foreach (var m in baseType.GetFields(context, filter)) { - if (!m.IsStatic) - yield return m; - } - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetProperties(this, context, FilterNonStatic(filter), options); } - public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - foreach (var baseType in GetNonCircularBaseTypes(context)) { - foreach (var m in baseType.GetEvents(context, filter)) { - if (!m.IsStatic) - yield return m; - } - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetFields(this, context, FilterNonStatic(filter), options); } - public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - foreach (var baseType in GetNonCircularBaseTypes(context)) { - foreach (var m in baseType.GetMembers(context, filter)) { - if (!m.IsStatic) - yield return m; - } - } + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetEvents(this, context, FilterNonStatic(filter), options); } - // Problem with type parameter resolving - circular declarations - // void Example (S s, T t) where S : T where T : S - IEnumerable GetNonCircularBaseTypes(ITypeResolveContext context) + public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - var result = this.GetBaseTypes(context).Where(bt => !IsCircular (context, bt)); - if (result.Any ()) - return result; - - // result may be empty, GetBaseTypes doesn't return object/struct when there are only constraints (even circular) as base types are available, - // but even when there are only circular references the default base type should be included. - IType defaultBaseType = context.GetTypeDefinition("System", HasValueTypeConstraint ? "ValueType" : "Object", 0, StringComparer.Ordinal); - if (defaultBaseType != null) - return new [] { defaultBaseType }; - return Enumerable.Empty (); - } - - bool IsCircular(ITypeResolveContext context, IType baseType) + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) + return EmptyList.Instance; + else + return GetMembersHelper.GetMembers(this, context, FilterNonStatic(filter), options); + } + + static Predicate FilterNonStatic(Predicate filter) where T : class, IMember { - var parameter = baseType as DefaultTypeParameter; - if (parameter == null) - return false; - var stack = new Stack(); - while (true) { - if (parameter == this) - return true; - foreach (DefaultTypeParameter parameterBaseType in parameter.GetNonCircularBaseTypes(context).Where(t => t is DefaultTypeParameter)) { - stack.Push(parameterBaseType); - } - if (stack.Count == 0) - return false; - parameter = stack.Pop(); - } + if (filter == null) + return member => !member.IsStatic; + else + return member => !member.IsStatic && filter(member); + } + + IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + return EmptyList.Instance; } - IEnumerable IType.GetNestedTypes(ITypeResolveContext context, Predicate filter) + IEnumerable IType.GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } @@ -343,8 +339,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation foreach (ITypeReference constraint in this.Constraints) { IType c = constraint.Resolve(context); yield return c; - ITypeDefinition cdef = c.GetDefinition(); - if (!(cdef != null && cdef.ClassType == ClassType.Interface)) + if (c.Kind != TypeKind.Interface) hasNonInterfaceConstraint = true; } // Do not add the 'System.Object' constraint if there is another constraint with a base class. @@ -357,8 +352,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() @@ -382,6 +382,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return o != null && this.attributes == o.attributes && this.constraints == o.constraints + && this.name == o.name && this.flags == o.flags && this.ownerType == o.ownerType && this.index == o.index diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs index 976b90ca5..72510f8d2 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetClassTypeReference.cs @@ -1,8 +1,22 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -10,11 +24,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) { @@ -42,6 +57,10 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.typeParameterCount = typeParameterCount; } + public string Namespace { get { return nameSpace; } } + public string Name { get { return name; } } + public int TypeParameterCount { get { return typeParameterCount; } } + /* sealed class CachedResult { @@ -61,37 +80,34 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation if (context == null) throw new ArgumentNullException("context"); - /* TODO PERF: caching disabled until we measure how much of an advantage it is - * (and whether other approaches like caching only the last N resolve calls in a thread-static cache would work better) - * Maybe even make a distinction between the really common type references (e.g. primitiveTypeReferences) and - * normal GetClassTypeReferences? - CacheManager cacheManager = context.CacheManager; - if (cacheManager != null) { - CachedResult result = this.v_cachedResult; - if (result != null && result.CacheManager == cacheManager) - return result.Result; - IType newResult = DoResolve(context); - this.v_cachedResult = new CachedResult(cacheManager, newResult); - cacheManager.Disposed += delegate { v_cachedResult = null; }; // maybe optimize this to use interface call instead of delegate? - return newResult; - } else { - return DoResolve(context); - } +// CacheManager cache = context.CacheManager; +// if (cache != null) { +// IType cachedType = cache.GetShared(this) as IType; +// if (cachedType != null) +// return cachedType; +// } - } - - IType DoResolve(ITypeResolveContext context) - { - */ - return context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType; + IType type = context.GetTypeDefinition(nameSpace, name, typeParameterCount, StringComparer.Ordinal) ?? SharedTypes.UnknownType; +// if (cache != null) +// cache.SetShared(this, type); + return type; } public override string ToString() { if (typeParameterCount == 0) - return NamespaceDeclaration.BuildQualifiedName(nameSpace, name); + return BuildQualifiedName(nameSpace, name); else - return NamespaceDeclaration.BuildQualifiedName(nameSpace, name) + "`" + typeParameterCount; + return BuildQualifiedName(nameSpace, name) + "`" + typeParameterCount; + } + + static string BuildQualifiedName (string name1, string name2) + { + if (string.IsNullOrEmpty (name1)) + return name2; + if (string.IsNullOrEmpty (name2)) + return name1; + return name1 + "." + name2; } void ISupportsInterning.PrepareForInterning(IInterningProvider provider) diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs new file mode 100644 index 000000000..a0aef1f95 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/GetMembersHelper.cs @@ -0,0 +1,281 @@ +// 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.Collections.Generic; +using System.Linq; +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Provides helper methods for implementing GetMembers() on IType-implementations. + /// Note: GetMembersHelper will recursively call back into IType.GetMembers(), but only with + /// both GetMemberOptions.IgnoreInheritedMembers and GetMemberOptions.ReturnMemberDefinitions set, + /// and only the 'simple' overloads (not taking type arguments). + /// + /// Ensure that your IType implementation does not use the GetMembersHelper if both flags are set, + /// otherwise you'll get a StackOverflowException! + /// + static class GetMembersHelper + { + #region GetNestedTypes + public static IEnumerable GetNestedTypes(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + return GetNestedTypes(type, null, context, filter, options); + } + + public static IEnumerable GetNestedTypes(IType type, IList nestedTypeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetNestedTypesImpl(type, nestedTypeArguments, context, filter, options); + } else { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetNestedTypesImpl(t, nestedTypeArguments, context, filter, options)); + } + } + + static IEnumerable GetNestedTypesImpl(IType outerType, IList nestedTypeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + ITypeDefinition outerTypeDef = outerType.GetDefinition(); + if (outerTypeDef == null) + yield break; + + int outerTypeParameterCount = outerTypeDef.TypeParameterCount; + ParameterizedType pt = outerType as ParameterizedType; + foreach (ITypeDefinition nestedType in outerTypeDef.NestedTypes) { + int totalTypeParameterCount = nestedType.TypeParameterCount; + if (nestedTypeArguments != null) { + if (totalTypeParameterCount - outerTypeParameterCount != nestedTypeArguments.Count) + continue; + } + if (!(filter == null || filter(nestedType))) + continue; + + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + yield return nestedType; + } else if (totalTypeParameterCount == 0 || (pt == null && totalTypeParameterCount == outerTypeParameterCount)) { + // The nested type has no new type parameters, and there are no type arguments + // to copy from the outer type + // -> we can directly return the nested type definition + yield return nestedType; + } else { + // We need to parameterize the nested type + IType[] newTypeArguments = new IType[totalTypeParameterCount]; + for (int i = 0; i < outerTypeParameterCount; i++) { + newTypeArguments[i] = pt != null ? pt.GetTypeArgument(i) : outerTypeDef.TypeParameters[i]; + } + for (int i = outerTypeParameterCount; i < totalTypeParameterCount; i++) { + if (nestedTypeArguments != null) + newTypeArguments[i] = nestedTypeArguments[i - outerTypeParameterCount]; + else + newTypeArguments[i] = SharedTypes.UnboundTypeArgument; + } + yield return new ParameterizedType(nestedType, newTypeArguments); + } + } + } + #endregion + + #region GetMethods + public static IEnumerable GetMethods(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + return GetMethods(type, null, context, filter, options); + } + + public static IEnumerable GetMethods(IType type, IList typeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + if (typeArguments != null && typeArguments.Count > 0) { + filter = FilterTypeParameterCount(typeArguments.Count).And(filter); + } + + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetMethodsImpl(type, typeArguments, context, filter, options); + } else { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMethodsImpl(t, typeArguments, context, filter, options)); + } + } + + static Predicate FilterTypeParameterCount(int expectedTypeParameterCount) + { + return m => m.TypeParameters.Count == expectedTypeParameterCount; + } + + const GetMemberOptions declaredMembers = GetMemberOptions.IgnoreInheritedMembers | GetMemberOptions.ReturnMemberDefinitions; + + static IEnumerable GetMethodsImpl(IType baseType, IList methodTypeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + IEnumerable declaredMethods = baseType.GetMethods(context, filter, options | declaredMembers); + + ParameterizedType pt = baseType as ParameterizedType; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == 0 + && (pt != null || (methodTypeArguments != null && methodTypeArguments.Count > 0))) + { + TypeParameterSubstitution substitution = null; + foreach (IMethod m in declaredMethods) { + if (methodTypeArguments != null && methodTypeArguments.Count > 0) { + if (m.TypeParameters.Count != methodTypeArguments.Count) + continue; + } + if (substitution == null) { + if (pt != null) + substitution = pt.GetSubstitution(methodTypeArguments); + else + substitution = new TypeParameterSubstitution(null, methodTypeArguments); + } + yield return new SpecializedMethod(baseType, m, methodTypeArguments, substitution, context); + } + } else { + foreach (IMethod m in declaredMethods) { + yield return m; + } + } + } + #endregion + + #region GetConstructors + public static IEnumerable GetConstructors(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetConstructorsImpl(type, context, filter, options); + } else { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetConstructorsImpl(t, context, filter, options)); + } + } + + static IEnumerable GetConstructorsImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + IEnumerable declaredCtors = baseType.GetConstructors(context, filter, options | declaredMembers); + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + return declaredCtors; + } + + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + var substitution = pt.GetSubstitution(); + return declaredCtors.Select(m => new SpecializedMethod(pt, m, null, substitution, context)); + } else { + return declaredCtors; + } + } + #endregion + + #region GetProperties + public static IEnumerable GetProperties(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetPropertiesImpl(type, context, filter, options); + } else { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetPropertiesImpl(t, context, filter, options)); + } + } + + static IEnumerable GetPropertiesImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + IEnumerable declaredProperties = baseType.GetProperties(context, filter, options | declaredMembers); + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + return declaredProperties; + } + + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + var substitution = pt.GetSubstitution(); + return declaredProperties.Select(m => new SpecializedProperty(pt, m, substitution, context)); + } else { + return declaredProperties; + } + } + #endregion + + #region GetFields + public static IEnumerable GetFields(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetFieldsImpl(type, context, filter, options); + } else { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetFieldsImpl(t, context, filter, options)); + } + } + + static IEnumerable GetFieldsImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + IEnumerable declaredFields = baseType.GetFields(context, filter, options | declaredMembers); + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + return declaredFields; + } + + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + var substitution = pt.GetSubstitution(); + return declaredFields.Select(m => new SpecializedField(pt, m, substitution, context)); + } else { + return declaredFields; + } + } + #endregion + + #region GetEvents + public static IEnumerable GetEvents(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetEventsImpl(type, context, filter, options); + } else { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetEventsImpl(t, context, filter, options)); + } + } + + static IEnumerable GetEventsImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + IEnumerable declaredEvents = baseType.GetEvents(context, filter, options | declaredMembers); + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) { + return declaredEvents; + } + + ParameterizedType pt = baseType as ParameterizedType; + if (pt != null) { + var substitution = pt.GetSubstitution(); + return declaredEvents.Select(m => new SpecializedEvent(pt, m, substitution, context)); + } else { + return declaredEvents; + } + } + #endregion + + #region GetMembers + public static IEnumerable GetMembers(IType type, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + if ((options & GetMemberOptions.IgnoreInheritedMembers) == GetMemberOptions.IgnoreInheritedMembers) { + return GetMembersImpl(type, context, filter, options); + } else { + return type.GetNonInterfaceBaseTypes(context).SelectMany(t => GetMembersImpl(t, context, filter, options)); + } + } + + static IEnumerable GetMembersImpl(IType baseType, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + foreach (var m in GetMethodsImpl(baseType, null, context, filter, options)) + yield return m; + foreach (var m in GetPropertiesImpl(baseType, context, filter, options)) + yield return m; + foreach (var m in GetFieldsImpl(baseType, context, filter, options)) + yield return m; + foreach (var m in GetEventsImpl(baseType, context, filter, options)) + yield return m; + } + #endregion + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs deleted file mode 100644 index 1a5d048f0..000000000 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/MethodTypeParameterSubstitution.cs +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; - -namespace ICSharpCode.NRefactory.TypeSystem.Implementation -{ - /// - /// Substitutes method type parameters with type arguments. Does not modify class type parameters. - /// - public class MethodTypeParameterSubstitution : TypeVisitor - { - readonly IList typeArguments; - - public MethodTypeParameterSubstitution(IList typeArguments) - { - this.typeArguments = typeArguments; - } - - public override IType VisitTypeParameter(ITypeParameter type) - { - int index = type.Index; - if (type.OwnerType == EntityType.Method) { - if (index >= 0 && index < typeArguments.Count) - return typeArguments[index]; - else - return SharedTypes.UnknownType; - } else { - return base.VisitTypeParameter(type); - } - } - } -} diff --git a/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs similarity index 51% rename from ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs rename to ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs index 64fc13493..e87fcf87e 100644 --- a/ICSharpCode.NRefactory/CSharp/Analysis/MinimalResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/MinimalResolveContext.cs @@ -1,20 +1,32 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; -using ICSharpCode.NRefactory.TypeSystem; -using ICSharpCode.NRefactory.TypeSystem.Implementation; - -namespace ICSharpCode.NRefactory.CSharp.Analysis +namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// /// Resolve context represents the minimal mscorlib required for evaluating constants. /// - sealed class MinimalResolveContext : AbstractAnnotatable, IProjectContent, ISynchronizedTypeResolveContext + public sealed class MinimalResolveContext : AbstractAnnotatable, IProjectContent, ISynchronizedTypeResolveContext { static readonly Lazy instance = new Lazy(() => new MinimalResolveContext()); @@ -23,16 +35,27 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis } readonly ReadOnlyCollection namespaces = Array.AsReadOnly(new string[] { "System" }); - readonly IAttribute[] assemblyAttributes = new IAttribute[0]; readonly ITypeDefinition systemObject, systemValueType; readonly ReadOnlyCollection types; private MinimalResolveContext() { List types = new List(); - types.Add(systemObject = new DefaultTypeDefinition(this, "System", "Object")); - types.Add(systemValueType = new DefaultTypeDefinition(this, "System", "ValueType") { BaseTypes = { systemObject } }); + + systemObject = new DefaultTypeDefinition(this, "System", "Object") { + Accessibility = Accessibility.Public + }; + systemValueType = new DefaultTypeDefinition(this, "System", "ValueType") { + Accessibility = Accessibility.Public, + BaseTypes = { systemObject } + }; + // TypeCode.Empty = void + types.Add(new VoidTypeDefinition(this)); + // types are added in the order they are defined in the TypeCode enum + types.Add(systemObject); + types.Add(CreateClass("System", "DBNull")); types.Add(CreateStruct("System", "Boolean")); + types.Add(CreateStruct("System", "Char")); types.Add(CreateStruct("System", "SByte")); types.Add(CreateStruct("System", "Byte")); types.Add(CreateStruct("System", "Int16")); @@ -44,16 +67,28 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis types.Add(CreateStruct("System", "Single")); types.Add(CreateStruct("System", "Double")); types.Add(CreateStruct("System", "Decimal")); - types.Add(new DefaultTypeDefinition(this, "System", "String") { BaseTypes = { systemObject } }); + types.Add(CreateStruct("System", "DateTime")); + types.Add(systemValueType); // misuse unused enum value (TypeCode)17 for System.ValueType + types.Add(CreateClass("System", "String")); foreach (ITypeDefinition type in types) type.Freeze(); this.types = types.AsReadOnly(); } + ITypeDefinition CreateClass(string nameSpace, string name) + { + return new DefaultTypeDefinition(this, nameSpace, name) { + Kind = TypeKind.Class, + Accessibility = Accessibility.Public, + BaseTypes = { systemObject } + }; + } + ITypeDefinition CreateStruct(string nameSpace, string name) { return new DefaultTypeDefinition(this, nameSpace, name) { - ClassType = ClassType.Struct, + Kind = TypeKind.Struct, + Accessibility = Accessibility.Public, BaseTypes = { systemValueType } }; } @@ -67,6 +102,11 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis return null; } + public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) + { + return types[(int)typeCode]; + } + public IEnumerable GetTypes() { return types; @@ -91,8 +131,12 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis return null; } - public IList AssemblyAttributes { - get { return assemblyAttributes; } + IList IProjectContent.AssemblyAttributes { + get { return EmptyList.Instance; } + } + + IList IProjectContent.ModuleAttributes { + get { return EmptyList.Instance; } } ICSharpCode.NRefactory.Utils.CacheManager ITypeResolveContext.CacheManager { @@ -123,5 +167,14 @@ namespace ICSharpCode.NRefactory.CSharp.Analysis return EmptyList.Instance; } } + + void IProjectContent.UpdateProjectContent(IParsedFile oldFile, IParsedFile newFile) + { + throw new NotSupportedException(); + } + + public string AssemblyName { + get { return "MinimalResolveContext"; } + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs index 856b7aa63..04e9385a2 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/NestedTypeReference.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -8,6 +23,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Type reference used to reference nested types. /// + [Serializable] public sealed class NestedTypeReference : ITypeReference, ISupportsInterning { ITypeReference declaringTypeRef; @@ -35,6 +51,18 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.additionalTypeParameterCount = additionalTypeParameterCount; } + public ITypeReference DeclaringTypeReference { + get { return declaringTypeRef; } + } + + public string Name { + get { return name; } + } + + public int AdditionalTypeParameterCount { + get { return additionalTypeParameterCount; } + } + public IType Resolve(ITypeResolveContext context) { ITypeDefinition declaringType = declaringTypeRef.Resolve(context) as ITypeDefinition; diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs index 4876c1e5c..ee0b06ed6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/ProxyTypeResolveContext.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -10,7 +25,8 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Proxy that forwards calls to another TypeResolveContext. /// Useful as base class for decorators. /// - public class ProxyTypeResolveContext : AbstractAnnotatable, ITypeResolveContext + [Serializable] + public class ProxyTypeResolveContext : ITypeResolveContext { protected readonly ITypeResolveContext target; @@ -66,5 +82,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation // it might not be cache-safe. get { return null; } } + + /// + public virtual ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) + { + return target.GetKnownTypeDefinition(typeCode); + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs index d61fd4d52..05c37c21a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleConstantValue.cs @@ -1,13 +1,30 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.Semantics; 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; @@ -21,17 +38,13 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.value = value; } - public IType GetValueType(ITypeResolveContext context) + public ResolveResult Resolve(ITypeResolveContext context) { - return type.Resolve(context); - } - - public object GetValue(ITypeResolveContext context) - { - if (value is ITypeReference) - return ((ITypeReference)value).Resolve(context); - else - return value; + if (value is ITypeReference) { + return new TypeOfResolveResult(type.Resolve(context), ((ITypeReference)value).Resolve(context)); + } else { + return new ConstantResolveResult(type.Resolve(context), value); + } } public override string ToString() diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs index 7ed18be85..0aca7d06d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleInterningProvider.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; @@ -24,21 +39,6 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation Intern(r); } - sealed class ReferenceComparer : IEqualityComparer - { - public readonly static ReferenceComparer Instance = new ReferenceComparer(); - - public new bool Equals(object a, object b) - { - return ReferenceEquals(a, b); - } - - public int GetHashCode(object obj) - { - return RuntimeHelpers.GetHashCode(obj); - } - } - sealed class InterningComparer : IEqualityComparer { public bool Equals(ISupportsInterning x, ISupportsInterning y) @@ -89,6 +89,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) @@ -105,13 +107,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation else supportsInternDict.Add(s, s); } - } else if (obj is IType || Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) { + } else if (Type.GetTypeCode(obj.GetType()) >= TypeCode.Boolean) { + // IType cannot be interned by value because ITypeParameters with different names are considered + // equal (for object.Equals), but should not be interned. object output; if (byValueDict.TryGetValue(obj, out output)) obj = (T)output; else byValueDict.Add(obj, obj); } + stackDepth--; return obj; } @@ -123,8 +128,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/SimpleProjectContent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs index 6cb78cbfa..0189d3cca 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SimpleProjectContent.cs @@ -1,12 +1,27 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.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 @@ -19,44 +34,72 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// Compared with , this class adds support for the IProjectContent interface, /// for partial classes, and for multi-threading. /// - public sealed class SimpleProjectContent : AbstractAnnotatable, IProjectContent + [Serializable] + public class SimpleProjectContent : AbstractAnnotatable, IProjectContent, ISerializable, IDeserializationCallback { - // This class is sealed by design: - // the synchronization story doesn't mix well with someone trying to extend this class. - // If you wanted to derive from this: use delegation, not inheritance. - readonly TypeStorage types = new TypeStorage(); - readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(); + readonly ReaderWriterLockSlim readerWriterLock = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion); readonly Dictionary fileDict = new Dictionary(Platform.FileNameComparer); + #region Constructor + /// + /// Creates a new SimpleProjectContent instance. + /// + public SimpleProjectContent() + { + } + #endregion + + public virtual string AssemblyName { + get { return string.Empty; } + } + #region AssemblyAttributes readonly List assemblyAttributes = new List(); // mutable assembly attribute storage + readonly List moduleAttributes = new List(); volatile IAttribute[] readOnlyAssemblyAttributes = {}; // volatile field with copy for reading threads + volatile IAttribute[] readOnlyModuleAttributes = {}; /// public IList AssemblyAttributes { get { return readOnlyAssemblyAttributes; } } - void AddRemoveAssemblyAttributes(ICollection removedAttributes, ICollection addedAttributes) + /// + public IList ModuleAttributes { + get { return readOnlyModuleAttributes; } + } + + static bool AddRemoveAttributes(ICollection removedAttributes, ICollection addedAttributes, + List attributeStorage) { // API uses ICollection instead of IEnumerable to discourage users from evaluating // the list inside the lock (this method is called inside the write lock) // [[not an issue anymore; the user now passes IParsedFile]] bool hasChanges = false; if (removedAttributes != null && removedAttributes.Count > 0) { - if (assemblyAttributes.RemoveAll(removedAttributes.Contains) > 0) + if (attributeStorage.RemoveAll(removedAttributes.Contains) > 0) hasChanges = true; } if (addedAttributes != null) { - assemblyAttributes.AddRange(addedAttributes); + attributeStorage.AddRange(addedAttributes); hasChanges = true; } - - if (hasChanges) + return hasChanges; + } + + void AddRemoveAssemblyAttributes(ICollection removedAttributes, ICollection addedAttributes) + { + if (AddRemoveAttributes(removedAttributes, addedAttributes, assemblyAttributes)) readOnlyAssemblyAttributes = assemblyAttributes.ToArray(); } + + void AddRemoveModuleAttributes(ICollection removedAttributes, ICollection addedAttributes) + { + if (AddRemoveAttributes(removedAttributes, addedAttributes, moduleAttributes)) + readOnlyModuleAttributes = moduleAttributes.ToArray(); + } #endregion #region AddType @@ -64,19 +107,40 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation { if (typeDefinition == null) throw new ArgumentNullException("typeDefinition"); - typeDefinition.Freeze(); // Type definition must be frozen before it can be added to a project content if (typeDefinition.ProjectContent != this) throw new ArgumentException("Cannot add a type definition that belongs to another project content"); - // TODO: handle partial classes - types.UpdateType(typeDefinition); + ITypeDefinition existingTypeDef = types.GetTypeDefinition(typeDefinition.Namespace, typeDefinition.Name, typeDefinition.TypeParameterCount, StringComparer.Ordinal); + if (existingTypeDef != null) { + // Add a part to a compound class + var newParts = new List(existingTypeDef.GetParts()); + newParts.Add(typeDefinition); + types.UpdateType(CompoundTypeDefinition.Create(newParts)); + } else { + types.UpdateType(typeDefinition); + } } #endregion #region RemoveType void RemoveType(ITypeDefinition typeDefinition) { - types.RemoveType (typeDefinition); // <- Daniel: Correct ? + var compoundTypeDef = typeDefinition.GetDefinition() as CompoundTypeDefinition; + if (compoundTypeDef != null) { + // Remove one part from a compound class + var newParts = new List(compoundTypeDef.GetParts()); + // We cannot use newParts.Remove() because we need to use reference equality + for (int i = 0; i < newParts.Count; i++) { + if (newParts[i] == typeDefinition) { + newParts.RemoveAt(i); + ((DefaultTypeDefinition)typeDefinition).SetCompoundTypeDefinition(typeDefinition); + break; + } + } + types.UpdateType(CompoundTypeDefinition.Create(newParts)); + } else { + types.RemoveType(typeDefinition); + } } #endregion @@ -110,7 +174,11 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } fileDict[newFile.FileName] = newFile; } - AddRemoveAssemblyAttributes(oldFile != null ? oldFile.AssemblyAttributes : null, newFile != null ? newFile.AssemblyAttributes : null); + AddRemoveAssemblyAttributes(oldFile != null ? oldFile.AssemblyAttributes : null, + newFile != null ? newFile.AssemblyAttributes : null); + + AddRemoveModuleAttributes(oldFile != null ? oldFile.ModuleAttributes : null, + newFile != null ? newFile.ModuleAttributes : null); } finally { readerWriterLock.ExitWriteLock(); } @@ -118,6 +186,16 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation #endregion #region IProjectContent implementation + public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) + { + readerWriterLock.EnterReadLock(); + try { + return types.GetKnownTypeDefinition(typeCode); + } finally { + readerWriterLock.ExitReadLock(); + } + } + public ITypeDefinition GetTypeDefinition(string nameSpace, string name, int typeParameterCount, StringComparer nameComparer) { readerWriterLock.EnterReadLock(); @@ -235,5 +313,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/SpecializedEvent.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs index b344d9491..09a15d95f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedEvent.cs @@ -1,56 +1,66 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Represents a specialized IEvent (e.g. after type substitution). + /// Represents a specialized IEvent (event after type substitution). /// - public class SpecializedEvent : DefaultEvent + public class SpecializedEvent : SpecializedMember, IEvent { - readonly IMember memberDefinition; - IType declaringType; + readonly IEvent eventDefinition; - public SpecializedEvent(IEvent e) : base(e) + public SpecializedEvent(IType declaringType, IEvent eventDefinition) + : base(declaringType, eventDefinition) { - this.memberDefinition = e.MemberDefinition; - this.declaringType = e.DeclaringType; + this.eventDefinition = eventDefinition; } - public override IType DeclaringType { - get { return declaringType; } + internal SpecializedEvent(IType declaringType, IEvent eventDefinition, TypeVisitor substitution, ITypeResolveContext context) + : base(declaringType, eventDefinition, substitution, context) + { + this.eventDefinition = eventDefinition; } - public void SetDeclaringType(IType declaringType) - { - CheckBeforeMutation(); - this.declaringType = declaringType; + public bool CanAdd { + get { return eventDefinition.CanAdd; } } - public override IMember MemberDefinition { - get { return memberDefinition; } + public bool CanRemove { + get { return eventDefinition.CanRemove; } } - public override int GetHashCode() - { - int hashCode = 0; - unchecked { - if (memberDefinition != null) - hashCode += 1000000007 * memberDefinition.GetHashCode(); - if (declaringType != null) - hashCode += 1000000009 * declaringType.GetHashCode(); - } - return hashCode; + public bool CanInvoke { + get { return eventDefinition.CanInvoke; } } - public override bool Equals(object obj) - { - SpecializedEvent other = obj as SpecializedEvent; - if (other == null) - return false; - return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + public IAccessor AddAccessor { + get { return eventDefinition.AddAccessor; } + } + + public IAccessor RemoveAccessor { + get { return eventDefinition.RemoveAccessor; } + } + + public IAccessor InvokeAccessor { + get { return eventDefinition.InvokeAccessor; } } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs index d8fc104b1..fc5a0e39a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedField.cs @@ -1,56 +1,62 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Represents a specialized IField (e.g. after type substitution). + /// Represents a specialized IField (field after type substitution). /// - public class SpecializedField : DefaultField + public class SpecializedField : SpecializedMember, IField { - readonly IMember memberDefinition; - IType declaringType; + readonly IField fieldDefinition; - public SpecializedField(IField f) : base(f) + public SpecializedField(IType declaringType, IField fieldDefinition) + : base(declaringType, fieldDefinition) { - this.memberDefinition = f.MemberDefinition; - this.declaringType = f.DeclaringType; + this.fieldDefinition = fieldDefinition; } - public override IType DeclaringType { - get { return declaringType; } + internal SpecializedField(IType declaringType, IField fieldDefinition, TypeVisitor substitution, ITypeResolveContext context) + : base(declaringType, fieldDefinition, substitution, context) + { + this.fieldDefinition = fieldDefinition; } - public void SetDeclaringType(IType declaringType) - { - CheckBeforeMutation(); - this.declaringType = declaringType; + public bool IsReadOnly { + get { return fieldDefinition.IsReadOnly; } } - public override IMember MemberDefinition { - get { return memberDefinition; } + public bool IsVolatile { + get { return fieldDefinition.IsVolatile; } } - public override int GetHashCode() - { - int hashCode = 0; - unchecked { - if (memberDefinition != null) - hashCode += 1000000007 * memberDefinition.GetHashCode(); - if (declaringType != null) - hashCode += 1000000009 * declaringType.GetHashCode(); - } - return hashCode; + ITypeReference IVariable.Type { + get { return this.ReturnType; } } - public override bool Equals(object obj) - { - SpecializedField other = obj as SpecializedField; - if (other == null) - return false; - return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + public bool IsConst { + get { return fieldDefinition.IsConst; } + } + + public IConstantValue ConstantValue { + get { return fieldDefinition.ConstantValue; } } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs new file mode 100644 index 000000000..fb5baff18 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMember.cs @@ -0,0 +1,286 @@ +// 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.Collections.Generic; +using System.Text; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Represents a SpecializedMember (a member on which type substitution has been performed). + /// + public abstract class SpecializedMember : IMember + { + readonly IType declaringType; + readonly IMember memberDefinition; + readonly ITypeReference returnType; + + protected SpecializedMember(IType declaringType, IMember memberDefinition) + : this(declaringType, memberDefinition, GetSubstitution(declaringType), null) + { + } + + internal SpecializedMember(IType declaringType, IMember memberDefinition, TypeVisitor substitution, ITypeResolveContext context) + { + if (declaringType == null) + throw new ArgumentNullException("declaringType"); + if (memberDefinition == null) + throw new ArgumentNullException("memberDefinition"); + + this.declaringType = declaringType; + this.memberDefinition = memberDefinition; + this.returnType = Substitute(memberDefinition.ReturnType, substitution, context); + } + + internal static TypeVisitor GetSubstitution(IType declaringType) + { + ParameterizedType pt = declaringType as ParameterizedType; + if (pt != null) + return pt.GetSubstitution(); + else + return null; + } + + internal static ITypeReference Substitute(ITypeReference type, TypeVisitor substitution, ITypeResolveContext context) + { + if (substitution == null) + return type; + if (context != null) + return type.Resolve(context).AcceptVisitor(substitution); + else + return SubstitutionTypeReference.Create(type, substitution); + } + + public IType DeclaringType { + get { return declaringType; } + } + + public IMember MemberDefinition { + get { return memberDefinition; } + } + + public ITypeReference ReturnType { + get { return returnType; } + } + + public IList InterfaceImplementations { + get { return memberDefinition.InterfaceImplementations; } + } + + public bool IsVirtual { + get { return memberDefinition.IsVirtual; } + } + + public bool IsOverride { + get { return memberDefinition.IsOverride; } + } + + public bool IsOverridable { + get { return memberDefinition.IsOverridable; } + } + + public EntityType EntityType { + get { return memberDefinition.EntityType; } + } + + public DomRegion Region { + get { return memberDefinition.Region; } + } + + public DomRegion BodyRegion { + get { return memberDefinition.BodyRegion; } + } + + public ITypeDefinition DeclaringTypeDefinition { + get { return memberDefinition.DeclaringTypeDefinition; } + } + + public IList Attributes { + get { return memberDefinition.Attributes; } + } + + public string Documentation { + get { return memberDefinition.Documentation; } + } + + public Accessibility Accessibility { + get { return memberDefinition.Accessibility; } + } + + public bool IsStatic { + get { return memberDefinition.IsStatic; } + } + + public bool IsAbstract { + get { return memberDefinition.IsAbstract; } + } + + public bool IsSealed { + get { return memberDefinition.IsSealed; } + } + + public bool IsShadowing { + get { return memberDefinition.IsShadowing; } + } + + public bool IsSynthetic { + get { return memberDefinition.IsSynthetic; } + } + + public bool IsPrivate { + get { return memberDefinition.IsPrivate; } + } + + public bool IsPublic { + get { return memberDefinition.IsPublic; } + } + + public bool IsProtected { + get { return memberDefinition.IsProtected; } + } + + public bool IsInternal { + get { return memberDefinition.IsInternal; } + } + + public bool IsProtectedOrInternal { + get { return memberDefinition.IsProtectedOrInternal; } + } + + public bool IsProtectedAndInternal { + get { return memberDefinition.IsProtectedAndInternal; } + } + + public IProjectContent ProjectContent { + get { return memberDefinition.ProjectContent; } + } + + public IParsedFile ParsedFile { + get { return memberDefinition.ParsedFile; } + } + + public string FullName { + get { return memberDefinition.FullName; } + } + + public string Name { + get { return memberDefinition.Name; } + } + + public string Namespace { + get { return memberDefinition.Namespace; } + } + + public string ReflectionName { + get { return memberDefinition.ReflectionName; } + } + + public bool IsFrozen { + get { return memberDefinition.IsFrozen; } + } + + void IFreezable.Freeze() + { + if (!memberDefinition.IsFrozen) + throw new NotSupportedException(); + } + + public override bool Equals(object obj) + { + SpecializedMember other = obj as SpecializedMember; + if (other == null) + return false; + return this.declaringType.Equals(other.declaringType) && this.memberDefinition.Equals(other.memberDefinition); + } + + public override int GetHashCode() + { + unchecked { + return 1000000007 * declaringType.GetHashCode() + 1000000009 * memberDefinition.GetHashCode(); + } + } + + public override string ToString() + { + StringBuilder b = new StringBuilder("["); + b.Append(GetType().Name); + b.Append(' '); + b.Append(declaringType.ToString()); + b.Append('.'); + b.Append(this.Name); + b.Append(':'); + b.Append(returnType.ToString()); + b.Append(']'); + return b.ToString(); + } + } + + public abstract class SpecializedParameterizedMember : SpecializedMember, IParameterizedMember + { + readonly IList parameters; + + protected SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition) + : this(declaringType, memberDefinition, GetSubstitution(declaringType), null) + { + } + + internal SpecializedParameterizedMember(IType declaringType, IParameterizedMember memberDefinition, TypeVisitor substitution, ITypeResolveContext context) + : base(declaringType, memberDefinition, substitution, context) + { + var paramDefs = memberDefinition.Parameters; + if (paramDefs.Count == 0) { + this.parameters = EmptyList.Instance; + } else { + var parameters = new IParameter[paramDefs.Count]; + for (int i = 0; i < parameters.Length; i++) { + ITypeReference newType = Substitute(paramDefs[i].Type, substitution, context); + if (newType != paramDefs[i].Type) { + parameters[i] = new DefaultParameter(paramDefs[i]) { Type = newType }; + } else { + parameters[i] = paramDefs[i]; + } + } + this.parameters = Array.AsReadOnly(parameters); + } + } + + public IList Parameters { + get { return parameters; } + } + + public override string ToString() + { + StringBuilder b = new StringBuilder("["); + b.Append(GetType().Name); + b.Append(' '); + b.Append(this.DeclaringType.ToString()); + b.Append('.'); + b.Append(this.Name); + b.Append('('); + for (int i = 0; i < parameters.Count; i++) { + if (i > 0) b.Append(", "); + b.Append(parameters[i].ToString()); + } + b.Append("):"); + b.Append(this.ReturnType.ToString()); + b.Append(']'); + return b.ToString(); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs index 9d76f93e2..60dded0d9 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedMethod.cs @@ -1,46 +1,79 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; +using System.Text; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// /// Represents a specialized IMethod (e.g. after type substitution). /// - public class SpecializedMethod : DefaultMethod + public class SpecializedMethod : SpecializedParameterizedMember, IMethod { - readonly IMember memberDefinition; - IType declaringType; + readonly IMethod methodDefinition; + readonly IList typeArguments; - public SpecializedMethod(IMethod m) : base(m) + public SpecializedMethod(IType declaringType, IMethod methodDefinition, IList typeArguments = null) + : this(declaringType, methodDefinition, typeArguments, GetSubstitution(declaringType, typeArguments), null) { - this.memberDefinition = m.MemberDefinition; - this.declaringType = m.DeclaringType; } - public override IType DeclaringType { - get { return declaringType; } + internal SpecializedMethod(IType declaringType, IMethod methodDefinition, IList typeArguments, TypeVisitor substitution, ITypeResolveContext context) : base(declaringType, methodDefinition, substitution, context) + { + this.methodDefinition = methodDefinition; + + if (typeArguments != null) { + if (typeArguments.Count != methodDefinition.TypeParameters.Count) + throw new ArgumentException("Number of type arguments does not match number of type parameters"); + this.typeArguments = typeArguments; + } else { + this.typeArguments = EmptyList.Instance; + } } - public void SetDeclaringType(IType declaringType) + internal static TypeVisitor GetSubstitution(IType declaringType, IList typeArguments) { - CheckBeforeMutation(); - this.declaringType = declaringType; + ParameterizedType pt = declaringType as ParameterizedType; + if (pt != null) + return pt.GetSubstitution(typeArguments); + else if (typeArguments != null) + return new TypeParameterSubstitution(null, typeArguments); + else + return null; } - public override IMember MemberDefinition { - get { return memberDefinition; } + /// + /// Gets the type arguments passed to this method. + /// + public IList TypeArguments { + get { return typeArguments; } } public override int GetHashCode() { - int hashCode = 0; + int hashCode = base.GetHashCode(); unchecked { - if (memberDefinition != null) - hashCode += 1000000007 * memberDefinition.GetHashCode(); - if (declaringType != null) - hashCode += 1000000009 * declaringType.GetHashCode(); + for (int i = 0; i < typeArguments.Count; i++) { + hashCode *= 362631391; + hashCode += typeArguments[i].GetHashCode(); + } } return hashCode; } @@ -48,25 +81,66 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation public override bool Equals(object obj) { SpecializedMethod other = obj as SpecializedMethod; - if (other == null) + if (!base.Equals(other)) + return false; + if (typeArguments.Count != other.typeArguments.Count) return false; - return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + for (int i = 0; i < typeArguments.Count; i++) { + if (!typeArguments[i].Equals(other.typeArguments[i])) + return false; + } + return true; } - /// - /// Performs type substitution in parameter types and in the return type. - /// - public void SubstituteTypes(Func substitution) + public IList ReturnTypeAttributes { + get { return methodDefinition.ReturnTypeAttributes; } + } + + public IList TypeParameters { + get { return methodDefinition.TypeParameters; } + } + + public bool IsExtensionMethod { + get { return methodDefinition.IsExtensionMethod; } + } + + public bool IsConstructor { + get { return methodDefinition.IsConstructor; } + } + + public bool IsDestructor { + get { return methodDefinition.IsDestructor; } + } + + public bool IsOperator { + get { return methodDefinition.IsOperator; } + } + + public override string ToString() { - this.ReturnType = substitution(this.ReturnType); - var p = this.Parameters; - for (int i = 0; i < p.Count; i++) { - ITypeReference newType = substitution(p[i].Type); - if (newType != p[i].Type) { - p[i] = new DefaultParameter(p[i]) { Type = newType }; + StringBuilder b = new StringBuilder("["); + b.Append(GetType().Name); + b.Append(' '); + b.Append(this.DeclaringType.ToString()); + b.Append('.'); + b.Append(this.Name); + if (typeArguments != null && typeArguments.Count > 0) { + b.Append('['); + for (int i = 0; i < typeArguments.Count; i++) { + if (i > 0) b.Append(", "); + b.Append(typeArguments[i].ToString()); } + b.Append(']'); + } + b.Append('('); + for (int i = 0; i < this.Parameters.Count; i++) { + if (i > 0) b.Append(", "); + b.Append(this.Parameters[i].ToString()); } - // TODO: we might also have to perform substitution within the method's constraints + b.Append("):"); + b.Append(this.ReturnType.ToString()); + b.Append(']'); + return b.ToString(); } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs index 921ffc029..5647ec872 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SpecializedProperty.cs @@ -1,71 +1,62 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { /// - /// Represents a specialized IProperty (e.g. after type substitution). + /// Represents a specialized IProperty (property after type substitution). /// - public class SpecializedProperty : DefaultProperty + public class SpecializedProperty : SpecializedParameterizedMember, IProperty { - readonly IMember memberDefinition; - IType declaringType; + readonly IProperty propertyDefinition; - public SpecializedProperty(IProperty p) : base(p) + public SpecializedProperty(IType declaringType, IProperty propertyDefinition) + : base(declaringType, propertyDefinition) { - this.memberDefinition = p.MemberDefinition; - this.declaringType = p.DeclaringType; + this.propertyDefinition = propertyDefinition; } - public override IType DeclaringType { - get { return declaringType; } + internal SpecializedProperty(IType declaringType, IProperty propertyDefinition, TypeVisitor substitution, ITypeResolveContext context) + : base(declaringType, propertyDefinition, substitution, context) + { + this.propertyDefinition = propertyDefinition; } - public void SetDeclaringType(IType declaringType) - { - CheckBeforeMutation(); - this.declaringType = declaringType; + public bool CanGet { + get { return propertyDefinition.CanGet; } } - public override IMember MemberDefinition { - get { return memberDefinition; } + public bool CanSet { + get { return propertyDefinition.CanSet; } } - public override int GetHashCode() - { - int hashCode = 0; - unchecked { - if (memberDefinition != null) - hashCode += 1000000007 * memberDefinition.GetHashCode(); - if (declaringType != null) - hashCode += 1000000009 * declaringType.GetHashCode(); - } - return hashCode; + public IAccessor Getter { + get { return propertyDefinition.Getter; } } - public override bool Equals(object obj) - { - SpecializedProperty other = obj as SpecializedProperty; - if (other == null) - return false; - return object.Equals(this.memberDefinition, other.memberDefinition) && object.Equals(this.declaringType, other.declaringType); + public IAccessor Setter { + get { return propertyDefinition.Setter; } } - /// - /// Performs type substitution in parameter types and in the return type. - /// - public void SubstituteTypes(Func substitution) - { - this.ReturnType = substitution(this.ReturnType); - var p = this.Parameters; - for (int i = 0; i < p.Count; i++) { - ITypeReference newType = substitution(p[i].Type); - if (newType != p[i].Type) { - p[i] = new DefaultParameter(p[i]) { Type = newType }; - } - } + public bool IsIndexer { + get { return propertyDefinition.IsIndexer; } } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs index aaf38718c..26579a06a 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/SubstitutionTypeReference.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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; @@ -23,9 +38,24 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation this.substitution = substitution; } + public static ITypeReference Create(ITypeReference baseTypeReference, TypeVisitor substitution) + { + IType baseType = baseTypeReference as IType; + if (baseType != null && substitution != null) { + return baseType.AcceptVisitor(substitution); + } else { + return new SubstitutionTypeReference(baseTypeReference, substitution); + } + } + public IType Resolve(ITypeResolveContext context) { return baseTypeReference.Resolve(context).AcceptVisitor(substitution); } + + public override string ToString() + { + return "[SubstitutionTypeReference " + baseTypeReference + " " + substitution + "]"; + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs new file mode 100644 index 000000000..cacfadd85 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeParameterSubstitution.cs @@ -0,0 +1,95 @@ +// 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.Collections.Generic; +using System.Text; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// + /// Substitues class and method type parameters. + /// + public class TypeParameterSubstitution : TypeVisitor + { + readonly IList classTypeArguments; + readonly IList methodTypeArguments; + + /// + /// Creates a new type parameter substitution. + /// + /// + /// The type arguments to substitute for class type parameters. + /// Pass null to keep class type parameters unmodified. + /// + /// + /// The type arguments to substitute for method type parameters. + /// Pass null to keep method type parameters unmodified. + /// + public TypeParameterSubstitution(IList classTypeArguments, IList methodTypeArguments) + { + this.classTypeArguments = classTypeArguments; + this.methodTypeArguments = methodTypeArguments; + } + + public override IType VisitTypeParameter(ITypeParameter type) + { + int index = type.Index; + if (classTypeArguments != null && type.OwnerType == EntityType.TypeDefinition) { + if (index >= 0 && index < classTypeArguments.Count) + return classTypeArguments[index]; + else + return SharedTypes.UnknownType; + } else if (methodTypeArguments != null && type.OwnerType == EntityType.Method) { + if (index >= 0 && index < methodTypeArguments.Count) + return methodTypeArguments[index]; + else + return SharedTypes.UnknownType; + } else { + return base.VisitTypeParameter(type); + } + } + + public override string ToString() + { + StringBuilder b = new StringBuilder(); + b.Append('['); + bool first = true; + if (classTypeArguments != null) { + for (int i = 0; i < classTypeArguments.Count; i++) { + if (first) first = false; else b.Append(", "); + b.Append('`'); + b.Append(i); + b.Append(" -> "); + b.Append(classTypeArguments[i]); + } + } + if (methodTypeArguments != null) { + for (int i = 0; i < methodTypeArguments.Count; i++) { + if (first) first = false; else b.Append(", "); + b.Append("``"); + b.Append(i); + b.Append(" -> "); + b.Append(methodTypeArguments[i]); + } + } + b.Append(']'); + return b.ToString(); + } + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs index d5f284295..e8c3ee98d 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeStorage.cs @@ -1,11 +1,26 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using System.Linq; +using System.Runtime.Serialization; using System.Threading; - using ICSharpCode.NRefactory.Utils; namespace ICSharpCode.NRefactory.TypeSystem.Implementation @@ -16,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 @@ -220,6 +236,12 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation return null; } + /// + public ITypeDefinition GetKnownTypeDefinition(TypeCode typeCode) + { + return GetTypeDefinition("System", ReflectionHelper.GetShortNameByTypeCode(typeCode), 0, StringComparer.Ordinal); + } + /// public IEnumerable GetTypes() { @@ -280,7 +302,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Removes a type definition from this project content. /// - public void RemoveType(ITypeDefinition typeDefinition) + public bool RemoveType(ITypeDefinition typeDefinition) { if (typeDefinition == null) throw new ArgumentNullException("typeDefinition"); @@ -308,6 +330,7 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } } + return wasRemoved; } void RemoveNamespaceIfPossible(Dictionary dict, NamespaceEntry ns) @@ -346,5 +369,36 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation } } #endregion + + #region Serialization + /// + /// Creates a new TypeStorage instance. + /// + public TypeStorage() + { + } + + SerializationInfo serializationInfo; + + private 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); + } + serializationInfo = null; + } + #endregion } } diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs index 7f4830555..ff08e14a3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/TypeWithElementType.cs @@ -1,13 +1,29 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; namespace ICSharpCode.NRefactory.TypeSystem.Implementation { + [Serializable] public abstract class TypeWithElementType : AbstractType { - protected readonly IType elementType; + protected IType elementType; protected TypeWithElementType(IType elementType) { diff --git a/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs b/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs index e966d66c7..c8b2d8832 100644 --- a/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs +++ b/ICSharpCode.NRefactory/TypeSystem/Implementation/VoidTypeDefinition.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -9,39 +24,50 @@ namespace ICSharpCode.NRefactory.TypeSystem.Implementation /// /// Special type definition for 'void'. /// + [Serializable] public class VoidTypeDefinition : DefaultTypeDefinition { public VoidTypeDefinition(IProjectContent projectContent) : base(projectContent, "System", "Void") { - this.ClassType = ClassType.Struct; + this.Kind = TypeKind.Void; this.Accessibility = Accessibility.Public; this.IsSealed = true; } - public override IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } - public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } - public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } - public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } - public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + return EmptyList.Instance; + } + + public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { return EmptyList.Instance; } + + public override IEnumerable GetMembers(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + return EmptyList.Instance; + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs index 688dc3893..2e5bf8849 100644 --- a/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/IntersectionType.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -7,6 +22,7 @@ using System.Collections.ObjectModel; using System.Diagnostics; using System.Linq; using System.Text; + using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem @@ -14,6 +30,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Represents the intersection of several types. /// + [Serializable] public class IntersectionType : AbstractType { readonly ReadOnlyCollection types; @@ -39,6 +56,10 @@ namespace ICSharpCode.NRefactory.TypeSystem return new IntersectionType(arr); } + public override TypeKind Kind { + get { return TypeKind.Intersection; } + } + public override string Name { get { StringBuilder b = new StringBuilder(); @@ -103,33 +124,42 @@ namespace ICSharpCode.NRefactory.TypeSystem return types; } - public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + return GetMembersHelper.GetMethods(this, context, FilterNonStatic(filter), options); + } + + public override IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter, GetMemberOptions options) { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetEvents(context, filter)); + return GetMembersHelper.GetMethods(this, typeArguments, context, filter, options); } - public override IEnumerable GetMethods(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetMethods(context, filter)); + return GetMembersHelper.GetProperties(this, context, FilterNonStatic(filter), options); } - public override IEnumerable GetProperties(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetProperties(context, filter)); + return GetMembersHelper.GetFields(this, context, FilterNonStatic(filter), options); } - public override IEnumerable GetFields(ITypeResolveContext context, Predicate filter) + public override IEnumerable GetEvents(ITypeResolveContext context, Predicate filter, GetMemberOptions options) { - filter = FilterNonStatic(filter); - return types.SelectMany(t => t.GetFields(context, filter)); + return GetMembersHelper.GetEvents(this, context, FilterNonStatic(filter), options); + } + + public override IEnumerable GetMembers(ITypeResolveContext context, Predicate filter, GetMemberOptions options) + { + return GetMembersHelper.GetMembers(this, context, FilterNonStatic(filter), options); } static Predicate FilterNonStatic(Predicate filter) where T : class, IMember { - return member => !member.IsStatic && (filter == null || filter(member)); + if (filter == null) + return member => !member.IsStatic; + else + return member => !member.IsStatic && filter(member); } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs b/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs index 19daedef1..938759a00 100644 --- a/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs +++ b/ICSharpCode.NRefactory/TypeSystem/KnownTypeReference.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -10,82 +25,93 @@ namespace ICSharpCode.NRefactory.TypeSystem /// /// Contains well-known type references. /// - public static class KnownTypeReference + [Serializable] + public sealed class KnownTypeReference : ITypeReference { /// /// Gets a type reference pointing to the void type. /// - public static readonly ITypeReference Void = new GetClassTypeReference("System", "Void", 0); + public static readonly ITypeReference Void = new KnownTypeReference(TypeCode.Empty); /// /// Gets a type reference pointing to the object type. /// - public static readonly ITypeReference Object = new GetClassTypeReference("System", "Object", 0); + public static readonly ITypeReference Object = new KnownTypeReference(TypeCode.Object); /// /// Gets a type reference pointing to the bool type. /// - public static readonly ITypeReference Boolean = new GetClassTypeReference("System", "Boolean", 0); + public static readonly ITypeReference Boolean = new KnownTypeReference(TypeCode.Boolean); + + /// + /// Gets a type reference pointing to the char type. + /// + public static readonly ITypeReference Char = new KnownTypeReference(TypeCode.Char); /// /// Gets a type reference pointing to the sbyte type. /// - public static readonly ITypeReference SByte = new GetClassTypeReference("System", "SByte", 0); + public static readonly ITypeReference SByte = new KnownTypeReference(TypeCode.SByte); /// /// Gets a type reference pointing to the byte type. /// - public static readonly ITypeReference Byte = new GetClassTypeReference("System", "Byte", 0); + public static readonly ITypeReference Byte = new KnownTypeReference(TypeCode.Byte); /// /// Gets a type reference pointing to the short type. /// - public static readonly ITypeReference Int16 = new GetClassTypeReference("System", "Int16", 0); + public static readonly ITypeReference Int16 = new KnownTypeReference(TypeCode.Int16); /// /// Gets a type reference pointing to the ushort type. /// - public static readonly ITypeReference UInt16 = new GetClassTypeReference("System", "UInt16", 0); + public static readonly ITypeReference UInt16 = new KnownTypeReference(TypeCode.UInt16); /// /// Gets a type reference pointing to the int type. /// - public static readonly ITypeReference Int32 = new GetClassTypeReference("System", "Int32", 0); + public static readonly ITypeReference Int32 = new KnownTypeReference(TypeCode.Int32); /// /// Gets a type reference pointing to the uint type. /// - public static readonly ITypeReference UInt32 = new GetClassTypeReference("System", "UInt32", 0); + public static readonly ITypeReference UInt32 = new KnownTypeReference(TypeCode.UInt32); /// /// Gets a type reference pointing to the long type. /// - public static readonly ITypeReference Int64 = new GetClassTypeReference("System", "Int64", 0); + public static readonly ITypeReference Int64 = new KnownTypeReference(TypeCode.Int64); /// /// Gets a type reference pointing to the ulong type. /// - public static readonly ITypeReference UInt64 = new GetClassTypeReference("System", "UInt64", 0); + public static readonly ITypeReference UInt64 = new KnownTypeReference(TypeCode.UInt64); /// - /// Gets a type reference pointing to the string type. + /// Gets a type reference pointing to the float type. /// - public static readonly ITypeReference String = new GetClassTypeReference("System", "String", 0); + public static readonly ITypeReference Single = new KnownTypeReference(TypeCode.Single); /// - /// Gets a type reference pointing to the char type. + /// Gets a type reference pointing to the double type. /// - public static readonly ITypeReference Char = new GetClassTypeReference("System", "Char", 0); + public static readonly ITypeReference Double = new KnownTypeReference(TypeCode.Double); /// - /// Gets a type reference pointing to the float type. + /// Gets a type reference pointing to the decimal type. /// - public static readonly ITypeReference Single = new GetClassTypeReference("System", "Single", 0); + public static readonly ITypeReference Decimal = new KnownTypeReference(TypeCode.Decimal); /// - /// Gets a type reference pointing to the double type. + /// Gets a type reference pointing to the string type. + /// + public static readonly ITypeReference String = new KnownTypeReference(TypeCode.String); + + /// + /// Gets a type reference pointing to the System.Type type. /// - public static readonly ITypeReference Double = new GetClassTypeReference("System", "Double", 0); + public static readonly ITypeReference Type = new GetClassTypeReference("System", "Type", 0); /// /// Gets all known type references. @@ -95,9 +121,39 @@ namespace ICSharpCode.NRefactory.TypeSystem return new[] { Void, Object, Boolean, SByte, Byte, Int16, UInt16, Int32, UInt32, Int64, UInt64, - String, Char, Single, Double + String, Char, Single, Double, Decimal, + Type }; } } + + readonly TypeCode typeCode; + + public TypeCode TypeCode { + get { return typeCode; } + } + + public KnownTypeReference(TypeCode typeCode) + { + this.typeCode = typeCode; + } + + public IType Resolve(ITypeResolveContext context) + { + return context.GetKnownTypeDefinition(typeCode) ?? SharedTypes.UnknownType; + } + + public string Namespace { + get { return "System"; } + } + + public string Name { + get { return ReflectionHelper.GetShortNameByTypeCode(typeCode); } + } + + public override string ToString() + { + return ReflectionHelper.GetCSharpNameByTypeCode(typeCode) ?? (this.Namespace + "." + this.Name); + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/NullableType.cs b/ICSharpCode.NRefactory/TypeSystem/NullableType.cs index 11809396e..16ad7be8c 100644 --- a/ICSharpCode.NRefactory/TypeSystem/NullableType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/NullableType.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -19,7 +34,12 @@ namespace ICSharpCode.NRefactory.TypeSystem if (type == null) throw new ArgumentNullException("type"); ParameterizedType pt = type as ParameterizedType; - return pt != null && pt.TypeArguments.Count == 1 && pt.FullName == "System.Nullable"; + return pt != null && pt.TypeParameterCount == 1 && pt.FullName == "System.Nullable"; + } + + public static bool IsNonNullableValueType(IType type, ITypeResolveContext context) + { + return type.IsReferenceType(context) == false && !IsNullable(type); } /// @@ -31,8 +51,8 @@ namespace ICSharpCode.NRefactory.TypeSystem if (type == null) throw new ArgumentNullException("type"); ParameterizedType pt = type as ParameterizedType; - if (pt != null && pt.TypeArguments.Count == 1 && pt.FullName == "System.Nullable") - return pt.TypeArguments[0]; + if (pt != null && pt.TypeParameterCount == 1 && pt.FullName == "System.Nullable") + return pt.GetTypeArgument(0); else return type; } diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs index e488f6def..2a55c1e1f 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterListComparer.cs @@ -1,35 +1,54 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; namespace ICSharpCode.NRefactory.TypeSystem { - public sealed class ParameterListComparer : IEqualityComparer + public static class ParameterListComparer { - public static readonly ParameterListComparer Instance = new ParameterListComparer(); - - public bool Equals(IParameterizedMember x, IParameterizedMember y) + public static bool Compare(ITypeResolveContext context, IParameterizedMember x, IParameterizedMember y) { var px = x.Parameters; var py = y.Parameters; if (px.Count != py.Count) return false; for (int i = 0; i < px.Count; i++) { - if (!px[i].Type.Equals(py[i].Type)) + var a = px[i]; + var b = py[i]; + if (a == null && b == null) + continue; + if (a == null || b == null) + return false; + if (!a.Type.Resolve(context).Equals(b.Type.Resolve(context))) return false; } return true; } - public int GetHashCode(IParameterizedMember obj) + public static int GetHashCode(ITypeResolveContext context, IParameterizedMember obj) { int hashCode = obj.Parameters.Count; unchecked { foreach (IParameter p in obj.Parameters) { hashCode *= 27; - hashCode += p.Type.GetHashCode(); + hashCode += p.Type.Resolve(context).GetHashCode(); } } return hashCode; diff --git a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs index a75fb7c21..4aa387059 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ParameterizedType.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -21,31 +36,9 @@ namespace ICSharpCode.NRefactory.TypeSystem /// type parameters in the signatures of the members are replaced with /// the type arguments. /// - public sealed class ParameterizedType : Immutable, IType + [Serializable] + public sealed class ParameterizedType : Immutable, IType, ISupportsInterning { - sealed class Substitution : TypeVisitor - { - readonly IType[] typeArguments; - - public Substitution(IType[] typeArguments) - { - this.typeArguments = typeArguments; - } - - public override IType VisitTypeParameter(ITypeParameter type) - { - int index = type.Index; - if (type.OwnerType == EntityType.TypeDefinition) { - if (index >= 0 && index < typeArguments.Length) - return typeArguments[index]; - else - return SharedTypes.UnknownType; - } else { - return base.VisitTypeParameter(type); - } - } - } - readonly ITypeDefinition genericType; readonly IType[] typeArguments; @@ -78,6 +71,10 @@ namespace ICSharpCode.NRefactory.TypeSystem this.typeArguments = typeArguments; } + public TypeKind Kind { + get { return genericType.Kind; } + } + public bool? IsReferenceType(ITypeResolveContext context) { return genericType.IsReferenceType(context); @@ -86,7 +83,9 @@ namespace ICSharpCode.NRefactory.TypeSystem public IType DeclaringType { get { ITypeDefinition declaringTypeDef = genericType.DeclaringTypeDefinition; - if (declaringTypeDef != null && declaringTypeDef.TypeParameterCount > 0) { + if (declaringTypeDef != null && declaringTypeDef.TypeParameterCount > 0 + && declaringTypeDef.TypeParameterCount <= genericType.TypeParameterCount) + { IType[] newTypeArgs = new IType[declaringTypeDef.TypeParameterCount]; Array.Copy(this.typeArguments, 0, newTypeArgs, 0, newTypeArgs.Length); return new ParameterizedType(declaringTypeDef, newTypeArgs); @@ -96,7 +95,7 @@ namespace ICSharpCode.NRefactory.TypeSystem } public int TypeParameterCount { - get { return genericType.TypeParameterCount; } + get { return typeArguments.Length; } } public string FullName { @@ -138,9 +137,17 @@ namespace ICSharpCode.NRefactory.TypeSystem } } + /// + /// Same as 'parameterizedType.TypeArguments[index]', but is a bit more efficient. + /// + public IType GetTypeArgument(int index) + { + return typeArguments[index]; + } + public ITypeDefinition GetDefinition() { - return genericType; + return genericType.GetDefinition(); } public IType Resolve(ITypeResolveContext context) @@ -154,168 +161,104 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public IType SubstituteInType(IType type) { - return type.AcceptVisitor(new Substitution(typeArguments)); + return type.AcceptVisitor(new TypeParameterSubstitution(typeArguments, null)); } /// /// Gets a type visitor that performs the substitution of class type parameters with the type arguments /// of this parameterized type. /// - public TypeVisitor GetSubstitution() + public TypeParameterSubstitution GetSubstitution() + { + return new TypeParameterSubstitution(typeArguments, null); + } + + /// + /// Gets a type visitor that performs the substitution of class type parameters with the type arguments + /// of this parameterized type, + /// and also substitutes method type parameters with the specified method type arguments. + /// + public TypeParameterSubstitution GetSubstitution(IList methodTypeArguments) { - return new Substitution(typeArguments); + return new TypeParameterSubstitution(typeArguments, methodTypeArguments); } public IEnumerable GetBaseTypes(ITypeResolveContext context) { - Substitution substitution = new Substitution(typeArguments); + var substitution = GetSubstitution(); return genericType.GetBaseTypes(context).Select(t => t.AcceptVisitor(substitution)); } - public IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetNestedTypes(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - /* - class Base { - class Nested {} - } - class Derived : Base {} - - Derived.GetNestedTypes() = { Base`1+Nested } - Derived.GetNestedTypes() = { Base`1+Nested } - Base.GetNestedTypes() = { Base`1+Nested } - Base.GetNestedTypes() = { Base`1+Nested } where T2 = copy of T in Base`1+Nested - */ - Substitution substitution = new Substitution(typeArguments); - List types = genericType.GetNestedTypes(context, filter).ToList(); - for (int i = 0; i < types.Count; i++) { - ITypeDefinition def = types[i] as ITypeDefinition; - if (def != null && def.TypeParameterCount > 0) { - // (partially) parameterize the nested type definition - IType[] newTypeArgs = new IType[def.TypeParameterCount]; - for (int j = 0; j < newTypeArgs.Length; j++) { - if (i < typeArguments.Length) - newTypeArgs[j] = typeArguments[i]; - else - newTypeArgs[j] = def.TypeParameters[j]; - } - types[i] = new ParameterizedType(def, newTypeArgs); - } else { - types[i] = types[i].AcceptVisitor(substitution); - } - } - return types; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetNestedTypes(context, filter, options); + else + return GetMembersHelper.GetNestedTypes(this, context, filter, options); } - public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetNestedTypes(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - Substitution substitution = new Substitution(typeArguments); - Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List methods = genericType.GetMethods(context, filter).ToList(); - for (int i = 0; i < methods.Count; i++) { - SpecializedMethod m = new SpecializedMethod(methods[i]); - m.SetDeclaringType(this); - m.SubstituteTypes(substitutionFunc); - methods[i] = m; - } - return methods; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetNestedTypes(typeArguments, context, filter, options); + else + return GetMembersHelper.GetNestedTypes(this, typeArguments, context, filter, options); } - public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetConstructors(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.IgnoreInheritedMembers) { - Substitution substitution = new Substitution(typeArguments); - Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List methods = genericType.GetConstructors(context, filter).ToList(); - for (int i = 0; i < methods.Count; i++) { - SpecializedMethod m = new SpecializedMethod(methods[i]); - m.SetDeclaringType(this); - m.SubstituteTypes(substitutionFunc); - methods[i] = m; - } - return methods; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetConstructors(context, filter, options); + else + return GetMembersHelper.GetConstructors(this, context, filter, options); } - public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetMethods(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - Substitution substitution = new Substitution(typeArguments); - Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List properties = genericType.GetProperties(context, filter).ToList(); - for (int i = 0; i < properties.Count; i++) { - SpecializedProperty p = new SpecializedProperty(properties[i]); - p.SetDeclaringType(this); - p.SubstituteTypes(substitutionFunc); - properties[i] = p; - } - return properties; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetMethods(context, filter, options); + else + return GetMembersHelper.GetMethods(this, context, filter, options); } - public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetMethods(IList typeArguments, ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - Substitution substitution = new Substitution(typeArguments); - List fields = genericType.GetFields(context, filter).ToList(); - for (int i = 0; i < fields.Count; i++) { - SpecializedField f = new SpecializedField(fields[i]); - f.SetDeclaringType(this); - f.ReturnType = f.ReturnType.Resolve(context).AcceptVisitor(substitution); - fields[i] = f; - } - return fields; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetMethods(typeArguments, context, filter, options); + else + return GetMembersHelper.GetMethods(this, typeArguments, context, filter, options); } - public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetProperties(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - Substitution substitution = new Substitution(typeArguments); - List events = genericType.GetEvents(context, filter).ToList(); - for (int i = 0; i < events.Count; i++) { - SpecializedEvent e = new SpecializedEvent(events[i]); - e.SetDeclaringType(this); - e.ReturnType = e.ReturnType.Resolve(context).AcceptVisitor(substitution); - events[i] = e; - } - return events; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetProperties(context, filter, options); + else + return GetMembersHelper.GetProperties(this, context, filter, options); } - public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null) + public IEnumerable GetFields(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - Substitution substitution = new Substitution(typeArguments); - Func substitutionFunc = t => t.Resolve(context).AcceptVisitor(substitution); - List members = genericType.GetMembers(context, filter).ToList(); - for (int i = 0; i < members.Count; i++) { - members[i] = Specialize(members[i], substitutionFunc); - } - return members; + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetFields(context, filter, options); + else + return GetMembersHelper.GetFields(this, context, filter, options); } - IMember Specialize(IMember member, Func substitution) + public IEnumerable GetEvents(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) { - IMethod method = member as IMethod; - if (method != null) { - SpecializedMethod m = new SpecializedMethod(method); - m.SetDeclaringType(this); - m.SubstituteTypes(substitution); - return m; - } - IProperty property = member as IProperty; - if (property != null) { - SpecializedProperty p = new SpecializedProperty(property); - p.SetDeclaringType(this); - p.SubstituteTypes(substitution); - return p; - } - IField field = member as IField; - if (field != null) { - SpecializedField f = new SpecializedField(field); - f.SetDeclaringType(this); - f.ReturnType = substitution(f.ReturnType); - return f; - } - IEvent ev = member as IEvent; - if (ev != null) { - SpecializedEvent e = new SpecializedEvent(ev); - e.SetDeclaringType(this); - e.ReturnType = substitution(e.ReturnType); - return e; - } - throw new ArgumentException("Unknown member"); + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetEvents(context, filter, options); + else + return GetMembersHelper.GetEvents(this, context, filter, options); + } + + public IEnumerable GetMembers(ITypeResolveContext context, Predicate filter = null, GetMemberOptions options = GetMemberOptions.None) + { + if ((options & GetMemberOptions.ReturnMemberDefinitions) == GetMemberOptions.ReturnMemberDefinitions) + return genericType.GetMembers(context, filter, options); + else + return GetMembersHelper.GetMembers(this, context, filter, options); } public override bool Equals(object obj) @@ -379,12 +322,38 @@ namespace ICSharpCode.NRefactory.TypeSystem else return new ParameterizedType(def, ta); } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + for (int i = 0; i < typeArguments.Length; i++) { + typeArguments[i] = provider.Intern(typeArguments[i]); + } + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return GetHashCode(); + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + ParameterizedType o = other as ParameterizedType; + if (o != null && genericType == o.genericType && typeArguments.Length == o.typeArguments.Length) { + for (int i = 0; i < typeArguments.Length; i++) { + if (typeArguments[i] != o.typeArguments[i]) + return false; + } + return true; + } + return false; + } } /// /// 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) @@ -499,7 +468,6 @@ namespace ICSharpCode.NRefactory.TypeSystem return true; } return false; - } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs index 692e81479..7660dadd8 100644 --- a/ICSharpCode.NRefactory/TypeSystem/PointerType.cs +++ b/ICSharpCode.NRefactory/TypeSystem/PointerType.cs @@ -1,17 +1,38 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; using ICSharpCode.NRefactory.TypeSystem.Implementation; namespace ICSharpCode.NRefactory.TypeSystem { - public class PointerType : TypeWithElementType + [Serializable] + public sealed class PointerType : TypeWithElementType, ISupportsInterning { public PointerType(IType elementType) : base(elementType) { } + public override TypeKind Kind { + get { return TypeKind.Pointer; } + } + public override string NameSuffix { get { return "*"; @@ -47,11 +68,28 @@ namespace ICSharpCode.NRefactory.TypeSystem else return new PointerType(e); } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + elementType = provider.Intern(elementType); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return elementType.GetHashCode() ^ 91725811; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + PointerType o = other as PointerType; + return o != null && this.elementType == o.elementType; + } } - public class PointerTypeReference : ITypeReference + [Serializable] + public sealed class PointerTypeReference : ITypeReference, ISupportsInterning { - readonly ITypeReference elementType; + ITypeReference elementType; public PointerTypeReference(ITypeReference elementType) { @@ -81,5 +119,21 @@ namespace ICSharpCode.NRefactory.TypeSystem else return new PointerTypeReference(elementType); } + + void ISupportsInterning.PrepareForInterning(IInterningProvider provider) + { + elementType = provider.Intern(elementType); + } + + int ISupportsInterning.GetHashCodeForInterning() + { + return elementType.GetHashCode() ^ 91725812; + } + + bool ISupportsInterning.EqualsForInterning(ISupportsInterning other) + { + PointerTypeReference o = other as PointerTypeReference; + return o != null && this.elementType == o.elementType; + } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs index 7decbb800..809f820c6 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ReflectionHelper.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -23,6 +38,11 @@ namespace ICSharpCode.NRefactory.TypeSystem /// public sealed class Dynamic {} + /// + /// A reflection class used to represent an unbound type argument. + /// + public sealed class UnboundTypeArgument {} + #region ITypeResolveContext.GetTypeDefinition(Type) /// /// Retrieves a type definition. @@ -78,10 +98,15 @@ namespace ICSharpCode.NRefactory.TypeSystem ITypeReference def = ToTypeReference(type.GetGenericTypeDefinition(), entity); Type[] arguments = type.GetGenericArguments(); ITypeReference[] args = new ITypeReference[arguments.Length]; + bool allUnbound = true; for (int i = 0; i < arguments.Length; i++) { args[i] = ToTypeReference(arguments[i], entity); + allUnbound &= args[i].Equals(SharedTypes.UnboundTypeArgument); } - return new ParameterizedTypeReference(def, args); + if (allUnbound) + return def; + else + return new ParameterizedTypeReference(def, args); } else if (type.IsArray) { return new ArrayTypeReference(ToTypeReference(type.GetElementType(), entity), type.GetArrayRank()); } else if (type.IsPointer) { @@ -111,6 +136,8 @@ namespace ICSharpCode.NRefactory.TypeSystem return SharedTypes.Dynamic; else if (type == typeof(Null)) return SharedTypes.Null; + else if (type == typeof(UnboundTypeArgument)) + return SharedTypes.UnboundTypeArgument; ITypeReference baseTypeRef = ToTypeReference(type.DeclaringType, entity); int typeParameterCount; string name = SplitTypeParameterCountFromReflectionName(type.Name, out typeParameterCount); @@ -175,7 +202,7 @@ namespace ICSharpCode.NRefactory.TypeSystem KnownTypeReference.UInt64, KnownTypeReference.Single, KnownTypeReference.Double, - new GetClassTypeReference("System", "Decimal", 0), + KnownTypeReference.Decimal, new GetClassTypeReference("System", "DateTime", 0), SharedTypes.UnknownType, // (TypeCode)17 has no enum value? KnownTypeReference.String @@ -193,37 +220,47 @@ namespace ICSharpCode.NRefactory.TypeSystem #endregion #region GetTypeCode - static readonly Dictionary typeNameToCodeDict = new Dictionary { - { "Object", TypeCode.Object }, - { "DBNull", TypeCode.DBNull }, - { "Boolean", TypeCode.Boolean }, - { "Char", TypeCode.Char }, - { "SByte", TypeCode.SByte }, - { "Byte", TypeCode.Byte }, - { "Int16", TypeCode.Int16 }, - { "UInt16", TypeCode.UInt16 }, - { "Int32", TypeCode.Int32 }, - { "UInt32", TypeCode.UInt32 }, - { "Int64", TypeCode.Int64 }, - { "UInt64", TypeCode.UInt64 }, - { "Single", TypeCode.Single }, - { "Double", TypeCode.Double }, - { "Decimal", TypeCode.Decimal }, - { "DateTime", TypeCode.DateTime }, - { "String", TypeCode.String } + static readonly string[] typeNamesByTypeCode = { + "Void", "Object", "DBNull", "Boolean", "Char", + "SByte", "Byte", "Int16", "UInt16", "Int32", "UInt32", "Int64", "UInt64", + "Single", "Double", "Decimal", "DateTime", null, "String" }; + static readonly string[] csharpTypeNamesByTypeCode = { + "void", "object", null, "bool", "char", + "sbyte", "byte", "short", "ushort", "int", "uint", "long", "ulong", + "float", "double", "decimal", null, null, "string" + }; + + internal static int ByTypeCodeArraySize { + get { return typeNamesByTypeCode.Length; } + } + + public static string GetShortNameByTypeCode(TypeCode typeCode) + { + return typeNamesByTypeCode[(int)typeCode]; + } + + public static string GetCSharpNameByTypeCode(TypeCode typeCode) + { + return csharpTypeNamesByTypeCode[(int)typeCode]; + } + /// /// Gets the type code for the specified type, or TypeCode.Empty if none of the other type codes matches. /// public static TypeCode GetTypeCode(IType type) { ITypeDefinition def = type as ITypeDefinition; - TypeCode typeCode; - if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System" && typeNameToCodeDict.TryGetValue(def.Name, out typeCode)) - return typeCode; - else - return TypeCode.Empty; + if (def != null && def.TypeParameterCount == 0 && def.Namespace == "System") { + string[] typeNames = typeNamesByTypeCode; + string name = def.Name; + for (int i = 1; i < typeNames.Length; i++) { + if (name == typeNames[i]) + return (TypeCode)i; + } + } + return TypeCode.Empty; } #endregion diff --git a/ICSharpCode.NRefactory/TypeSystem/ReflectionNameParseException.cs b/ICSharpCode.NRefactory/TypeSystem/ReflectionNameParseException.cs index 0ef605427..4cec1c959 100644 --- a/ICSharpCode.NRefactory/TypeSystem/ReflectionNameParseException.cs +++ b/ICSharpCode.NRefactory/TypeSystem/ReflectionNameParseException.cs @@ -1,4 +1,21 @@ - +// 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.Runtime.Serialization; diff --git a/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs b/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs index f72e5fc15..6fc19ae88 100644 --- a/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs +++ b/ICSharpCode.NRefactory/TypeSystem/SharedTypes.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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 ICSharpCode.NRefactory.TypeSystem.Implementation; @@ -15,19 +30,26 @@ namespace ICSharpCode.NRefactory.TypeSystem /// Gets the type representing resolve errors. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] - public readonly static IType UnknownType = new UnknownTypeImpl(); + public readonly static IType UnknownType = new SharedTypeImpl(TypeKind.Unknown, "?", isReferenceType: null); /// /// The null type is used as type of the null literal. It is a reference type without any members; and it is a subtype of all reference types. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] - public readonly static IType Null = new NullType(); + public readonly static IType Null = new SharedTypeImpl(TypeKind.Null, "null", isReferenceType: true); /// /// Type representing the C# 'dynamic' type. /// [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] - public readonly static IType Dynamic = new DynamicType(); + public readonly static IType Dynamic = new SharedTypeImpl(TypeKind.Dynamic, "dynamic", isReferenceType: true); + + /// + /// A type used for unbound type arguments in partially parameterized types. + /// + /// + [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA2104:DoNotDeclareReadOnlyMutableReferenceTypes", Justification = "It's immutable")] + public readonly static IType UnboundTypeArgument = new SharedTypeImpl(TypeKind.UnboundTypeArgument, "", isReferenceType: null); /* * I'd like to define static instances for common types like @@ -48,78 +70,41 @@ namespace ICSharpCode.NRefactory.TypeSystem * would have to return true even though these are two distinct definitions. */ - /// - /// Type representing resolve errors. - /// - sealed class UnknownTypeImpl : AbstractType + [Serializable] + sealed class SharedTypeImpl : AbstractType { - public override string Name { - get { return "?"; } - } + readonly TypeKind kind; + readonly string name; + readonly bool? isReferenceType; - public override bool? IsReferenceType(ITypeResolveContext context) + public SharedTypeImpl(TypeKind kind, string name, bool? isReferenceType) { - return null; + this.kind = kind; + this.name = name; + this.isReferenceType = isReferenceType; } - public override bool Equals(IType other) - { - return other is UnknownTypeImpl; + public override TypeKind Kind { + get { return kind; } } - public override int GetHashCode() - { - return 950772036; - } - } - - /// - /// Type of the 'null' literal. - /// - sealed class NullType : AbstractType - { - public override string Name { - get { return "null"; } - } - - public override bool? IsReferenceType(ITypeResolveContext context) - { - return true; - } - - public override bool Equals(IType other) - { - return other is NullType; - } - - public override int GetHashCode() - { - return 362709548; - } - } - - /// - /// Type representing the C# 'dynamic' type. - /// - sealed class DynamicType : AbstractType - { public override string Name { - get { return "dynamic"; } + get { return name; } } public override bool? IsReferenceType(ITypeResolveContext context) { - return true; + return isReferenceType; } public override bool Equals(IType other) { - return other is DynamicType; + return other != null && other.Kind == kind; } public override int GetHashCode() { - return 31986112; + return (int)kind; } } } diff --git a/ICSharpCode.NRefactory/TypeSystem/TypeKind.cs b/ICSharpCode.NRefactory/TypeSystem/TypeKind.cs new file mode 100644 index 000000000..4796a25d8 --- /dev/null +++ b/ICSharpCode.NRefactory/TypeSystem/TypeKind.cs @@ -0,0 +1,81 @@ +// 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; + +namespace ICSharpCode.NRefactory.TypeSystem +{ + /// + /// . + /// + public enum TypeKind : byte + { + /// Language-specific type that is not part of NRefactory.TypeSystem itself. + Other, + + /// A or that is a class. + Class, + /// A or that is an interface. + Interface, + /// A or that is a struct. + Struct, + /// A or that is a delegate. + /// System.Delegate itself is TypeKind.Class + Delegate, + /// A that is an enum. + /// System.Enum itself is TypeKind.Class + Enum, + /// A that is a module (VB). + Module, + + /// The System.Void type. + /// + Void, + + /// + Unknown, + /// The type of the null literal. + /// + Null, + /// Type representing the C# 'dynamic' type. + /// + Dynamic, + /// Represents missing type arguments in partially parameterized types. + /// + /// + UnboundTypeArgument, + + /// The type is a type parameter. + /// + TypeParameter, + + /// An array type + /// + Array, + /// A pointer type + /// + Pointer, + /// A managed reference type + /// + ByReference, + + /// Intersection of several types + /// + Intersection + } +} diff --git a/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs b/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs index 37042842f..9bf2610a3 100644 --- a/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs +++ b/ICSharpCode.NRefactory/TypeSystem/TypeVisitor.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/Utils/7BitEncodedInts.cs b/ICSharpCode.NRefactory/Utils/7BitEncodedInts.cs new file mode 100644 index 000000000..b16047c95 --- /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 82f412407..a8b512215 100644 --- a/ICSharpCode.NRefactory/Utils/BitVector16.cs +++ b/ICSharpCode.NRefactory/Utils/BitVector16.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; @@ -8,6 +23,7 @@ namespace ICSharpCode.NRefactory.Utils /// /// Holds 16 boolean values. /// + [Serializable] public struct BitVector16 : IEquatable { ushort data; diff --git a/ICSharpCode.NRefactory/Utils/BusyManager.cs b/ICSharpCode.NRefactory/Utils/BusyManager.cs index c743b7bfd..2c7f161aa 100644 --- a/ICSharpCode.NRefactory/Utils/BusyManager.cs +++ b/ICSharpCode.NRefactory/Utils/BusyManager.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/Utils/CSharpPrimitiveCast.cs b/ICSharpCode.NRefactory/Utils/CSharpPrimitiveCast.cs index 41d9f5bff..52ca8c7dd 100644 --- a/ICSharpCode.NRefactory/Utils/CSharpPrimitiveCast.cs +++ b/ICSharpCode.NRefactory/Utils/CSharpPrimitiveCast.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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; diff --git a/ICSharpCode.NRefactory/Utils/CacheManager.cs b/ICSharpCode.NRefactory/Utils/CacheManager.cs index bfb05248e..4068522ca 100644 --- a/ICSharpCode.NRefactory/Utils/CacheManager.cs +++ b/ICSharpCode.NRefactory/Utils/CacheManager.cs @@ -1,102 +1,64 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Concurrent; +using System.Collections.Generic; using System.Threading; namespace ICSharpCode.NRefactory.Utils { /// - /// Allows the registration of static "caching types" which can then be used to efficiently retrieve an - /// instance per CacheManager (or even per CacheManager and thread). + /// Allows caching values for a specific resolve context. + /// A CacheManager consists of two dictionaries: one for shared instances (shared among all threads working with that resolve context), + /// and one for thread-local instances. + /// Additionally, it provides a Dispose() event that can be used to clear any external caches when + /// leaving the "using (var ctx = context.Synchronize())" block. /// /// This class is thread-safe public sealed class CacheManager : IDisposable { - /* Lots of code commented out because I don't know if it's useful, clients can usually replicate - * the functionality much more easily and only need the Disposed event to ensure cleanup. - * - * Actually, what I've implemented here looks very much like .NET's internal System.LocalDataStore - * (used for Thread.GetData/SetData) - * - static int nextSharedIndex, nextThreadLocalIndex; + readonly ConcurrentDictionary sharedDict = new ConcurrentDictionary(ReferenceComparer.Instance); + readonly ThreadLocal> localDict = new ThreadLocal>(() => new Dictionary(ReferenceComparer.Instance)); - /// - /// Registers a new cache type. This causes each CacheManager to allocate space for the new cache type. - /// - /// Specifies whether this cache is shared (multi-threaded) or whether - /// there is one instance per thread. - /// Returns a token that can be used to access the cache. - public static CacheToken RegisterType(CacheMode mode) where T : class, new() + public object GetShared(object key) { - int index; - switch (mode) { - case CacheMode.Shared: - index = Interlocked.Increment(ref nextSharedIndex); - break; - case CacheMode.ThreadLocal: - index = Interlocked.Increment(ref nextThreadLocalIndex); - break; - default: - throw new ArgumentException("Invalid value for CacheMode", "mode"); - } - return new CacheToken(mode, index); + object val; + sharedDict.TryGetValue(key, out val); + return val; } - readonly object lockObj = new object(); - volatile object[] _sharedCaches = new object[nextSharedIndex]; - ThreadLocal threadLocalCaches = new ThreadLocal(() => new object[nextThreadLocalIndex]); + public void SetShared(object key, object val) + { + sharedDict[key] = val; + } - /// - /// Gets the cache using the specified token. - /// - public T Get(CacheToken token) where T : class, new() + public object GetThreadLocal(object key) { - switch (token.Mode) { - case CacheMode.Shared: - object[] sharedCaches = this._sharedCaches; - if (token.Index < sharedCaches.Length) { - object c = sharedCaches[token.Index]; - if (c != null) - return (T)c; - } - // it seems like the cache doesn't exist yet, so try to create it: - T newCache = new T(); - lock (lockObj) { - sharedCaches = this._sharedCaches; // fetch fresh value after locking - // use double-checked locking - if (token.Index < sharedCaches.Length) { - object c = sharedCaches[token.Index]; - if (c != null) { - // looks like someone else was faster creating it than this thread - return (T)c; - } - } else { - Array.Resize(ref sharedCaches, nextSharedIndex); - this._sharedCaches = sharedCaches; - } - sharedCaches[token.Index] = newCache; - } - return newCache; - case CacheMode.ThreadLocal: - object[] localCaches = threadLocalCaches.Value; - if (token.Index >= localCaches.Length) { - Array.Resize(ref localCaches, nextThreadLocalIndex); - threadLocalCaches.Value = localCaches; - } - object lc = localCaches[token.Index]; - if (lc != null) { - return (T)lc; - } else { - T newLocalCache = new T(); - localCaches[token.Index] = newLocalCache; - return newLocalCache; - } - default: - throw new ArgumentException("Invalid token"); - } + object val; + localDict.Value.TryGetValue(key, out val); + return val; + } + + public void SetThreadLocal(object key, object val) + { + localDict.Value[key] = val; } - */ public event EventHandler Disposed; @@ -105,7 +67,8 @@ namespace ICSharpCode.NRefactory.Utils /// public void Dispose() { - //threadLocalCaches.Dispose(); // dispose the ThreadLocal + sharedDict.Clear(); + localDict.Dispose(); // dispose the ThreadLocal // TODO: test whether this frees the referenced value on all threads // fire Disposed() only once by removing the old event handlers @@ -114,24 +77,4 @@ namespace ICSharpCode.NRefactory.Utils disposed(this, EventArgs.Empty); } } - - /* - public enum CacheMode - { - // don't use 0 so that default(CacheToken<...>) is an invalid mode - Shared = 1, - ThreadLocal = 2 - } - - public struct CacheToken where T : class, new() - { - internal readonly CacheMode Mode; - internal readonly int Index; - - internal CacheToken(CacheMode mode, int index) - { - this.Mode = mode; - this.Index = index; - } - }*/ } diff --git a/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs b/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs deleted file mode 100644 index df2a58dea..000000000 --- a/ICSharpCode.NRefactory/Utils/DotNet35Compat.cs +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) - -using System; -using System.Collections.Generic; -using System.Linq; - -internal static class DotNet35Compat -{ - public static string StringJoin(string separator, IEnumerable elements) - { - #if DOTNET35 - return string.Join(separator, elements.Select(e => e != null ? e.ToString() : null).ToArray()); - #else - return string.Join(separator, elements); - #endif - } - - public static IEnumerable SafeCast(this IEnumerable elements) where T : class, U where U : class - { - #if DOTNET35 - foreach (T item in elements) - yield return item; - #else - return elements; - #endif - } - - public static Predicate SafeCast(this Predicate predicate) where U : class, T where T : class - { - #if DOTNET35 - return e => predicate(e); - #else - return predicate; - #endif - } - - #if DOTNET35 - public static IEnumerable Zip(this IEnumerable input1, IEnumerable input2, Func f) - { - using (var e1 = input1.GetEnumerator()) - using (var e2 = input2.GetEnumerator()) - while (e1.MoveNext() && e2.MoveNext()) - yield return f(e1.Current, e2.Current); - } - #endif -} - -#if DOTNET35 -namespace System.Diagnostics.Contracts { } -namespace System.Threading -{ - internal struct CancellationToken - { - public void ThrowIfCancellationRequested() {} - } -} -#endif diff --git a/ICSharpCode.NRefactory/Utils/EmptyList.cs b/ICSharpCode.NRefactory/Utils/EmptyList.cs index da4ac74a4..ed566005b 100644 --- a/ICSharpCode.NRefactory/Utils/EmptyList.cs +++ b/ICSharpCode.NRefactory/Utils/EmptyList.cs @@ -1,13 +1,115 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections; +using System.Collections.Generic; using System.Collections.ObjectModel; namespace ICSharpCode.NRefactory { - static class EmptyList + [Serializable] + public sealed class EmptyList : IList, IEnumerator { - public static readonly ReadOnlyCollection Instance = new ReadOnlyCollection(new T[0]); + public static readonly IList Instance = new EmptyList(); + + private EmptyList() {} + + T IList.this[int index] { + get { throw new IndexOutOfRangeException(); } + set { throw new IndexOutOfRangeException(); } + } + + int ICollection.Count { + get { return 0; } + } + + bool ICollection.IsReadOnly { + get { return true; } + } + + int IList.IndexOf(T item) + { + return -1; + } + + void IList.Insert(int index, T item) + { + throw new NotSupportedException(); + } + + void IList.RemoveAt(int index) + { + throw new NotSupportedException(); + } + + void ICollection.Add(T item) + { + throw new NotSupportedException(); + } + + void ICollection.Clear() + { + } + + bool ICollection.Contains(T item) + { + return false; + } + + void ICollection.CopyTo(T[] array, int arrayIndex) + { + } + + bool ICollection.Remove(T item) + { + return false; + } + + IEnumerator IEnumerable.GetEnumerator() + { + return this; + } + + System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() + { + return this; + } + + T IEnumerator.Current { + get { return default(T); } + } + + object IEnumerator.Current { + get { return default(T); } + } + + void IDisposable.Dispose() + { + } + + bool IEnumerator.MoveNext() + { + return false; + } + + void IEnumerator.Reset() + { + } } } diff --git a/ICSharpCode.NRefactory/Utils/ExtensionMethods.cs b/ICSharpCode.NRefactory/Utils/ExtensionMethods.cs index d720ba16f..dd7d29c41 100644 --- a/ICSharpCode.NRefactory/Utils/ExtensionMethods.cs +++ b/ICSharpCode.NRefactory/Utils/ExtensionMethods.cs @@ -1,5 +1,20 @@ -// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; @@ -16,5 +31,14 @@ namespace ICSharpCode.NRefactory.Utils foreach (T item in input) target.Add(item); } + + public static Predicate And(this Predicate filter1, Predicate filter2) + { + if (filter1 == null) + return filter2; + if (filter2 == null) + return filter1; + return m => filter1(m) && filter2(m); + } } } diff --git a/ICSharpCode.NRefactory/Utils/FastSerializer.cs b/ICSharpCode.NRefactory/Utils/FastSerializer.cs new file mode 100644 index 000000000..9a14c0331 --- /dev/null +++ b/ICSharpCode.NRefactory/Utils/FastSerializer.cs @@ -0,0 +1,1334 @@ +// 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.Reflection; +using System.Reflection.Emit; +using System.Runtime.Serialization; + +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; } + + /// + /// Can be used to set several 'fixed' instances. + /// When serializing, such instances will not be included; and any references to a fixed instance + /// will be stored as the index in this array. + /// When deserializing, the same (or equivalent) instances must be specified, and the deserializer + /// will use them in place of the fixed instances. + /// + public object[] FixedInstances { get; set; } + #endregion + + #region Constants + const int magic = 0x71D28A5D; + + 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 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(ReferenceComparer.Instance); + readonly List instances = new List(); // index: object ID + readonly List objectTypes = new List(); // index: object ID + SerializationType stringType; + + 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; + int fixedInstanceCount; + + internal SerializationContext(FastSerializer fastSerializer, BinaryWriter writer) + { + this.fastSerializer = fastSerializer; + this.writer = writer; + instances.Add(null); // use object ID 0 for null + objectTypes.Add(null); + } + + #region Scanning + public void MarkFixedInstances(object[] fixedInstances) + { + if (fixedInstances == null) + return; + foreach (object obj in fixedInstances) { + if (!objectToID.ContainsKey(obj)) { + objectToID.Add(obj, instances.Count); + instances.Add(obj); + fixedInstanceCount++; + } + } + } + + /// + /// 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..."); + // starting from 1, because index 0 is null + // Also, do not scan any of the 'fixed instances'. + for (int i = 1 + fixedInstanceCount; i < instances.Count; i++) { + object instance = instances[i]; + ISerializable serializable = instance as ISerializable; + Type type = instance.GetType(); + Log("Scan #{0}: {1}", i, type.Name); + SerializationType sType = MarkType(type); + objectTypes.Add(sType); + 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); + } + sType.Writer = serializationInfoWriter; + } else { + 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) { + Debug.Assert(type.IsArray); + 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() + { + for (int i = 0; i < types.Count; i++) { + 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); + } + } + } + #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); + } + + 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(instances.Count); + writer.Write(types.Count); + writer.Write(assemblyNames.Count); + writer.Write(fixedInstanceCount); + + foreach (string assemblyName in assemblyNames) { + writer.Write(assemblyName); + } + + 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); + if (fields.Count >= byte.MaxValue) + throw new SerializationException("Too many fields."); + writer.Write((byte)fields.Count); + foreach (var field in fields) { + WriteTypeID(field.FieldType); + writer.Write(field.Name); + } + } + } + + // Write out information necessary to create the instances + // starting from 1, because index 0 is null + for (int i = 1 + fixedInstanceCount; i < instances.Count; i++) { + SerializationType sType = objectTypes[i]; + if (types.Count <= ushort.MaxValue) + writer.Write((ushort)sType.ID); + else + 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 (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 + fixedInstanceCount; i < instances.Count; 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."); + } + #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 BinaryWriterWith7BitEncodedInts(stream), instance); + } + + public void Serialize(BinaryWriter writer, object instance) + { + SerializationContext context = new SerializationContext(this, writer); + context.MarkFixedInstances(this.FixedInstances); + context.Mark(instance); + context.Scan(); + context.ScanTypes(); + context.Write(); + context.WriteObjectID(instance); + } + + delegate void TypeSerializer(object instance, SerializationContext context); + #endregion + + #region Deserialization + sealed class DeserializationContext + { + public Type[] Types; // 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 ReadTypeID() + { + 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]; + if (type.IsGenericTypeDefinition || type.HasElementType) + continue; + bool isCustomSerialization = typeof(ISerializable).IsAssignableFrom(type); + bool typeIsSpecial = 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 = ReadTypeID(); + + 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); + } + } + } + } + #endregion + } + + delegate void ObjectReader(DeserializationContext context, object instance); + + public object Deserialize(Stream stream) + { + return Deserialize(new BinaryReaderWith7BitEncodedInts(stream)); + } + + 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.Objects = new object[reader.ReadInt32()]; + context.Types = new Type[reader.ReadInt32()]; + string[] assemblyNames = new string[reader.ReadInt32()]; + int fixedInstanceCount = reader.ReadInt32(); + + if (fixedInstanceCount != 0) { + if (this.FixedInstances == null || this.FixedInstances.Length != fixedInstanceCount) + throw new SerializationException("Number of fixed instances doesn't match"); + for (int i = 0; i < fixedInstanceCount; i++) { + context.Objects[i + 1] = this.FixedInstances[i]; + } + } + + for (int i = 0; i < assemblyNames.Length; i++) { + assemblyNames[i] = reader.ReadString(); + } + int stringTypeID = -1; + for (int i = 0; i < context.Types.Length; i++) { + 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 + fixedInstanceCount; i < context.Objects.Length; i++) { + int typeID = context.ReadTypeID(); + + 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(); + ObjectReader[] objectReaders = new ObjectReader[context.Types.Length]; // index: type ID + for (int i = 1 + fixedInstanceCount; 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 { + 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); + foreach (CustomDeserialization customDeserializaton in customDeserializatons) { + customDeserializaton.Run(streamingContext); + } + for (int i = 1 + fixedInstanceCount; i < context.Objects.Length; i++) { + IDeserializationCallback dc = context.Objects[i] as IDeserializationCallback; + if (dc != null) + dc.OnDeserialization(null); + } + + return context.ReadObject(); + } + + #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); + } + } +} diff --git a/ICSharpCode.NRefactory/Utils/GraphVizGraph.cs b/ICSharpCode.NRefactory/Utils/GraphVizGraph.cs index 2bf93c353..880a4c2df 100644 --- a/ICSharpCode.NRefactory/Utils/GraphVizGraph.cs +++ b/ICSharpCode.NRefactory/Utils/GraphVizGraph.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/ICSharpCode.NRefactory/Utils/Platform.cs b/ICSharpCode.NRefactory/Utils/Platform.cs index 1e512330d..ff6a5f2a2 100644 --- a/ICSharpCode.NRefactory/Utils/Platform.cs +++ b/ICSharpCode.NRefactory/Utils/Platform.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT license (for details please see \doc\license.txt) +// 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; @@ -8,7 +23,7 @@ namespace ICSharpCode.NRefactory.Utils /// /// Platform-specific code. /// - static class Platform + public static class Platform { public static StringComparer FileNameComparer { get { diff --git a/ICSharpCode.NRefactory/Utils/ReferenceComparer.cs b/ICSharpCode.NRefactory/Utils/ReferenceComparer.cs new file mode 100644 index 000000000..9e0e3b0df --- /dev/null +++ b/ICSharpCode.NRefactory/Utils/ReferenceComparer.cs @@ -0,0 +1,39 @@ +// 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.Collections.Generic; +using System.Runtime.CompilerServices; + +namespace ICSharpCode.NRefactory.Utils +{ + sealed class ReferenceComparer : IEqualityComparer + { + public readonly static ReferenceComparer Instance = new ReferenceComparer(); + + public new bool Equals(object a, object b) + { + return a == b; + } + + public int GetHashCode(object obj) + { + return RuntimeHelpers.GetHashCode(obj); + } + } +} diff --git a/ICSharpCode.NRefactory/Utils/TreeTraversal.cs b/ICSharpCode.NRefactory/Utils/TreeTraversal.cs index 4e1b238ac..219927fc0 100644 --- a/ICSharpCode.NRefactory/Utils/TreeTraversal.cs +++ b/ICSharpCode.NRefactory/Utils/TreeTraversal.cs @@ -1,5 +1,20 @@ -// Copyright (c) 2010 AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt) -// This code is distributed under MIT X11 license (for details please see \doc\license.txt) +// 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.Collections.Generic; diff --git a/NRefactory.sln b/NRefactory.sln index baf2f03d5..5052f8973 100644 --- a/NRefactory.sln +++ b/NRefactory.sln @@ -1,9 +1,9 @@  Microsoft Visual Studio Solution File, Format Version 11.00 # Visual Studio 2010 -# SharpDevelop 4.1.0.7590-alpha +# SharpDevelop 4.1.0.7887-beta Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{DC98210E-1646-483B-819A-2BB8272461E4}" - ProjectSection(SolutionItems) = postProject + ProjectSection(SolutionItems) = preProject README = README doc\TODO = doc\TODO EndProjectSection @@ -14,70 +14,71 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Test EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.VB", "ICSharpCode.NRefactory.VB\ICSharpCode.NRefactory.VB.csproj", "{7B82B671-419F-45F4-B778-D9286F996EFA}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.VB.Tests", "ICSharpCode.NRefactory.VB.Tests\ICSharpCode.NRefactory.VB.Tests.csproj", "{870115DD-960A-4406-A6B9-600BCDC36A03}" -EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Mono.Cecil", "..\Mono.Cecil\Mono.Cecil.csproj", "{D68133BD-1E63-496E-9EDE-4FBDBF77B486}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.Demo", "ICSharpCode.NRefactory.Demo\ICSharpCode.NRefactory.Demo.csproj", "{9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.Editor", "ICSharpCode.Editor\ICSharpCode.Editor.csproj", "{F054A788-B591-4561-A8BA-AE745BBEB817}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ICSharpCode.NRefactory.CSharp", "ICSharpCode.NRefactory.CSharp\ICSharpCode.NRefactory.CSharp.csproj", "{53DCA265-3C3C-42F9-B647-F72BA678122B}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|x86.ActiveCfg = Debug|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Debug|x86.Build.0 = Debug|Any CPU {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.ActiveCfg = Release|Any CPU {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|Any CPU.Build.0 = Release|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|x86.ActiveCfg = Release|Any CPU + {3B2A5653-EC97-4001-BB9B-D90F1AF2C371}.Release|x86.Build.0 = Release|Any CPU {63D3B27A-D966-4902-90B3-30290E1692F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {63D3B27A-D966-4902-90B3-30290E1692F1}.Debug|Any CPU.Build.0 = Debug|Any CPU + {63D3B27A-D966-4902-90B3-30290E1692F1}.Debug|x86.ActiveCfg = Debug|x86 + {63D3B27A-D966-4902-90B3-30290E1692F1}.Debug|x86.Build.0 = Debug|x86 {63D3B27A-D966-4902-90B3-30290E1692F1}.Release|Any CPU.ActiveCfg = Release|Any CPU {63D3B27A-D966-4902-90B3-30290E1692F1}.Release|Any CPU.Build.0 = Release|Any CPU - {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|Any CPU.Build.0 = Debug|x86 - {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|Any CPU.ActiveCfg = Debug|x86 - {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|x86.Build.0 = Debug|x86 - {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|x86.ActiveCfg = Debug|x86 - {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|Any CPU.Build.0 = Release|x86 - {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|Any CPU.ActiveCfg = Release|x86 - {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|x86.Build.0 = Release|x86 - {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|x86.ActiveCfg = Release|x86 - {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|Any CPU.Build.0 = Debug|Any CPU - {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|x86.Build.0 = Debug|Any CPU - {870115DD-960A-4406-A6B9-600BCDC36A03}.Debug|x86.ActiveCfg = Debug|Any CPU - {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|Any CPU.Build.0 = Release|Any CPU - {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|Any CPU.ActiveCfg = Release|Any CPU - {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|x86.Build.0 = Release|Any CPU - {870115DD-960A-4406-A6B9-600BCDC36A03}.Release|x86.ActiveCfg = Release|Any CPU + {63D3B27A-D966-4902-90B3-30290E1692F1}.Release|x86.ActiveCfg = Release|x86 + {63D3B27A-D966-4902-90B3-30290E1692F1}.Release|x86.Build.0 = Release|x86 + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|x86.ActiveCfg = Debug|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Debug|x86.Build.0 = Debug|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|Any CPU.Build.0 = Release|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|x86.ActiveCfg = Release|Any CPU + {7B82B671-419F-45F4-B778-D9286F996EFA}.Release|x86.Build.0 = Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_4_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|Any CPU.ActiveCfg = net_3_5_Debug|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_4_0_Debug|Any CPU {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Debug|x86.ActiveCfg = net_3_5_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_3_5_Release|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_4_0_Debug|Any CPU - {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_3_5_Release|Any CPU - {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|Any CPU.Build.0 = Debug|x86 - {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|Any CPU.ActiveCfg = Debug|x86 - {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|x86.Build.0 = Debug|x86 + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|Any CPU.Build.0 = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.ActiveCfg = net_4_0_Release|Any CPU + {D68133BD-1E63-496E-9EDE-4FBDBF77B486}.Release|x86.Build.0 = net_4_0_Release|Any CPU + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|Any CPU.Build.0 = Debug|Any CPU {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|x86.ActiveCfg = Debug|x86 - {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|Any CPU.Build.0 = Release|x86 - {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|Any CPU.ActiveCfg = Release|x86 - {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|x86.Build.0 = Release|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Debug|x86.Build.0 = Debug|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|Any CPU.Build.0 = Release|Any CPU {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|x86.ActiveCfg = Release|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|Any CPU.Build.0 = Debug|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|Any CPU.ActiveCfg = Debug|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|x86.Build.0 = Debug|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Debug|x86.ActiveCfg = Debug|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|Any CPU.Build.0 = Release|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|Any CPU.ActiveCfg = Release|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|x86.Build.0 = Release|x86 - {F054A788-B591-4561-A8BA-AE745BBEB817}.Release|x86.ActiveCfg = Release|x86 + {9C19E629-C93E-4ACB-9A4B-13072B5AEF9D}.Release|x86.Build.0 = Release|x86 + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Debug|x86.Build.0 = Debug|Any CPU + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Debug|x86.ActiveCfg = Debug|Any CPU + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Release|Any CPU.Build.0 = Release|Any CPU + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Release|x86.Build.0 = Release|Any CPU + {53DCA265-3C3C-42F9-B647-F72BA678122B}.Release|x86.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = ICSharpCode.NRefactory\ICSharpCode.NRefactory.csproj diff --git a/doc/TODO b/doc/TODO index 1b43f8b85..0e9a61a36 100644 --- a/doc/TODO +++ b/doc/TODO @@ -21,4 +21,21 @@ Features: - Extract Method refactoring For integration into SharpDevelop: -- Review NR and DOM changes done in the timeframe \ No newline at end of file +- Review NR and DOM changes done in the timeframe + + + +Idea for automated testing of the NR resolver: + +Given some source code + the references, + Compile source code with MS C# Compiler + Load references into NR.TypeSystem + Load source code into NR.TypeSystem + Load compiled assembly into NR.TypeSystem + Compare entities 3a. and 3b. (but ignore compiled-generated members - ILSpy has logic to detect those) + For each method: + Resolve whole method with ResolveVisitor + Ensure there are no errors detected + Extract list of methods being called (incl. op_Implicit etc.) + Compare with methods being called in compiled assembly. (also compare type arguments) +